/** * Returns the mime type for a given attachment. There are three possible results: - If thumbnail * Uri, always returns "image/png" (even if there's no attachment) - If the attachment does not * exist, returns null - Returns the mime type of the attachment */ @Override public String getType(Uri uri) { long callingId = Binder.clearCallingIdentity(); try { List<String> segments = uri.getPathSegments(); String id = segments.get(1); int match = sURIMatcher.match(uri); String format = (match == ATTACHMENTS_CACHED_FILE_ACCESS) ? null : segments.get(2); if (AttachmentUtilities.FORMAT_THUMBNAIL.equals(format)) { return "image/png"; } else { uri = (match == ATTACHMENTS_CACHED_FILE_ACCESS) ? rebuildUri(uri) : ContentUris.withAppendedId(Attachment.CONTENT_URI, Long.parseLong(id)); Cursor c = getContext().getContentResolver().query(uri, MIME_TYPE_PROJECTION, null, null, null); try { if (c.moveToFirst()) { String mimeType = c.getString(MIME_TYPE_COLUMN_MIME_TYPE); String fileName = c.getString(MIME_TYPE_COLUMN_FILENAME); mimeType = AttachmentUtilities.inferMimeType(fileName, mimeType); return mimeType; } } finally { c.close(); } return null; } } finally { Binder.restoreCallingIdentity(callingId); } }
/** * Open an attachment file. There are two "formats" - "raw", which returns an actual file, and * "thumbnail", which attempts to generate a thumbnail image. * * <p>Thumbnails are cached for easy space recovery and cleanup. * * <p>TODO: The thumbnail format returns null for its failure cases, instead of throwing * FileNotFoundException, and should be fixed for consistency. * * @throws FileNotFoundException */ @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { int match = sURIMatcher.match(uri); if (match == ATTACHMENTS_CACHED_FILE_ACCESS) { long callingId = Binder.clearCallingIdentity(); try { return getContext().getContentResolver().openFileDescriptor(rebuildUri(uri), "r"); } finally { Binder.restoreCallingIdentity(callingId); } } // If this is a write, the caller must have the EmailProvider permission, which is // based on signature only if (mode.equals("w")) { Context context = getContext(); if (context.checkCallingOrSelfPermission(EmailContent.PROVIDER_PERMISSION) != PackageManager.PERMISSION_GRANTED) { throw new FileNotFoundException(); } List<String> segments = uri.getPathSegments(); String accountId = segments.get(0); String id = segments.get(1); File saveIn = AttachmentUtilities.getAttachmentDirectory(context, Long.parseLong(accountId)); if (!saveIn.exists()) { saveIn.mkdirs(); } File newFile = new File(saveIn, id); return ParcelFileDescriptor.open( newFile, ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_TRUNCATE); } long callingId = Binder.clearCallingIdentity(); try { List<String> segments = uri.getPathSegments(); String accountId = segments.get(0); String id = segments.get(1); String format = segments.get(2); if (AttachmentUtilities.FORMAT_THUMBNAIL.equals(format)) { int width = Integer.parseInt(segments.get(3)); int height = Integer.parseInt(segments.get(4)); String filename = "thmb_" + accountId + "_" + id; File dir = getContext().getCacheDir(); File file = new File(dir, filename); if (!file.exists()) { Uri attachmentUri = AttachmentUtilities.getAttachmentUri(Long.parseLong(accountId), Long.parseLong(id)); Cursor c = query(attachmentUri, new String[] {Columns.DATA}, null, null, null); if (c != null) { try { if (c.moveToFirst()) { attachmentUri = Uri.parse(c.getString(0)); } else { return null; } } finally { c.close(); } } String type = getContext().getContentResolver().getType(attachmentUri); try { InputStream in = getContext().getContentResolver().openInputStream(attachmentUri); Bitmap thumbnail = createThumbnail(type, in); if (thumbnail == null) { return null; } thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true); FileOutputStream out = new FileOutputStream(file); thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out); out.close(); in.close(); } catch (IOException ioe) { LogUtils.d(Logging.LOG_TAG, "openFile/thumbnail failed with " + ioe.getMessage()); return null; } catch (OutOfMemoryError oome) { LogUtils.d(Logging.LOG_TAG, "openFile/thumbnail failed with " + oome.getMessage()); return null; } } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); } else { return ParcelFileDescriptor.open( new File(getContext().getDatabasePath(accountId + ".db_att"), id), ParcelFileDescriptor.MODE_READ_ONLY); } } finally { Binder.restoreCallingIdentity(callingId); } }