From f87ab53b9bdbf0a712c74ec235d63029a51f9503 Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 9 Nov 2014 21:57:16 +0100 Subject: [PATCH] Try original and inferred MIME type to find best viewer for attachment In order for Android to find apps that are capable of opening an attachment for viewing the ACTION_VIEW Intent needs to contain an appropriate MIME type. Ideally, we'd use the MIME type specified for the attachment in the message. But often the supplied MIME type is wrong/useless. So we look at the file extension to try to come up with a sensible MIME type on our own. We then go on to ask Android which of the two MIME types leads to more apps claiming to be able to open our attachment for viewing and use that one. --- src/com/fsck/k9/view/AttachmentView.java | 49 ++++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java index 35740beeb..bf1a918b6 100644 --- a/src/com/fsck/k9/view/AttachmentView.java +++ b/src/com/fsck/k9/view/AttachmentView.java @@ -6,9 +6,13 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.List; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; @@ -111,10 +115,11 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo private boolean extractAttachmentInformation(Part part) throws MessagingException { boolean firstClassAttachment = true; - contentType = MimeUtility.unfoldAndDecode(part.getContentType()); + contentType = part.getMimeType(); + String contentTypeHeader = MimeUtility.unfoldAndDecode(part.getContentType()); String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition()); - name = MimeUtility.getHeaderParameter(contentType, "name"); + name = MimeUtility.getHeaderParameter(contentTypeHeader, "name"); if (name == null) { name = MimeUtility.getHeaderParameter(contentDisposition, "filename"); } @@ -141,7 +146,6 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo } catch (NumberFormatException e) { /* ignore */ } } - contentType = MimeUtility.getMimeTypeForViewing(part.getMimeType(), name); return firstClassAttachment; } @@ -239,12 +243,10 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo } public void showFile() { - Uri uri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId()); - Intent intent = createViewIntentForContentUri(contentType, uri); - + Intent intent = constructViewIntent(); try { context.startActivity(intent); - } catch (Exception e) { + } 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); @@ -252,6 +254,30 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo } } + private Intent constructViewIntent() { + Intent intent; + Uri uri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId()); + + Intent originalMimeTypeIntent = createViewIntentForContentUri(contentType, uri); + int originalMimeTypeActivitiesCount = getResolvedIntentActivitiesCount(originalMimeTypeIntent); + + String inferredMimeType = MimeUtility.getMimeTypeByExtension(name); + if (inferredMimeType.equals(contentType)) { + intent = originalMimeTypeIntent; + } else { + Intent inferredMimeTypeIntent = createViewIntentForContentUri(inferredMimeType, uri); + int inferredMimeTypeActivitiesCount = getResolvedIntentActivitiesCount(inferredMimeTypeIntent); + + if (inferredMimeTypeActivitiesCount > originalMimeTypeActivitiesCount) { + intent = inferredMimeTypeIntent; + } else { + intent = originalMimeTypeIntent; + } + } + + return intent; + } + private Intent createViewIntentForContentUri(String mimeType, Uri uri) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(uri, mimeType); @@ -260,6 +286,15 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo return intent; } + private int getResolvedIntentActivitiesCount(Intent intent) { + PackageManager packageManager = context.getPackageManager(); + + List resolveInfos = + packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + + return resolveInfos.size(); + } + private void displayAttachmentSavedMessage(final String filename) { String message = context.getString(R.string.message_view_status_attachment_saved, filename); displayMessageToUser(message);