Fix problem with sending attachments in Exchange
The problem was that when the attachment was attempted to be opened from the Exchange process, it didn't have access to the cached file. Instead, use a content provider uri to reference the cached file. Bug: 8400456 Change-Id: I80abd66642e938cf09f73bf0e9bd049aa8d7ba1d
This commit is contained in:
parent
68a8e21248
commit
5a3aebbd2d
@ -239,11 +239,12 @@ public class Rfc822Output {
|
|||||||
inStream = new ByteArrayInputStream(attachment.mContentBytes);
|
inStream = new ByteArrayInputStream(attachment.mContentBytes);
|
||||||
} else {
|
} else {
|
||||||
// First try the cached file
|
// First try the cached file
|
||||||
final String cachedFile = attachment.getCachedFilePath();
|
final String cachedFile = attachment.getCachedFileUri();
|
||||||
if (!TextUtils.isEmpty(cachedFile)) {
|
if (!TextUtils.isEmpty(cachedFile)) {
|
||||||
|
final Uri cachedFileUri = Uri.parse(cachedFile);
|
||||||
try {
|
try {
|
||||||
inStream = new FileInputStream(cachedFile);
|
inStream = context.getContentResolver().openInputStream(cachedFileUri);
|
||||||
} catch (IOException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// Couldn't open the cached file, fall back to the original content uri
|
// Couldn't open the cached file, fall back to the original content uri
|
||||||
inStream = null;
|
inStream = null;
|
||||||
|
|
||||||
|
@ -1196,6 +1196,8 @@ public abstract class EmailContent {
|
|||||||
public static final String ATTACHMENT_PROVIDER_LEGACY_URI_PREFIX =
|
public static final String ATTACHMENT_PROVIDER_LEGACY_URI_PREFIX =
|
||||||
"content://com.android.email.attachmentprovider";
|
"content://com.android.email.attachmentprovider";
|
||||||
|
|
||||||
|
public static final String CACHED_FILE_QUERY_PARAM = "filePath";
|
||||||
|
|
||||||
public static Uri CONTENT_URI;
|
public static Uri CONTENT_URI;
|
||||||
// This must be used with an appended id: ContentUris.withAppendedId(MESSAGE_ID_URI, id)
|
// This must be used with an appended id: ContentUris.withAppendedId(MESSAGE_ID_URI, id)
|
||||||
public static Uri MESSAGE_ID_URI;
|
public static Uri MESSAGE_ID_URI;
|
||||||
@ -1217,7 +1219,7 @@ public abstract class EmailContent {
|
|||||||
public long mSize;
|
public long mSize;
|
||||||
public String mContentId;
|
public String mContentId;
|
||||||
private String mContentUri;
|
private String mContentUri;
|
||||||
private String mCachedFile;
|
private String mCachedFileUri;
|
||||||
public long mMessageKey;
|
public long mMessageKey;
|
||||||
public String mLocation;
|
public String mLocation;
|
||||||
public String mEncoding;
|
public String mEncoding;
|
||||||
@ -1295,12 +1297,12 @@ public abstract class EmailContent {
|
|||||||
mBaseUri = CONTENT_URI;
|
mBaseUri = CONTENT_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCachedFilePath(String cachedFile) {
|
public void setCachedFileUri(String cachedFile) {
|
||||||
mCachedFile = cachedFile;
|
mCachedFileUri = cachedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCachedFilePath() {
|
public String getCachedFileUri() {
|
||||||
return mCachedFile;
|
return mCachedFileUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContentUri(String contentUri) {
|
public void setContentUri(String contentUri) {
|
||||||
@ -1404,7 +1406,7 @@ public abstract class EmailContent {
|
|||||||
mSize = cursor.getLong(CONTENT_SIZE_COLUMN);
|
mSize = cursor.getLong(CONTENT_SIZE_COLUMN);
|
||||||
mContentId = cursor.getString(CONTENT_CONTENT_ID_COLUMN);
|
mContentId = cursor.getString(CONTENT_CONTENT_ID_COLUMN);
|
||||||
mContentUri = cursor.getString(CONTENT_CONTENT_URI_COLUMN);
|
mContentUri = cursor.getString(CONTENT_CONTENT_URI_COLUMN);
|
||||||
mCachedFile = cursor.getString(CONTENT_CACHED_FILE_COLUMN);
|
mCachedFileUri = cursor.getString(CONTENT_CACHED_FILE_COLUMN);
|
||||||
mMessageKey = cursor.getLong(CONTENT_MESSAGE_ID_COLUMN);
|
mMessageKey = cursor.getLong(CONTENT_MESSAGE_ID_COLUMN);
|
||||||
mLocation = cursor.getString(CONTENT_LOCATION_COLUMN);
|
mLocation = cursor.getString(CONTENT_LOCATION_COLUMN);
|
||||||
mEncoding = cursor.getString(CONTENT_ENCODING_COLUMN);
|
mEncoding = cursor.getString(CONTENT_ENCODING_COLUMN);
|
||||||
@ -1425,7 +1427,7 @@ public abstract class EmailContent {
|
|||||||
values.put(AttachmentColumns.SIZE, mSize);
|
values.put(AttachmentColumns.SIZE, mSize);
|
||||||
values.put(AttachmentColumns.CONTENT_ID, mContentId);
|
values.put(AttachmentColumns.CONTENT_ID, mContentId);
|
||||||
values.put(AttachmentColumns.CONTENT_URI, mContentUri);
|
values.put(AttachmentColumns.CONTENT_URI, mContentUri);
|
||||||
values.put(AttachmentColumns.CACHED_FILE, mCachedFile);
|
values.put(AttachmentColumns.CACHED_FILE, mCachedFileUri);
|
||||||
values.put(AttachmentColumns.MESSAGE_KEY, mMessageKey);
|
values.put(AttachmentColumns.MESSAGE_KEY, mMessageKey);
|
||||||
values.put(AttachmentColumns.LOCATION, mLocation);
|
values.put(AttachmentColumns.LOCATION, mLocation);
|
||||||
values.put(AttachmentColumns.ENCODING, mEncoding);
|
values.put(AttachmentColumns.ENCODING, mEncoding);
|
||||||
@ -1453,7 +1455,7 @@ public abstract class EmailContent {
|
|||||||
dest.writeLong(mSize);
|
dest.writeLong(mSize);
|
||||||
dest.writeString(mContentId);
|
dest.writeString(mContentId);
|
||||||
dest.writeString(mContentUri);
|
dest.writeString(mContentUri);
|
||||||
dest.writeString(mCachedFile);
|
dest.writeString(mCachedFileUri);
|
||||||
dest.writeLong(mMessageKey);
|
dest.writeLong(mMessageKey);
|
||||||
dest.writeString(mLocation);
|
dest.writeString(mLocation);
|
||||||
dest.writeString(mEncoding);
|
dest.writeString(mEncoding);
|
||||||
@ -1479,7 +1481,7 @@ public abstract class EmailContent {
|
|||||||
mSize = in.readLong();
|
mSize = in.readLong();
|
||||||
mContentId = in.readString();
|
mContentId = in.readString();
|
||||||
mContentUri = in.readString();
|
mContentUri = in.readString();
|
||||||
mCachedFile = in.readString();
|
mCachedFileUri = in.readString();
|
||||||
mMessageKey = in.readLong();
|
mMessageKey = in.readLong();
|
||||||
mLocation = in.readString();
|
mLocation = in.readString();
|
||||||
mEncoding = in.readString();
|
mEncoding = in.readString();
|
||||||
@ -1514,7 +1516,7 @@ public abstract class EmailContent {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[" + mFileName + ", " + mMimeType + ", " + mSize + ", " + mContentId + ", "
|
return "[" + mFileName + ", " + mMimeType + ", " + mSize + ", " + mContentId + ", "
|
||||||
+ mContentUri + ", " + mCachedFile + ", " + mMessageKey + ", "
|
+ mContentUri + ", " + mCachedFileUri + ", " + mMessageKey + ", "
|
||||||
+ mLocation + ", " + mEncoding + ", " + mFlags + ", " + mContentBytes + ", "
|
+ mLocation + ", " + mEncoding + ", " + mFlags + ", " + mContentBytes + ", "
|
||||||
+ mAccountKey + "," + mUiState + "," + mUiDestination + ","
|
+ mAccountKey + "," + mUiState + "," + mUiDestination + ","
|
||||||
+ mUiDownloadedSize + "]";
|
+ mUiDownloadedSize + "]";
|
||||||
|
@ -53,6 +53,7 @@ import com.android.emailcommon.provider.EmailContent.HostAuthColumns;
|
|||||||
import com.android.emailcommon.provider.EmailContent.Message;
|
import com.android.emailcommon.provider.EmailContent.Message;
|
||||||
import com.android.emailcommon.provider.HostAuth;
|
import com.android.emailcommon.provider.HostAuth;
|
||||||
import com.android.emailcommon.provider.ProviderUnavailableException;
|
import com.android.emailcommon.provider.ProviderUnavailableException;
|
||||||
|
import com.android.mail.utils.LogUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -745,11 +746,13 @@ public class Utility {
|
|||||||
} else if (attachment.mContentBytes != null) {
|
} else if (attachment.mContentBytes != null) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
final String cachedFile = attachment.getCachedFilePath();
|
final String cachedFile = attachment.getCachedFileUri();
|
||||||
// Try the cached file first
|
// Try the cached file first
|
||||||
if (!TextUtils.isEmpty(cachedFile)) {
|
if (!TextUtils.isEmpty(cachedFile)) {
|
||||||
|
final Uri cachedFileUri = Uri.parse(cachedFile);
|
||||||
try {
|
try {
|
||||||
final InputStream inStream = new FileInputStream(cachedFile);
|
final InputStream inStream =
|
||||||
|
context.getContentResolver().openInputStream(cachedFileUri);
|
||||||
try {
|
try {
|
||||||
inStream.close();
|
inStream.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -758,6 +761,7 @@ public class Utility {
|
|||||||
return true;
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// We weren't able to open the file, try the content uri below
|
// We weren't able to open the file, try the content uri below
|
||||||
|
LogUtils.e(Logging.LOG_TAG, e, "not able to open cached file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final String contentUri = attachment.getContentUri();
|
final String contentUri = attachment.getContentUri();
|
||||||
|
@ -37,8 +37,10 @@ import android.database.MergeCursor;
|
|||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteException;
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@ -101,6 +103,7 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -199,6 +202,7 @@ public class EmailProvider extends ContentProvider {
|
|||||||
private static final int ATTACHMENT = ATTACHMENT_BASE;
|
private static final int ATTACHMENT = ATTACHMENT_BASE;
|
||||||
private static final int ATTACHMENT_ID = ATTACHMENT_BASE + 1;
|
private static final int ATTACHMENT_ID = ATTACHMENT_BASE + 1;
|
||||||
private static final int ATTACHMENTS_MESSAGE_ID = ATTACHMENT_BASE + 2;
|
private static final int ATTACHMENTS_MESSAGE_ID = ATTACHMENT_BASE + 2;
|
||||||
|
private static final int ATTACHMENTS_CACHED_FILE_ACCESS = ATTACHMENT_BASE + 3;
|
||||||
|
|
||||||
private static final int HOSTAUTH_BASE = 0x4000;
|
private static final int HOSTAUTH_BASE = 0x4000;
|
||||||
private static final int HOSTAUTH = HOSTAUTH_BASE;
|
private static final int HOSTAUTH = HOSTAUTH_BASE;
|
||||||
@ -1095,6 +1099,8 @@ public class EmailProvider extends ContentProvider {
|
|||||||
// The attachments of a specific message (query only) (insert & delete TBD)
|
// The attachments of a specific message (query only) (insert & delete TBD)
|
||||||
matcher.addURI(EmailContent.AUTHORITY, "attachment/message/#",
|
matcher.addURI(EmailContent.AUTHORITY, "attachment/message/#",
|
||||||
ATTACHMENTS_MESSAGE_ID);
|
ATTACHMENTS_MESSAGE_ID);
|
||||||
|
matcher.addURI(EmailContent.AUTHORITY, "attachment/cachedFile",
|
||||||
|
ATTACHMENTS_CACHED_FILE_ACCESS);
|
||||||
|
|
||||||
// All mail bodies
|
// All mail bodies
|
||||||
matcher.addURI(EmailContent.AUTHORITY, "body", BODY);
|
matcher.addURI(EmailContent.AUTHORITY, "body", BODY);
|
||||||
@ -1891,6 +1897,39 @@ outer:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||||
|
if (LogUtils.isLoggable(TAG, LogUtils.DEBUG)) {
|
||||||
|
LogUtils.d(TAG, "EmailProvider.openFile: %s", LogUtils.contentUriToString(TAG, uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
final int match = findMatch(uri, "openFile");
|
||||||
|
switch (match) {
|
||||||
|
case ATTACHMENTS_CACHED_FILE_ACCESS:
|
||||||
|
// Parse the cache file path out from the uri
|
||||||
|
final String cachedFilePath =
|
||||||
|
uri.getQueryParameter(EmailContent.Attachment.CACHED_FILE_QUERY_PARAM);
|
||||||
|
|
||||||
|
if (cachedFilePath != null) {
|
||||||
|
// clearCallingIdentity means that the download manager will
|
||||||
|
// check our permissions rather than the permissions of whatever
|
||||||
|
// code is calling us.
|
||||||
|
long binderToken = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
LogUtils.d(TAG, "Opening attachment %s", cachedFilePath);
|
||||||
|
return ParcelFileDescriptor.open(
|
||||||
|
new File(cachedFilePath), ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(binderToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException("unable to open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base notification URI for the given content type.
|
* Returns the base notification URI for the given content type.
|
||||||
*
|
*
|
||||||
@ -3473,7 +3512,15 @@ outer:
|
|||||||
com.android.mail.providers.Attachment uiAtt, String cachedFile) {
|
com.android.mail.providers.Attachment uiAtt, String cachedFile) {
|
||||||
final Attachment att = new Attachment();
|
final Attachment att = new Attachment();
|
||||||
att.setContentUri(uiAtt.contentUri.toString());
|
att.setContentUri(uiAtt.contentUri.toString());
|
||||||
att.setCachedFilePath(cachedFile);
|
|
||||||
|
if (!TextUtils.isEmpty(cachedFile)) {
|
||||||
|
// Generate the content provider uri for this cached file
|
||||||
|
final Uri.Builder cachedFileBuilder = Uri.parse(
|
||||||
|
"content://" + EmailContent.AUTHORITY + "/attachment/cachedFile").buildUpon();
|
||||||
|
cachedFileBuilder.appendQueryParameter(Attachment.CACHED_FILE_QUERY_PARAM, cachedFile);
|
||||||
|
att.setCachedFileUri(cachedFileBuilder.build().toString());
|
||||||
|
}
|
||||||
|
|
||||||
att.mFileName = uiAtt.getName();
|
att.mFileName = uiAtt.getName();
|
||||||
att.mMimeType = uiAtt.getContentType();
|
att.mMimeType = uiAtt.getContentType();
|
||||||
att.mSize = uiAtt.size;
|
att.mSize = uiAtt.size;
|
||||||
|
Loading…
Reference in New Issue
Block a user