Handle inline images in EmailProvider

* Automatically prefetch these attachments
* Use AttachmentProvider properly (to get output stream)

Bug: 6437156
Change-Id: I6f594e3b9b6286cb19d7fb7390aa6979ba492c22
This commit is contained in:
Marc Blank 2012-05-29 08:46:17 -07:00
parent cf1a862526
commit 21102f6323
3 changed files with 40 additions and 21 deletions

View File

@ -32,6 +32,8 @@ import android.webkit.MimeTypeMap;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.provider.EmailContent.AttachmentColumns;
import com.android.emailcommon.provider.EmailContent.Body;
import com.android.emailcommon.provider.EmailContent.BodyColumns;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.MessageColumns;
import com.android.mail.providers.UIProvider;
@ -42,6 +44,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class AttachmentUtilities {
public static final String AUTHORITY = "com.android.email.attachmentprovider";
@ -361,8 +364,7 @@ public class AttachmentUtilities {
}
}
private static long copyFile(InputStream in, File file) throws IOException {
FileOutputStream out = new FileOutputStream(file);
private static long copyFile(InputStream in, OutputStream out) throws IOException {
long size = IOUtils.copy(in, out);
in.close();
out.flush();
@ -378,24 +380,20 @@ public class AttachmentUtilities {
ContentValues cv = new ContentValues();
long attachmentId = attachment.mId;
long accountId = attachment.mAccountKey;
String contentUri;
String contentUri = null;
long size;
try {
ContentResolver resolver = context.getContentResolver();
if (attachment.mUiDestination == UIProvider.AttachmentDestination.CACHE) {
File saveIn = getAttachmentDirectory(context, accountId);
if (!saveIn.exists()) {
saveIn.mkdirs();
}
File file = getAttachmentFilename(context, accountId, attachmentId);
file.createNewFile();
size = copyFile(in, file);
contentUri = getAttachmentUri(accountId, attachmentId).toString();
Uri attUri = getAttachmentUri(accountId, attachmentId);
size = copyFile(in, resolver.openOutputStream(attUri));
contentUri = attUri.toString();
} else if (Utility.isExternalStorageMounted()) {
File downloads = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS);
downloads.mkdirs();
File file = Utility.createUniqueFile(downloads, attachment.mFileName);
size = copyFile(in, file);
size = copyFile(in, new FileOutputStream(file));
String absolutePath = file.getAbsolutePath();
// Although the download manager can scan media files, scanning only happens
@ -428,5 +426,20 @@ public class AttachmentUtilities {
}
context.getContentResolver().update(uri, cv, null, null);
// If this is an inline attachment, update the body
if (contentUri != null && attachment.mContentId != null) {
Body body = Body.restoreBodyWithMessageId(context, attachment.mMessageKey);
if (body != null && body.mHtmlContent != null) {
cv.clear();
String html = body.mHtmlContent;
String contentIdRe =
"\\s+(?i)src=\"cid(?-i):\\Q" + attachment.mContentId + "\\E\"";
String srcContentUri = " src=\"" + contentUri + "\"";
html = html.replaceAll(contentIdRe, srcContentUri);
cv.put(BodyColumns.HTML_CONTENT, html);
context.getContentResolver().update(
ContentUris.withAppendedId(Body.CONTENT_URI, body.mId), cv, null, null);
}
}
}
}

View File

@ -2333,6 +2333,9 @@ outer:
ArrayList<com.android.mail.providers.Attachment> uiAtts =
new ArrayList<com.android.mail.providers.Attachment>();
for (Attachment att : atts) {
if (att.mContentId != null && att.mContentUri != null) {
continue;
}
com.android.mail.providers.Attachment uiAtt =
new com.android.mail.providers.Attachment();
uiAtt.name = att.mFileName;

View File

@ -352,25 +352,28 @@ public class AttachmentDownloadService extends Service implements Runnable {
// We'll load up the newest 25 attachments that aren't loaded or queued
Uri lookupUri = EmailContent.uriWithLimit(Attachment.CONTENT_URI,
MAX_ATTACHMENTS_TO_CHECK);
Cursor c = mContext.getContentResolver().query(lookupUri, AttachmentInfo.PROJECTION,
Cursor c = mContext.getContentResolver().query(lookupUri,
Attachment.CONTENT_PROJECTION,
EmailContent.Attachment.PRECACHE_INBOX_SELECTION,
null, Attachment.RECORD_ID + " DESC");
File cacheDir = mContext.getCacheDir();
try {
while (c.moveToNext()) {
long accountKey = c.getLong(AttachmentInfo.COLUMN_ACCOUNT_KEY);
long id = c.getLong(AttachmentInfo.COLUMN_ID);
Account account = Account.restoreAccountWithId(mContext, accountKey);
Attachment att = new Attachment();
att.restore(c);
Account account = Account.restoreAccountWithId(mContext, att.mAccountKey);
if (account == null) {
// Clean up this orphaned attachment; there's no point in keeping it
// around; then try to find another one
EmailContent.delete(mContext, Attachment.CONTENT_URI, id);
} else if (canPrefetchForAccount(account, cacheDir)) {
EmailContent.delete(mContext, Attachment.CONTENT_URI, att.mId);
} else {
// Check that the attachment meets system requirements for download
AttachmentInfo info = new AttachmentInfo(mContext, c);
AttachmentInfo info = new AttachmentInfo(mContext, att);
if (info.isEligibleForDownload()) {
Attachment att = Attachment.restoreAttachmentWithId(mContext, id);
if (att != null) {
// Either the account must be able to prefetch or this must be
// an inline attachment
if (att.mContentId != null ||
(canPrefetchForAccount(account, cacheDir))) {
Integer tryCount;
tryCount = mAttachmentFailureMap.get(att.mId);
if (tryCount != null && tryCount > MAX_DOWNLOAD_RETRIES) {