MessageCompose: initial save attachments and load them back.
- load attachments for EditDraft. - save attachments when save message. - unit test for restoreAccountsWithMessageId()
This commit is contained in:
parent
03be523b16
commit
44144d0301
|
@ -28,6 +28,7 @@ import com.android.email.mail.internet.EmailHtmlUtil;
|
|||
import com.android.email.mail.internet.MimeUtility;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.Attachment;
|
||||
import com.android.email.provider.EmailContent.Body;
|
||||
import com.android.email.provider.EmailContent.BodyColumns;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
|
@ -71,9 +72,9 @@ import android.widget.Toast;
|
|||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class MessageCompose extends Activity implements OnClickListener, OnFocusChangeListener {
|
||||
private static final String ACTION_REPLY = "com.android.email.intent.action.REPLY";
|
||||
private static final String ACTION_REPLY_ALL = "com.android.email.intent.action.REPLY_ALL";
|
||||
|
@ -82,9 +83,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
|
||||
private static final String EXTRA_ACCOUNT_ID = "account_id";
|
||||
private static final String EXTRA_MESSAGE_ID = "message_id";
|
||||
|
||||
private static final String STATE_KEY_ATTACHMENTS =
|
||||
"com.android.email.activity.MessageCompose.attachments";
|
||||
private static final String STATE_KEY_CC_SHOWN =
|
||||
"com.android.email.activity.MessageCompose.ccShown";
|
||||
private static final String STATE_KEY_BCC_SHOWN =
|
||||
|
@ -93,8 +91,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
"com.android.email.activity.MessageCompose.quotedTextShown";
|
||||
private static final String STATE_KEY_SOURCE_MESSAGE_PROCED =
|
||||
"com.android.email.activity.MessageCompose.stateKeySourceMessageProced";
|
||||
private static final String STATE_KEY_DRAFT_UID =
|
||||
"com.android.email.activity.MessageCompose.draftUid";
|
||||
|
||||
private static final int MSG_PROGRESS_ON = 1;
|
||||
private static final int MSG_PROGRESS_OFF = 2;
|
||||
|
@ -135,6 +131,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
private Controller mController;
|
||||
private Listener mListener = new Listener();
|
||||
private boolean mDraftNeedsSaving;
|
||||
private AsyncTask mLoadAttachmentsTask;
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
@Override
|
||||
|
@ -162,16 +159,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulates known information about a single attachment.
|
||||
*/
|
||||
private static class AttachmentInfo {
|
||||
public String name;
|
||||
public String contentType;
|
||||
public long size;
|
||||
public Uri uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a new message using the given account. If account is -1 the default account
|
||||
* will be used.
|
||||
|
@ -274,6 +261,21 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
} else {
|
||||
mAccount = Account.restoreAccountWithId(this, Account.getDefaultAccountId(this));
|
||||
}
|
||||
if (ACTION_EDIT_DRAFT.equals(action) && messageId != -1) {
|
||||
mLoadAttachmentsTask = new AsyncTask<Long, Void, Attachment[]>() {
|
||||
@Override
|
||||
protected Attachment[] doInBackground(Long... messageIds) {
|
||||
return Attachment.restoreAttachmentsWithMessageId(MessageCompose.this,
|
||||
messageIds[0]);
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(Attachment[] attachments) {
|
||||
for (Attachment attachment : attachments) {
|
||||
addAttachment(attachment);
|
||||
}
|
||||
}
|
||||
}.execute(messageId);
|
||||
}
|
||||
}
|
||||
|
||||
if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) ||
|
||||
|
@ -311,12 +313,16 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
super.onDestroy();
|
||||
mQuotedText.destroy();
|
||||
mQuotedText = null;
|
||||
if (mLoadAttachmentsTask != null
|
||||
&& mLoadAttachmentsTask.getStatus() != AsyncTask.Status.FINISHED) {
|
||||
mLoadAttachmentsTask.cancel(true);
|
||||
mLoadAttachmentsTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The framework handles most of the fields, but we need to handle stuff that we
|
||||
* dynamically show and hide:
|
||||
* Attachment list,
|
||||
* Cc field,
|
||||
* Bcc field,
|
||||
* Quoted text,
|
||||
|
@ -325,32 +331,16 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
saveIfNeeded();
|
||||
ArrayList<Uri> attachments = new ArrayList<Uri>();
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
View view = mAttachments.getChildAt(i);
|
||||
AttachmentInfo attachment = (AttachmentInfo) view.getTag();
|
||||
attachments.add(attachment.uri);
|
||||
}
|
||||
outState.putParcelableArrayList(STATE_KEY_ATTACHMENTS, attachments);
|
||||
outState.putBoolean(STATE_KEY_CC_SHOWN, mCcView.getVisibility() == View.VISIBLE);
|
||||
outState.putBoolean(STATE_KEY_BCC_SHOWN, mBccView.getVisibility() == View.VISIBLE);
|
||||
outState.putBoolean(STATE_KEY_QUOTED_TEXT_SHOWN,
|
||||
mQuotedTextBar.getVisibility() == View.VISIBLE);
|
||||
outState.putBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, mSourceMessageProcessed);
|
||||
// outState.putString(STATE_KEY_DRAFT_UID, mDraftUid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
ArrayList<Parcelable> attachments =
|
||||
savedInstanceState.getParcelableArrayList(STATE_KEY_ATTACHMENTS);
|
||||
mAttachments.removeAllViews();
|
||||
for (Parcelable p : attachments) {
|
||||
Uri uri = (Uri) p;
|
||||
addAttachment(uri);
|
||||
}
|
||||
|
||||
mCcView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN) ?
|
||||
View.VISIBLE : View.GONE);
|
||||
mBccView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_BCC_SHOWN) ?
|
||||
|
@ -359,7 +349,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
View.VISIBLE : View.GONE);
|
||||
mQuotedText.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ?
|
||||
View.VISIBLE : View.GONE);
|
||||
// mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID);
|
||||
mDraftNeedsSaving = false;
|
||||
}
|
||||
|
||||
|
@ -652,44 +641,16 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
message.mAccountKey = account.mId;
|
||||
message.mDisplayName = makeDisplayName(message.mTo, message.mCc, message.mBcc);
|
||||
message.mFlagLoaded = Message.LOADED;
|
||||
// TODO: add attachments (as below)
|
||||
}
|
||||
|
||||
// TextBody body = new TextBody(text);
|
||||
// if (mAttachments.getChildCount() > 0) {
|
||||
// /*
|
||||
// * The message has attachments that need to be included. First we add the part
|
||||
// * containing the text that will be sent and then we include each attachment.
|
||||
// */
|
||||
|
||||
// MimeMultipart mp;
|
||||
|
||||
// mp = new MimeMultipart();
|
||||
// mp.addBodyPart(new MimeBodyPart(body, "text/plain"));
|
||||
|
||||
// for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
// Attachment attachment = (Attachment) mAttachments.getChildAt(i).getTag();
|
||||
// MimeBodyPart bp = new MimeBodyPart(
|
||||
// new LocalStore.LocalAttachmentBody(attachment.uri, getApplication()));
|
||||
// bp.setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\n name=\"%s\"",
|
||||
// attachment.contentType,
|
||||
// attachment.name));
|
||||
// bp.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
|
||||
// bp.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
|
||||
// String.format("attachment;\n filename=\"%s\"",
|
||||
// attachment.name));
|
||||
// mp.addBodyPart(bp);
|
||||
// }
|
||||
|
||||
// message.setBody(mp);
|
||||
// }
|
||||
// else {
|
||||
// /*
|
||||
// * No attachments to include, just stick the text body in the message and call
|
||||
// * it good.
|
||||
// */
|
||||
// message.setBody(body);
|
||||
// }
|
||||
private Attachment[] getAttachmentsFromUI() {
|
||||
int count = mAttachments.getChildCount();
|
||||
Attachment[] attachments = new Attachment[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
attachments[i] = (Attachment) mAttachments.getChildAt(i).getTag();
|
||||
}
|
||||
return attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send or save a message:
|
||||
|
@ -714,11 +675,19 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
values.put(BodyColumns.TEXT_CONTENT, mDraft.mText);
|
||||
Body.updateBodyWithMessageId(MessageCompose.this, mDraft.mId, values);
|
||||
} else {
|
||||
// saveToMailbox() is synchronous (in this same thread)
|
||||
// so that mDraft.mId is set upon return
|
||||
// (needed by the sendMessage() that happens afterwards).
|
||||
// mDraft.mId is set upon return of saveToMailbox()
|
||||
mController.saveToMailbox(mDraft, EmailContent.Mailbox.TYPE_DRAFTS);
|
||||
}
|
||||
|
||||
// TODO: remove from DB the attachments that were removed from UI
|
||||
for (Attachment attachment : getAttachmentsFromUI()) {
|
||||
if (!attachment.isSaved()) {
|
||||
// this attachment is new so save it to DB.
|
||||
attachment.mMessageKey = mDraft.mId;
|
||||
attachment.save(MessageCompose.this);
|
||||
}
|
||||
}
|
||||
|
||||
if (send) {
|
||||
mController.sendMessage(mDraft.mId, mDraft.mAccountKey);
|
||||
// After a send it's no longer a draft; null it here just to be sure,
|
||||
|
@ -730,13 +699,14 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(Void dummy) {
|
||||
if (!send) {
|
||||
// Don't display the toast if the user is just changing the orientation
|
||||
if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
|
||||
Toast.makeText(MessageCompose.this, getString(R.string.message_saved_toast),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
// TODO: fix toast display for "saved as draft" if needed
|
||||
// if (!send) {
|
||||
// // Don't display the toast if the user is just changing the orientation
|
||||
// if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
|
||||
// Toast.makeText(MessageCompose.this, getString(R.string.message_saved_toast),
|
||||
// Toast.LENGTH_LONG).show();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
@ -811,7 +781,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
ACTIVITY_REQUEST_PICK_ATTACHMENT);
|
||||
}
|
||||
|
||||
private AttachmentInfo loadAttachmentInfo(Uri uri) {
|
||||
private Attachment loadAttachmentInfo(Uri uri) {
|
||||
int size = -1;
|
||||
String name = null;
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
|
@ -837,18 +807,17 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
contentType = "";
|
||||
}
|
||||
|
||||
AttachmentInfo attachment = new AttachmentInfo();
|
||||
attachment.name = name;
|
||||
attachment.contentType = contentType;
|
||||
attachment.size = size;
|
||||
attachment.uri = uri;
|
||||
Attachment attachment = new Attachment();
|
||||
attachment.mFileName = name;
|
||||
attachment.mContentUri = uri.toString();
|
||||
attachment.mSize = size;
|
||||
attachment.mMimeType = contentType;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
private void addAttachment(Uri uri) {
|
||||
AttachmentInfo attachment = loadAttachmentInfo(uri);
|
||||
private void addAttachment(Attachment attachment) {
|
||||
// Before attaching the attachment, make sure it meets any other pre-attach criteria
|
||||
if (attachment.size > Email.MAX_ATTACHMENT_UPLOAD_SIZE) {
|
||||
if (attachment.mSize > Email.MAX_ATTACHMENT_UPLOAD_SIZE) {
|
||||
Toast.makeText(this, R.string.message_compose_attachment_size, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
return;
|
||||
|
@ -858,13 +827,17 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||
mAttachments, false);
|
||||
TextView nameView = (TextView)view.findViewById(R.id.attachment_name);
|
||||
ImageButton delete = (ImageButton)view.findViewById(R.id.attachment_delete);
|
||||
nameView.setText(attachment.name);
|
||||
nameView.setText(attachment.mFileName);
|
||||
delete.setOnClickListener(this);
|
||||
delete.setTag(view);
|
||||
view.setTag(attachment);
|
||||
mAttachments.addView(view);
|
||||
}
|
||||
|
||||
private void addAttachment(Uri uri) {
|
||||
addAttachment(loadAttachmentInfo(uri));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (data == null) {
|
||||
|
|
|
@ -1043,31 +1043,15 @@ public class MessageView extends Activity
|
|||
* this implementation is incomplete, as it will fail to refresh properly if the message is
|
||||
* partially loaded at this time.
|
||||
*/
|
||||
private class LoadAttachmentsTask extends AsyncTask<Void, Void, Cursor> {
|
||||
|
||||
private long mId;
|
||||
|
||||
/**
|
||||
* Special constructor to cache some local info
|
||||
*/
|
||||
public LoadAttachmentsTask(long messageId) {
|
||||
mId = messageId;
|
||||
private class LoadAttachmentsTask extends AsyncTask<Long, Void, Attachment[]> {
|
||||
@Override
|
||||
protected Attachment[] doInBackground(Long... messageIds) {
|
||||
return Attachment.restoreAttachmentsWithMessageId(MessageView.this, messageIds[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Cursor doInBackground(Void... params) {
|
||||
Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, mId);
|
||||
return MessageView.this.managedQuery(
|
||||
uri,
|
||||
Attachment.CONTENT_PROJECTION,
|
||||
null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Cursor cursor) {
|
||||
while (cursor.moveToNext()) {
|
||||
// load and capture one attachment
|
||||
Attachment attachment = new Attachment().restore(cursor);
|
||||
protected void onPostExecute(Attachment[] attachments) {
|
||||
for (Attachment attachment : attachments) {
|
||||
addAttachment(attachment);
|
||||
}
|
||||
}
|
||||
|
@ -1108,8 +1092,8 @@ public class MessageView extends Activity
|
|||
mLoadBodyTask.execute();
|
||||
|
||||
// Ask for attachments
|
||||
mLoadAttachmentsTask = new LoadAttachmentsTask(message.mId);
|
||||
mLoadAttachmentsTask.execute();
|
||||
mLoadAttachmentsTask = new LoadAttachmentsTask();
|
||||
mLoadAttachmentsTask.execute(message.mId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1587,6 +1587,27 @@ public abstract class EmailContent {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore all the Attachments of a message given its messageId
|
||||
*/
|
||||
public static Attachment[] restoreAttachmentsWithMessageId(Context context,
|
||||
long messageId) {
|
||||
Uri uri = ContentUris.withAppendedId(MESSAGE_ID_URI, messageId);
|
||||
Cursor c = context.getContentResolver().query(uri, CONTENT_PROJECTION,
|
||||
null, null, null);
|
||||
try {
|
||||
int count = c.getCount();
|
||||
Attachment[] attachments = new Attachment[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
c.moveToNext();
|
||||
attachments[i] = new Attachment().restore(c);
|
||||
}
|
||||
return attachments;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique file in the external store by appending a hyphen
|
||||
* and a number to the given filename.
|
||||
|
|
|
@ -285,6 +285,15 @@ public class ProviderTests extends ProviderTestCase2<EmailProvider> {
|
|||
} finally {
|
||||
c.close();
|
||||
}
|
||||
|
||||
// test EmailContent.restoreAttachmentsWitdMessageId()
|
||||
Attachment[] attachments =
|
||||
Attachment.restoreAttachmentsWithMessageId(mMockContext, message4Id);
|
||||
int size = attachments.length;
|
||||
assertEquals(3, size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
ProviderTestUtils.assertAttachmentEqual("save-message4", atts.get(i), attachments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue