1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-23 18:02:15 -05:00

If we can't find an app to view an attachment try again with a file:// URI

Sadly, some apps only support the 'file' scheme in their intent filters. Among
them is Android's own package installer.
This commit is contained in:
cketti 2014-11-10 05:37:22 +01:00
parent 44ecf5d588
commit 6a1905b7b7

View File

@ -223,16 +223,10 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
*/ */
public void writeFile(File directory) { public void writeFile(File directory) {
try { try {
String filename = Utility.sanitizeFilename(name); File file = writeAttachmentToStorage(directory);
File file = Utility.createUniqueFile(directory, filename);
Uri uri = AttachmentProvider.getAttachmentUri(account, part.getAttachmentId());
InputStream in = context.getContentResolver().openInputStream(uri);
OutputStream out = new FileOutputStream(file);
IOUtils.copy(in, out);
out.flush();
out.close();
in.close();
displayAttachmentSavedMessage(file.toString()); displayAttachmentSavedMessage(file.toString());
new MediaScannerNotifier(context, file); new MediaScannerNotifier(context, file);
} catch (IOException ioe) { } catch (IOException ioe) {
if (K9.DEBUG) { if (K9.DEBUG) {
@ -242,20 +236,55 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
} }
} }
public void showFile() { private File writeAttachmentToStorage(File directory) throws IOException {
Intent intent = constructViewIntent(); String filename = Utility.sanitizeFilename(name);
File file = Utility.createUniqueFile(directory, filename);
Uri uri = AttachmentProvider.getAttachmentUri(account, part.getAttachmentId());
InputStream in = context.getContentResolver().openInputStream(uri);
try { try {
context.startActivity(intent); OutputStream out = new FileOutputStream(file);
} catch (ActivityNotFoundException e) { try {
Log.e(K9.LOG_TAG, "Could not display attachment of type " + contentType, e); IOUtils.copy(in, out);
out.flush();
} finally {
out.close();
}
} finally {
in.close();
}
String message = context.getString(R.string.message_view_no_viewer, contentType); return file;
displayMessageToUser(message); }
public void showFile() {
new ViewAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private Intent getBestViewIntentAndSaveFileIfNecessary() {
IntentAndResolvedActivitiesCount resultForContentUri = getBestViewIntentForContentUri();
if (resultForContentUri.getActivitiesCount() > 0) {
return resultForContentUri.getIntent();
}
IntentAndResolvedActivitiesCount resultForFileUri = getBestViewIntentForFileUri();
if (resultForFileUri.getActivitiesCount() > 0) {
try {
File file = writeAttachmentToStorage(new File(K9.getAttachmentDefaultPath()));
return createViewIntentForFileUri(resultForFileUri.getMimeType(), Uri.fromFile(file));
} catch (IOException e) {
if (K9.DEBUG) {
Log.e(K9.LOG_TAG, "Error while saving attachment to use file:// URI with ACTION_VIEW Intent", e);
}
} }
} }
private Intent constructViewIntent() { return resultForContentUri.getIntent();
}
private IntentAndResolvedActivitiesCount getBestViewIntentForContentUri() {
Intent intent; Intent intent;
int activitiesCount;
Uri originalMimeTypeUri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId(), Uri originalMimeTypeUri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId(),
contentType); contentType);
@ -265,6 +294,7 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
String inferredMimeType = MimeUtility.getMimeTypeByExtension(name); String inferredMimeType = MimeUtility.getMimeTypeByExtension(name);
if (inferredMimeType.equals(contentType)) { if (inferredMimeType.equals(contentType)) {
intent = originalMimeTypeIntent; intent = originalMimeTypeIntent;
activitiesCount = originalMimeTypeActivitiesCount;
} else { } else {
Uri inferredMimeTypeUri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId(), Uri inferredMimeTypeUri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId(),
inferredMimeType); inferredMimeType);
@ -273,22 +303,67 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
if (inferredMimeTypeActivitiesCount > originalMimeTypeActivitiesCount) { if (inferredMimeTypeActivitiesCount > originalMimeTypeActivitiesCount) {
intent = inferredMimeTypeIntent; intent = inferredMimeTypeIntent;
activitiesCount = inferredMimeTypeActivitiesCount;
} else { } else {
intent = originalMimeTypeIntent; intent = originalMimeTypeIntent;
activitiesCount = originalMimeTypeActivitiesCount;
} }
} }
return intent; return new IntentAndResolvedActivitiesCount(intent, activitiesCount);
}
private IntentAndResolvedActivitiesCount getBestViewIntentForFileUri() {
Intent intent;
int activitiesCount;
File dummyFile = new File(Utility.sanitizeFilename(name));
Uri fileUri = Uri.fromFile(dummyFile);
Intent originalMimeTypeIntent = createViewIntentForFileUri(contentType, fileUri);
int originalMimeTypeActivitiesCount = getResolvedIntentActivitiesCount(originalMimeTypeIntent);
String inferredMimeType = MimeUtility.getMimeTypeByExtension(name);
if (inferredMimeType.equals(contentType)) {
intent = originalMimeTypeIntent;
activitiesCount = originalMimeTypeActivitiesCount;
} else {
Intent inferredMimeTypeIntent = createViewIntentForFileUri(inferredMimeType, fileUri);
int inferredMimeTypeActivitiesCount = getResolvedIntentActivitiesCount(inferredMimeTypeIntent);
if (inferredMimeTypeActivitiesCount > originalMimeTypeActivitiesCount) {
intent = inferredMimeTypeIntent;
activitiesCount = inferredMimeTypeActivitiesCount;
} else {
intent = originalMimeTypeIntent;
activitiesCount = originalMimeTypeActivitiesCount;
}
}
return new IntentAndResolvedActivitiesCount(intent, activitiesCount);
} }
private Intent createViewIntentForContentUri(String mimeType, Uri uri) { private Intent createViewIntentForContentUri(String mimeType, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType); intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
addUiIntentFlags(intent);
return intent; return intent;
} }
private Intent createViewIntentForFileUri(String mimeType, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType);
addUiIntentFlags(intent);
return intent;
}
private void addUiIntentFlags(Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
}
private int getResolvedIntentActivitiesCount(Intent intent) { private int getResolvedIntentActivitiesCount(Intent intent) {
PackageManager packageManager = context.getPackageManager(); PackageManager packageManager = context.getPackageManager();
@ -328,6 +403,28 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
} }
private static class IntentAndResolvedActivitiesCount {
private Intent intent;
private int activitiesCount;
IntentAndResolvedActivitiesCount(Intent intent, int activitiesCount) {
this.intent = intent;
this.activitiesCount = activitiesCount;
}
public Intent getIntent() {
return intent;
}
public int getActivitiesCount() {
return activitiesCount;
}
public String getMimeType() {
return intent.getType();
}
}
private class LoadAndDisplayThumbnailAsyncTask extends AsyncTask<Void, Void, Bitmap> { private class LoadAndDisplayThumbnailAsyncTask extends AsyncTask<Void, Void, Bitmap> {
private final ImageView thumbnail; private final ImageView thumbnail;
@ -364,4 +461,34 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
} }
} }
} }
private class ViewAttachmentAsyncTask extends AsyncTask<Void, Void, Intent> {
@Override
protected void onPreExecute() {
viewButton.setEnabled(false);
}
@Override
protected Intent doInBackground(Void... params) {
return getBestViewIntentAndSaveFileIfNecessary();
}
@Override
protected void onPostExecute(Intent intent) {
viewAttachment(intent);
viewButton.setEnabled(true);
}
private void viewAttachment(Intent intent) {
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(K9.LOG_TAG, "Could not display attachment of type " + contentType, e);
String message = context.getString(R.string.message_view_no_viewer, contentType);
displayMessageToUser(message);
}
}
}
} }