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.
This commit is contained in:
cketti 2014-11-09 21:57:16 +01:00
parent 11a9eff109
commit f87ab53b9b

View file

@ -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<ResolveInfo> 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);