/** Save the body part of a single attachment, to a file in the attachments directory. */ public static void saveAttachmentBody( final Context context, final Part part, final Attachment localAttachment, long accountId) throws MessagingException, IOException { if (part.getBody() != null) { final long attachmentId = localAttachment.mId; final File saveIn = AttachmentUtilities.getAttachmentDirectory(context, accountId); if (!saveIn.isDirectory() && !saveIn.mkdirs()) { throw new IOException("Could not create attachment directory"); } final File saveAs = AttachmentUtilities.getAttachmentFilename(context, accountId, attachmentId); InputStream in = null; FileOutputStream out = null; final long copySize; try { in = part.getBody().getInputStream(); out = new FileOutputStream(saveAs); copySize = IOUtils.copyLarge(in, out); } finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } // update the attachment with the extra information we now know final String contentUriString = AttachmentUtilities.getAttachmentUri(accountId, attachmentId).toString(); localAttachment.mSize = copySize; localAttachment.setContentUri(contentUriString); // update the attachment in the database as well final ContentValues cv = new ContentValues(3); cv.put(AttachmentColumns.SIZE, copySize); cv.put(AttachmentColumns.CONTENT_URI, contentUriString); cv.put(AttachmentColumns.UI_STATE, UIProvider.AttachmentState.SAVED); final Uri uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, attachmentId); context.getContentResolver().update(uri, cv, null, null); } }
/** * 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); } }