Rework service to use provider accounts and controller.
* Rewrite service logic to select and update one account at a time * Add checkmail API to Controller, and much rework/cleanup of existing callback API's * Rewrite notification posting code * Rewire connection to MessageList to be opened by notifications, to cancel notifications, and to reset the "new message" count whenever an account is viewed. * Boilerplate cleanup to a lot of activities because they share the callbacks that have had minor changes. * Remove old push controls from Store API In progress: * To provide notification mechanism for EAS pushed mail
This commit is contained in:
parent
d1fd72a44e
commit
46d7d7f1b6
@ -53,6 +53,7 @@ public class Controller {
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private Context mProviderContext;
|
private Context mProviderContext;
|
||||||
private MessagingController mLegacyController;
|
private MessagingController mLegacyController;
|
||||||
|
private LegacyListener mLegacyListener = new LegacyListener();
|
||||||
private ServiceCallback mServiceCallback = new ServiceCallback();
|
private ServiceCallback mServiceCallback = new ServiceCallback();
|
||||||
private HashSet<Result> mListeners = new HashSet<Result>();
|
private HashSet<Result> mListeners = new HashSet<Result>();
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ public class Controller {
|
|||||||
mContext = _context;
|
mContext = _context;
|
||||||
mProviderContext = _context;
|
mProviderContext = _context;
|
||||||
mLegacyController = MessagingController.getInstance(mContext);
|
mLegacyController = MessagingController.getInstance(mContext);
|
||||||
|
mLegacyController.addListener(mLegacyListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,11 +160,39 @@ public class Controller {
|
|||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Account account =
|
mLegacyController.listFolders(accountId, mLegacyListener);
|
||||||
EmailContent.Account.restoreAccountWithId(mProviderContext, accountId);
|
}
|
||||||
MessagingListener listener = new LegacyListener(callback);
|
}.start();
|
||||||
mLegacyController.addListener(listener);
|
}
|
||||||
mLegacyController.listFolders(account, listener);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a remote update of a mailbox. For use by the timed service.
|
||||||
|
*
|
||||||
|
* Functionally this is quite similar to updateMailbox(), but it's a separate API and
|
||||||
|
* separate callback in order to keep UI callbacks from affecting the service loop.
|
||||||
|
*/
|
||||||
|
public void serviceCheckMail(final long accountId, final long mailboxId, final long tag,
|
||||||
|
final Result callback) {
|
||||||
|
IEmailService service = getServiceForAccount(accountId);
|
||||||
|
if (service != null) {
|
||||||
|
// Service implementation
|
||||||
|
// try {
|
||||||
|
// TODO this isn't quite going to work, because we're going to get the
|
||||||
|
// generic (UI) callbacks and not the ones we need to restart the ol' service.
|
||||||
|
// service.startSync(mailboxId, tag);
|
||||||
|
callback.serviceCheckMailCallback(null, accountId, mailboxId, 100, tag);
|
||||||
|
// } catch (RemoteException e) {
|
||||||
|
// TODO Change exception handling to be consistent with however this method
|
||||||
|
// is implemented for other protocols
|
||||||
|
// Log.d("updateMailbox", "RemoteException" + e);
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
// MessagingController implementation
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mLegacyController.checkMail(accountId, tag, mLegacyListener);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
@ -175,14 +205,13 @@ public class Controller {
|
|||||||
* a simple message list. We should also at this point queue up a background task of
|
* a simple message list. We should also at this point queue up a background task of
|
||||||
* downloading some/all of the messages in this mailbox, but that should be interruptable.
|
* downloading some/all of the messages in this mailbox, but that should be interruptable.
|
||||||
*/
|
*/
|
||||||
public void updateMailbox(final long accountId,
|
public void updateMailbox(final long accountId, final long mailboxId, final Result callback) {
|
||||||
final EmailContent.Mailbox mailbox, final Result callback) {
|
|
||||||
|
|
||||||
IEmailService service = getServiceForAccount(accountId);
|
IEmailService service = getServiceForAccount(accountId);
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
// Service implementation
|
// Service implementation
|
||||||
try {
|
try {
|
||||||
service.startSync(mailbox.mId);
|
service.startSync(mailboxId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// TODO Change exception handling to be consistent with however this method
|
// TODO Change exception handling to be consistent with however this method
|
||||||
// is implemented for other protocols
|
// is implemented for other protocols
|
||||||
@ -193,11 +222,12 @@ public class Controller {
|
|||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
// TODO shouldn't be passing fully-build accounts & mailboxes into APIs
|
||||||
Account account =
|
Account account =
|
||||||
EmailContent.Account.restoreAccountWithId(mProviderContext, accountId);
|
EmailContent.Account.restoreAccountWithId(mProviderContext, accountId);
|
||||||
MessagingListener listener = new LegacyListener(callback);
|
Mailbox mailbox =
|
||||||
mLegacyController.addListener(listener);
|
EmailContent.Mailbox.restoreMailboxWithId(mProviderContext, mailboxId);
|
||||||
mLegacyController.synchronizeMailbox(account, mailbox, listener);
|
mLegacyController.synchronizeMailbox(account, mailbox, mLegacyListener);
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
@ -516,7 +546,6 @@ public class Controller {
|
|||||||
* made from the UI thread, so you may need further handlers to safely make UI updates.
|
* made from the UI thread, so you may need further handlers to safely make UI updates.
|
||||||
*/
|
*/
|
||||||
public interface Result {
|
public interface Result {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for updateMailboxList
|
* Callback for updateMailboxList
|
||||||
*
|
*
|
||||||
@ -528,15 +557,17 @@ public class Controller {
|
|||||||
int progress);
|
int progress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for updateMailbox
|
* Callback for updateMailbox. Note: This looks a lot like checkMailCallback, but
|
||||||
|
* it's a separate call used only by UI's, so we can keep things separate.
|
||||||
*
|
*
|
||||||
* @param result If null, the operation completed without error
|
* @param result If null, the operation completed without error
|
||||||
* @param accountId The account being operated on
|
* @param accountId The account being operated on
|
||||||
* @param mailboxId The mailbox being operated on
|
* @param mailboxId The mailbox being operated on
|
||||||
* @param progress 0 for "starting", 1..99 for updates (if needed in UI), 100 for complete
|
* @param progress 0 for "starting", 1..99 for updates (if needed in UI), 100 for complete
|
||||||
|
* @param numNewMessages the number of new messages delivered
|
||||||
*/
|
*/
|
||||||
public void updateMailboxCallback(MessagingException result, long accountId,
|
public void updateMailboxCallback(MessagingException result, long accountId,
|
||||||
long mailboxId, int progress, int totalMessagesInMailbox, int numNewMessages);
|
long mailboxId, int progress, int numNewMessages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for loadAttachment
|
* Callback for loadAttachment
|
||||||
@ -548,6 +579,20 @@ public class Controller {
|
|||||||
*/
|
*/
|
||||||
public void loadAttachmentCallback(MessagingException result, long messageId,
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
long attachmentId, int progress);
|
long attachmentId, int progress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for checkmail. Note: This looks a lot like updateMailboxCallback, but
|
||||||
|
* it's a separate call used only by the automatic checker service, so we can keep
|
||||||
|
* things separate.
|
||||||
|
*
|
||||||
|
* @param result If null, the operation completed without error
|
||||||
|
* @param accountId The account being operated on
|
||||||
|
* @param mailboxId The mailbox being operated on (may be unknown at start)
|
||||||
|
* @param progress 0 for "starting", no updates, 100 for complete
|
||||||
|
* @param tag the same tag that was passed to serviceCheckMail()
|
||||||
|
*/
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -555,70 +600,87 @@ public class Controller {
|
|||||||
* out of scope.
|
* out of scope.
|
||||||
*/
|
*/
|
||||||
private class LegacyListener extends MessagingListener {
|
private class LegacyListener extends MessagingListener {
|
||||||
Result mResultCallback;
|
|
||||||
|
|
||||||
public LegacyListener(Result callback) {
|
|
||||||
mResultCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listFoldersStarted(EmailContent.Account account) {
|
public void listFoldersStarted(EmailContent.Account account) {
|
||||||
if (mResultCallback != null && isActiveResultCallback(mResultCallback)) {
|
synchronized (mListeners) {
|
||||||
mResultCallback.updateMailboxListCallback(null, account.mId, 0);
|
for (Result l : mListeners) {
|
||||||
|
l.updateMailboxListCallback(null, account.mId, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listFoldersFailed(EmailContent.Account account, String message) {
|
public void listFoldersFailed(EmailContent.Account account, String message) {
|
||||||
if (mResultCallback != null && isActiveResultCallback(mResultCallback)) {
|
synchronized (mListeners) {
|
||||||
mResultCallback.updateMailboxListCallback(new MessagingException(message),
|
for (Result l : mListeners) {
|
||||||
account.mId, 0);
|
l.updateMailboxListCallback(new MessagingException(message), account.mId, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mLegacyController.removeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listFoldersFinished(EmailContent.Account account) {
|
public void listFoldersFinished(EmailContent.Account account) {
|
||||||
if (mResultCallback != null && isActiveResultCallback(mResultCallback)) {
|
synchronized (mListeners) {
|
||||||
mResultCallback.updateMailboxListCallback(null, account.mId, 100);
|
for (Result l : mListeners) {
|
||||||
|
l.updateMailboxListCallback(null, account.mId, 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mLegacyController.removeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxStarted(EmailContent.Account account,
|
public void synchronizeMailboxStarted(EmailContent.Account account,
|
||||||
EmailContent.Mailbox folder) {
|
EmailContent.Mailbox folder) {
|
||||||
if (mResultCallback != null && isActiveResultCallback(mResultCallback)) {
|
synchronized (mListeners) {
|
||||||
mResultCallback.updateMailboxCallback(null, account.mId, folder.mId, 0, -1, -1);
|
for (Result l : mListeners) {
|
||||||
|
l.updateMailboxCallback(null, account.mId, folder.mId, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxFinished(EmailContent.Account account,
|
public void synchronizeMailboxFinished(EmailContent.Account account,
|
||||||
EmailContent.Mailbox folder, int totalMessagesInMailbox, int numNewMessages) {
|
EmailContent.Mailbox folder, int totalMessagesInMailbox, int numNewMessages) {
|
||||||
if (mResultCallback != null && isActiveResultCallback(mResultCallback)) {
|
synchronized (mListeners) {
|
||||||
mResultCallback.updateMailboxCallback(null, account.mId, folder.mId, 100,
|
for (Result l : mListeners) {
|
||||||
totalMessagesInMailbox, numNewMessages);
|
l.updateMailboxCallback(null, account.mId, folder.mId, 100, numNewMessages);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mLegacyController.removeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void synchronizeMailboxFailed(EmailContent.Account account,
|
public void synchronizeMailboxFailed(EmailContent.Account account,
|
||||||
EmailContent.Mailbox folder, Exception e) {
|
EmailContent.Mailbox folder, Exception e) {
|
||||||
if (mResultCallback != null && isActiveResultCallback(mResultCallback)) {
|
synchronized (mListeners) {
|
||||||
MessagingException me;
|
for (Result l : mListeners) {
|
||||||
if (e instanceof MessagingException) {
|
MessagingException me;
|
||||||
me = (MessagingException) e;
|
if (e instanceof MessagingException) {
|
||||||
} else {
|
me = (MessagingException) e;
|
||||||
me = new MessagingException(e.toString());
|
} else {
|
||||||
|
me = new MessagingException(e.toString());
|
||||||
|
}
|
||||||
|
l.updateMailboxCallback(me, account.mId, folder.mId, 0, 0);
|
||||||
}
|
}
|
||||||
mResultCallback.updateMailboxCallback(me, account.mId, folder.mId, 0, -1, -1);
|
|
||||||
}
|
}
|
||||||
mLegacyController.removeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkMailStarted(Context context, long accountId, long tag) {
|
||||||
|
synchronized (mListeners) {
|
||||||
|
for (Result l : mListeners) {
|
||||||
|
l.serviceCheckMailCallback(null, accountId, -1, 0, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkMailFinished(Context context, long accountId, long folderId, long tag) {
|
||||||
|
synchronized (mListeners) {
|
||||||
|
for (Result l : mListeners) {
|
||||||
|
l.serviceCheckMailCallback(null, accountId, folderId, 100, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -700,8 +762,7 @@ public class Controller {
|
|||||||
result = new MessagingException(String.valueOf(statusCode));
|
result = new MessagingException(String.valueOf(statusCode));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// TODO can we get "number of new messages" back as well?
|
// TODO where do we get "number of new messages" as well?
|
||||||
// TODO remove "total num messages" which can be looked up if needed
|
|
||||||
// TODO should pass this back instead of looking it up here
|
// TODO should pass this back instead of looking it up here
|
||||||
// TODO smaller projection
|
// TODO smaller projection
|
||||||
Mailbox mbx = Mailbox.restoreMailboxWithId(mContext, mailboxId);
|
Mailbox mbx = Mailbox.restoreMailboxWithId(mContext, mailboxId);
|
||||||
@ -710,7 +771,7 @@ public class Controller {
|
|||||||
long accountId = mbx.mAccountKey;
|
long accountId = mbx.mAccountKey;
|
||||||
synchronized(mListeners) {
|
synchronized(mListeners) {
|
||||||
for (Result listener : mListeners) {
|
for (Result listener : mListeners) {
|
||||||
listener.updateMailboxCallback(result, accountId, mailboxId, progress, 0, 0);
|
listener.updateMailboxCallback(result, accountId, mailboxId, progress, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,25 +138,20 @@ public class GroupMessagingListener extends MessagingListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public void checkMailStarted(Context context, EmailContent.Account account) {
|
synchronized public void checkMailStarted(Context context, long accountId, long tag) {
|
||||||
for (MessagingListener l : mListeners) {
|
for (MessagingListener l : mListeners) {
|
||||||
l.checkMailStarted(context, account);
|
l.checkMailStarted(context, accountId, tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public void checkMailFinished(Context context, EmailContent.Account account) {
|
synchronized public void checkMailFinished(Context context, long accountId, long folderId,
|
||||||
|
long tag) {
|
||||||
for (MessagingListener l : mListeners) {
|
for (MessagingListener l : mListeners) {
|
||||||
l.checkMailFinished(context, account);
|
l.checkMailFinished(context, accountId, folderId, tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
synchronized public void checkMailFailed(Context context, EmailContent.Account account,
|
|
||||||
String reason) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public void sendPendingMessagesCompleted(EmailContent.Account account) {
|
synchronized public void sendPendingMessagesCompleted(EmailContent.Account account) {
|
||||||
for (MessagingListener l : mListeners) {
|
for (MessagingListener l : mListeners) {
|
||||||
|
@ -34,6 +34,7 @@ import com.android.email.mail.store.LocalStore.LocalFolder;
|
|||||||
import com.android.email.mail.store.LocalStore.LocalMessage;
|
import com.android.email.mail.store.LocalStore.LocalMessage;
|
||||||
import com.android.email.mail.store.LocalStore.PendingCommand;
|
import com.android.email.mail.store.LocalStore.PendingCommand;
|
||||||
import com.android.email.provider.EmailContent;
|
import com.android.email.provider.EmailContent;
|
||||||
|
import com.android.email.provider.EmailContent.Mailbox;
|
||||||
import com.android.email.provider.EmailContent.MailboxColumns;
|
import com.android.email.provider.EmailContent.MailboxColumns;
|
||||||
import com.android.email.provider.EmailContent.MessageColumns;
|
import com.android.email.provider.EmailContent.MessageColumns;
|
||||||
import com.android.email.provider.EmailContent.SyncColumns;
|
import com.android.email.provider.EmailContent.SyncColumns;
|
||||||
@ -219,7 +220,9 @@ public class MessagingController implements Runnable {
|
|||||||
* @param listener
|
* @param listener
|
||||||
* @throws MessagingException
|
* @throws MessagingException
|
||||||
*/
|
*/
|
||||||
public void listFolders(final EmailContent.Account account, MessagingListener listener) {
|
public void listFolders(long accountId, MessagingListener listener) {
|
||||||
|
final EmailContent.Account account =
|
||||||
|
EmailContent.Account.restoreAccountWithId(mContext, accountId);
|
||||||
mListeners.listFoldersStarted(account);
|
mListeners.listFoldersStarted(account);
|
||||||
put("listFolders", listener, new Runnable() {
|
put("listFolders", listener, new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -493,6 +496,7 @@ public class MessagingController implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* Start foreground synchronization of the specified folder. This is called by
|
* Start foreground synchronization of the specified folder. This is called by
|
||||||
* synchronizeMailbox or checkMail.
|
* synchronizeMailbox or checkMail.
|
||||||
|
* TODO this should use ID's instead of fully-restored objects
|
||||||
* @param account
|
* @param account
|
||||||
* @param folder
|
* @param folder
|
||||||
* @param listener
|
* @param listener
|
||||||
@ -528,49 +532,6 @@ public class MessagingController implements Runnable {
|
|||||||
mListeners.synchronizeMailboxFailed(account, folder, e);
|
mListeners.synchronizeMailboxFailed(account, folder, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move all this to top
|
|
||||||
/*
|
|
||||||
public static final int CONTENT_ID_COLUMN = 0;
|
|
||||||
public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
|
|
||||||
public static final int CONTENT_TIMESTAMP_COLUMN = 2;
|
|
||||||
public static final int CONTENT_SUBJECT_COLUMN = 3;
|
|
||||||
public static final int CONTENT_PREVIEW_COLUMN = 4;
|
|
||||||
public static final int CONTENT_FLAG_READ_COLUMN = 5;
|
|
||||||
public static final int CONTENT_FLAG_LOADED_COLUMN = 6;
|
|
||||||
public static final int CONTENT_FLAG_FAVORITE_COLUMN = 7;
|
|
||||||
public static final int CONTENT_FLAG_ATTACHMENT_COLUMN = 8;
|
|
||||||
public static final int CONTENT_FLAGS_COLUMN = 9;
|
|
||||||
public static final int CONTENT_TEXT_INFO_COLUMN = 10;
|
|
||||||
public static final int CONTENT_HTML_INFO_COLUMN = 11;
|
|
||||||
public static final int CONTENT_BODY_ID_COLUMN = 12;
|
|
||||||
public static final int CONTENT_SERVER_ID_COLUMN = 13;
|
|
||||||
public static final int CONTENT_CLIENT_ID_COLUMN = 14;
|
|
||||||
public static final int CONTENT_MESSAGE_ID_COLUMN = 15;
|
|
||||||
public static final int CONTENT_THREAD_ID_COLUMN = 16;
|
|
||||||
public static final int CONTENT_MAILBOX_KEY_COLUMN = 17;
|
|
||||||
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 18;
|
|
||||||
public static final int CONTENT_REFERENCE_KEY_COLUMN = 19;
|
|
||||||
public static final int CONTENT_SENDER_LIST_COLUMN = 20;
|
|
||||||
public static final int CONTENT_FROM_LIST_COLUMN = 21;
|
|
||||||
public static final int CONTENT_TO_LIST_COLUMN = 22;
|
|
||||||
public static final int CONTENT_CC_LIST_COLUMN = 23;
|
|
||||||
public static final int CONTENT_BCC_LIST_COLUMN = 24;
|
|
||||||
public static final int CONTENT_REPLY_TO_COLUMN = 25;
|
|
||||||
public static final int CONTENT_SERVER_VERSION_COLUMN = 26;
|
|
||||||
public static final String[] CONTENT_PROJECTION = new String[] {
|
|
||||||
RECORD_ID, MessageColumns.DISPLAY_NAME, MessageColumns.TIMESTAMP,
|
|
||||||
MessageColumns.SUBJECT, MessageColumns.PREVIEW, MessageColumns.FLAG_READ,
|
|
||||||
MessageColumns.FLAG_LOADED, MessageColumns.FLAG_FAVORITE,
|
|
||||||
MessageColumns.FLAG_ATTACHMENT, MessageColumns.FLAGS, MessageColumns.TEXT_INFO,
|
|
||||||
MessageColumns.HTML_INFO, MessageColumns.BODY_ID, SyncColumns.SERVER_ID,
|
|
||||||
MessageColumns.CLIENT_ID, MessageColumns.MESSAGE_ID, MessageColumns.THREAD_ID,
|
|
||||||
MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY, MessageColumns.REFERENCE_KEY,
|
|
||||||
MessageColumns.SENDER_LIST, MessageColumns.FROM_LIST, MessageColumns.TO_LIST,
|
|
||||||
MessageColumns.CC_LIST, MessageColumns.BCC_LIST, MessageColumns.REPLY_TO_LIST,
|
|
||||||
SyncColumns.SERVER_VERSION
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lightweight record for the first pass of message sync, where I'm just seeing if
|
* Lightweight record for the first pass of message sync, where I'm just seeing if
|
||||||
@ -1135,8 +1096,7 @@ public class MessagingController implements Runnable {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StoreSynchronizer.SyncResults(0, 0);
|
return new StoreSynchronizer.SyncResults(remoteMessageCount, newMessages.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void queuePendingCommand(EmailContent.Account account, PendingCommand command) {
|
private void queuePendingCommand(EmailContent.Account account, PendingCommand command) {
|
||||||
@ -1710,6 +1670,9 @@ public class MessagingController implements Runnable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to send any messages that are sitting in the Outbox.
|
* Attempt to send any messages that are sitting in the Outbox.
|
||||||
|
* TODO rewrite for database not LocalStore
|
||||||
|
* TODO this should accept accountId, and probably be reworked in other ways
|
||||||
|
*
|
||||||
* @param account
|
* @param account
|
||||||
* @param listener
|
* @param listener
|
||||||
*/
|
*/
|
||||||
@ -1846,51 +1809,36 @@ public class MessagingController implements Runnable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks mail for one or multiple accounts. If account is null all accounts
|
* Checks mail for one or multiple accounts. If account is null all accounts
|
||||||
* are checked.
|
* are checked. This entry point is for use by the mail checking service only, because it
|
||||||
|
* gives slightly different callbacks (so the service doesn't get confused by callbacks
|
||||||
|
* triggered by/for the foreground UI.
|
||||||
*
|
*
|
||||||
* TODO: There is no use case for "check all accounts". Clean up this API to remove
|
* TODO clean up the execution model which is unnecessarily threaded due to legacy code
|
||||||
* that case. Callers can supply the appropriate list.
|
|
||||||
*
|
|
||||||
* TODO: Better protection against a failure in account n, which should not prevent
|
|
||||||
* syncing account in accounts n+1 and beyond.
|
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* @param accounts List of accounts to check, or null to check all accounts
|
* @param accountId the account to check
|
||||||
* @param listener
|
* @param listener
|
||||||
*/
|
*/
|
||||||
public void checkMail(final Context context, EmailContent.Account[] accounts,
|
public void checkMail(final long accountId, final long tag, final MessagingListener listener) {
|
||||||
final MessagingListener listener) {
|
mListeners.checkMailStarted(mContext, accountId, tag);
|
||||||
/**
|
|
||||||
* Note: The somewhat tortured logic here is to guarantee proper ordering of events:
|
|
||||||
* listeners: checkMailStarted
|
|
||||||
* account 1: list folders
|
|
||||||
* account 1: sync messages
|
|
||||||
* account 2: list folders
|
|
||||||
* account 2: sync messages
|
|
||||||
* ...
|
|
||||||
* account n: list folders
|
|
||||||
* account n: sync messages
|
|
||||||
* listeners: checkMailFinished
|
|
||||||
*/
|
|
||||||
mListeners.checkMailStarted(context, null); // TODO this needs to pass the actual array
|
|
||||||
if (accounts == null) {
|
|
||||||
// TODO eliminate this use case, implement, or ...?
|
|
||||||
// accounts = Preferences.getPreferences(context).getAccounts();
|
|
||||||
}
|
|
||||||
for (final EmailContent.Account account : accounts) {
|
|
||||||
listFolders(account, null);
|
|
||||||
|
|
||||||
put("checkMail", listener, new Runnable() {
|
// This puts the command on the queue (not synchronous)
|
||||||
public void run() {
|
listFolders(accountId, null);
|
||||||
sendPendingMessagesSynchronous(account);
|
|
||||||
// TODO find mailbox # for inbox and sync it.
|
// Put this on the queue as well so it follows listFolders
|
||||||
// synchronizeMailboxSynchronous(account, Email.INBOX);
|
put("emptyTrash", listener, new Runnable() {
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
put("checkMailFinished", listener, new Runnable() {
|
|
||||||
public void run() {
|
public void run() {
|
||||||
mListeners.checkMailFinished(context, null); // TODO this needs to pass actual array
|
EmailContent.Account account =
|
||||||
|
EmailContent.Account.restoreAccountWithId(mContext, accountId);
|
||||||
|
sendPendingMessagesSynchronous(account);
|
||||||
|
// find mailbox # for inbox and sync it.
|
||||||
|
// TODO we already know this in Controller, can we pass it in?
|
||||||
|
long inboxId = Mailbox.findMailboxOfType(mContext, accountId, Mailbox.TYPE_INBOX);
|
||||||
|
EmailContent.Mailbox mailbox =
|
||||||
|
EmailContent.Mailbox.restoreMailboxWithId(mContext, inboxId);
|
||||||
|
synchronizeMailboxSynchronous(account, mailbox);
|
||||||
|
|
||||||
|
mListeners.checkMailFinished(mContext, accountId, tag, inboxId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -71,13 +71,10 @@ public class MessagingListener {
|
|||||||
String message) {
|
String message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkMailStarted(Context context, EmailContent.Account account) {
|
public void checkMailStarted(Context context, long accountId, long tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkMailFinished(Context context, EmailContent.Account account) {
|
public void checkMailFinished(Context context, long accountId, long folderId, long tag) {
|
||||||
}
|
|
||||||
|
|
||||||
public void checkMailFailed(Context context, EmailContent.Account account, String reason) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPendingMessagesCompleted(EmailContent.Account account) {
|
public void sendPendingMessagesCompleted(EmailContent.Account account) {
|
||||||
|
@ -611,23 +611,34 @@ public class AccountFolderList extends ListActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for async Controller results. This is all a placeholder until we figure out the
|
* Callback for async Controller results.
|
||||||
* final way to do this.
|
|
||||||
*/
|
*/
|
||||||
private class ControllerResults implements Controller.Result {
|
private class ControllerResults implements Controller.Result {
|
||||||
public void updateMailboxListCallback(MessagingException result, long accountKey,
|
public void updateMailboxListCallback(MessagingException result, long accountKey,
|
||||||
int progress) {
|
int progress) {
|
||||||
mHandler.progress(false);
|
if (progress == 0) {
|
||||||
|
mHandler.progress(true);
|
||||||
|
} else if (result != null || progress == 100) {
|
||||||
|
mHandler.progress(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
public void updateMailboxCallback(MessagingException result, long accountKey,
|
||||||
long mailboxKey, int progress, int totalMessagesInMailbox, int numNewMessages) {
|
long mailboxKey, int progress, int numNewMessages) {
|
||||||
mHandler.progress(false);
|
if (progress == 0) {
|
||||||
|
mHandler.progress(true);
|
||||||
|
} else if (result != null || progress == 100) {
|
||||||
|
mHandler.progress(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAttachmentCallback(MessagingException result, long messageId,
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
long attachmentId, int progress) {
|
long attachmentId, int progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static class AccountsAdapter extends CursorAdapter {
|
/* package */ static class AccountsAdapter extends CursorAdapter {
|
||||||
|
@ -755,14 +755,14 @@ public class FolderMessageList extends ExpandableListActivity {
|
|||||||
private void doRefreshOpenMailbox() {
|
private void doRefreshOpenMailbox() {
|
||||||
if (this.mExpandedGroup != -1) {
|
if (this.mExpandedGroup != -1) {
|
||||||
Cursor mailboxCursor = mNewAdapter.getGroup(mExpandedGroup);
|
Cursor mailboxCursor = mNewAdapter.getGroup(mExpandedGroup);
|
||||||
EmailContent.Mailbox mailbox =
|
// EmailContent.Mailbox mailbox =
|
||||||
EmailContent.getContent(mailboxCursor, EmailContent.Mailbox.class);
|
// EmailContent.getContent(mailboxCursor, EmailContent.Mailbox.class);
|
||||||
|
//
|
||||||
if (mailbox != null) {
|
// if (mailbox != null) {
|
||||||
mHandler.progress(true);
|
// mHandler.progress(true);
|
||||||
Controller.getInstance(getApplication()).
|
// Controller.getInstance(getApplication()).
|
||||||
updateMailbox(mAccount.mId, mailbox, mControllerCallback);
|
// updateMailbox(mAccount.mId, mailbox, mControllerCallback);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,13 +778,17 @@ public class FolderMessageList extends ExpandableListActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
public void updateMailboxCallback(MessagingException result, long accountKey,
|
||||||
long mailboxKey, int progress, int totalMessagesInMailbox, int numNewMessages) {
|
long mailboxKey, int progress, int numNewMessages) {
|
||||||
mHandler.progress(false);
|
mHandler.progress(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAttachmentCallback(MessagingException result, long messageId,
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
long attachmentId, int progress) {
|
long attachmentId, int progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -275,8 +275,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
|
|||||||
Controller controller = Controller.getInstance(getApplication());
|
Controller controller = Controller.getInstance(getApplication());
|
||||||
mHandler.progress(true);
|
mHandler.progress(true);
|
||||||
if (mailboxId >= 0) {
|
if (mailboxId >= 0) {
|
||||||
Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mailboxId);
|
controller.updateMailbox(mAccountId, mailboxId, mControllerCallback);
|
||||||
controller.updateMailbox(mAccountId, mailbox, mControllerCallback);
|
|
||||||
} else {
|
} else {
|
||||||
controller.updateMailboxList(mAccountId, mControllerCallback);
|
controller.updateMailboxList(mAccountId, mControllerCallback);
|
||||||
}
|
}
|
||||||
@ -376,8 +375,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
|
|||||||
if (accountKey == mAccountId) {
|
if (accountKey == mAccountId) {
|
||||||
if (progress == 0) {
|
if (progress == 0) {
|
||||||
mHandler.progress(true);
|
mHandler.progress(true);
|
||||||
}
|
} else if (result != null || progress == 100) {
|
||||||
else if (result != null || progress == 100) {
|
|
||||||
mHandler.progress(false);
|
mHandler.progress(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,12 +383,11 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
|
|||||||
|
|
||||||
// TODO report errors into UI
|
// TODO report errors into UI
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
public void updateMailboxCallback(MessagingException result, long accountKey,
|
||||||
long mailboxKey, int progress, int totalMessagesInMailbox, int numNewMessages) {
|
long mailboxKey, int progress, int numNewMessages) {
|
||||||
if (accountKey == mAccountId) {
|
if (accountKey == mAccountId) {
|
||||||
if (progress == 0) {
|
if (progress == 0) {
|
||||||
mHandler.progress(true);
|
mHandler.progress(true);
|
||||||
}
|
} else if (result != null || progress == 100) {
|
||||||
else if (result != null || progress == 100) {
|
|
||||||
mHandler.progress(false);
|
mHandler.progress(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,6 +396,10 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
|
|||||||
public void loadAttachmentCallback(MessagingException result, long messageId,
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
long attachmentId, int progress) {
|
long attachmentId, int progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,14 +20,10 @@ import com.android.email.Controller;
|
|||||||
import com.android.email.Email;
|
import com.android.email.Email;
|
||||||
import com.android.email.EmailAddressAdapter;
|
import com.android.email.EmailAddressAdapter;
|
||||||
import com.android.email.EmailAddressValidator;
|
import com.android.email.EmailAddressValidator;
|
||||||
import com.android.email.MessagingController;
|
|
||||||
import com.android.email.R;
|
import com.android.email.R;
|
||||||
import com.android.email.Utility;
|
import com.android.email.Utility;
|
||||||
import com.android.email.mail.Address;
|
import com.android.email.mail.Address;
|
||||||
import com.android.email.mail.MessagingException;
|
import com.android.email.mail.MessagingException;
|
||||||
import com.android.email.mail.Multipart;
|
|
||||||
import com.android.email.mail.Part;
|
|
||||||
import com.android.email.mail.Message.RecipientType;
|
|
||||||
import com.android.email.mail.internet.EmailHtmlUtil;
|
import com.android.email.mail.internet.EmailHtmlUtil;
|
||||||
import com.android.email.mail.internet.MimeUtility;
|
import com.android.email.mail.internet.MimeUtility;
|
||||||
import com.android.email.provider.EmailContent;
|
import com.android.email.provider.EmailContent;
|
||||||
@ -56,7 +52,6 @@ import android.text.SpannableStringBuilder;
|
|||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.text.util.Rfc822Tokenizer;
|
import android.text.util.Rfc822Tokenizer;
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -72,7 +67,6 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.MultiAutoCompleteTextView;
|
import android.widget.MultiAutoCompleteTextView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import android.widget.AutoCompleteTextView.Validator;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
@ -1232,12 +1226,16 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountId,
|
public void updateMailboxCallback(MessagingException result, long accountId,
|
||||||
long mailboxId, int progress, int totalMessagesInMailbox, int numNewMessages) {
|
long mailboxId, int progress, int numNewMessages) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAttachmentCallback(MessagingException result, long messageId,
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
long attachmentId, int progress) {
|
long attachmentId, int progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// class Listener extends MessagingListener {
|
// class Listener extends MessagingListener {
|
||||||
|
@ -28,8 +28,10 @@ import com.android.email.provider.EmailContent.Mailbox;
|
|||||||
import com.android.email.provider.EmailContent.MailboxColumns;
|
import com.android.email.provider.EmailContent.MailboxColumns;
|
||||||
import com.android.email.provider.EmailContent.Message;
|
import com.android.email.provider.EmailContent.Message;
|
||||||
import com.android.email.provider.EmailContent.MessageColumns;
|
import com.android.email.provider.EmailContent.MessageColumns;
|
||||||
|
import com.android.email.service.MailService;
|
||||||
|
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
|
import android.app.NotificationManager;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -180,13 +182,15 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
* notifications.
|
* notifications.
|
||||||
*
|
*
|
||||||
* @param context The caller's context (for generating an intent)
|
* @param context The caller's context (for generating an intent)
|
||||||
* @param accountId The account to open
|
* @param accountId The account to open, or -1
|
||||||
* @param mailboxType the type of mailbox to open (e.g. @see EmailContent.Mailbox.TYPE_INBOX)
|
* @param mailboxId the ID of the mailbox to open, or -1
|
||||||
|
* @param mailboxType the type of mailbox to open (e.g. @see Mailbox.TYPE_INBOX) or -1
|
||||||
*/
|
*/
|
||||||
public static Intent actionHandleAccountIntent(Context context, long accountId,
|
public static Intent actionHandleAccountIntent(Context context, long accountId,
|
||||||
int mailboxType) {
|
long mailboxId, int mailboxType) {
|
||||||
Intent intent = new Intent(context, MessageList.class);
|
Intent intent = new Intent(context, MessageList.class);
|
||||||
intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
|
intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
|
||||||
|
intent.putExtra(EXTRA_MAILBOX_ID, mailboxId);
|
||||||
intent.putExtra(EXTRA_MAILBOX_TYPE, mailboxType);
|
intent.putExtra(EXTRA_MAILBOX_TYPE, mailboxType);
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
@ -201,7 +205,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
*/
|
*/
|
||||||
public static Intent actionHandleAccountUriIntent(Context context, long accountId,
|
public static Intent actionHandleAccountUriIntent(Context context, long accountId,
|
||||||
int mailboxType) {
|
int mailboxType) {
|
||||||
Intent i = actionHandleAccountIntent(context, accountId, mailboxType);
|
Intent i = actionHandleAccountIntent(context, accountId, -1, mailboxType);
|
||||||
i.removeExtra(EXTRA_ACCOUNT_ID);
|
i.removeExtra(EXTRA_ACCOUNT_ID);
|
||||||
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
||||||
i.setData(uri);
|
i.setData(uri);
|
||||||
@ -241,7 +245,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
// Specific mailbox ID was provided - go directly to it
|
// Specific mailbox ID was provided - go directly to it
|
||||||
mSetTitleTask = new SetTitleTask(mMailboxId);
|
mSetTitleTask = new SetTitleTask(mMailboxId);
|
||||||
mSetTitleTask.execute();
|
mSetTitleTask.execute();
|
||||||
mLoadMessagesTask = new LoadMessagesTask(mMailboxId);
|
mLoadMessagesTask = new LoadMessagesTask(mMailboxId, -1);
|
||||||
mLoadMessagesTask.execute();
|
mLoadMessagesTask.execute();
|
||||||
} else {
|
} else {
|
||||||
long accountId = -1;
|
long accountId = -1;
|
||||||
@ -278,8 +282,11 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Controller.getInstance(getApplication()).addResultCallback(mControllerCallback);
|
Controller.getInstance(getApplication()).addResultCallback(mControllerCallback);
|
||||||
|
|
||||||
// TODO: may need to clear notifications here
|
// clear notifications here
|
||||||
|
NotificationManager notificationManager = (NotificationManager)
|
||||||
|
getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.cancel(MailService.NEW_MESSAGE_NOTIFICATION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -410,12 +417,11 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
|
|
||||||
private void onRefresh() {
|
private void onRefresh() {
|
||||||
// TODO: This needs to loop through all open mailboxes (there might be more than one)
|
// TODO: This needs to loop through all open mailboxes (there might be more than one)
|
||||||
// TODO: Should not be reading from DB in UI thread
|
// TODO: Should not be reading from DB in UI thread - need a cleaner way to get accountId
|
||||||
if (mMailboxId >= 0) {
|
if (mMailboxId >= 0) {
|
||||||
EmailContent.Mailbox mailbox =
|
Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mMailboxId);
|
||||||
EmailContent.Mailbox.restoreMailboxWithId(this, mMailboxId);
|
|
||||||
Controller.getInstance(getApplication()).updateMailbox(
|
Controller.getInstance(getApplication()).updateMailbox(
|
||||||
mailbox.mAccountKey, mailbox, mControllerCallback);
|
mailbox.mAccountKey, mMailboxId, mControllerCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,7 +657,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
mMailboxId = mailboxId;
|
mMailboxId = mailboxId;
|
||||||
mSetTitleTask = new SetTitleTask(mMailboxId);
|
mSetTitleTask = new SetTitleTask(mMailboxId);
|
||||||
mSetTitleTask.execute();
|
mSetTitleTask.execute();
|
||||||
mLoadMessagesTask = new LoadMessagesTask(mMailboxId);
|
mLoadMessagesTask = new LoadMessagesTask(mMailboxId, mAccountId);
|
||||||
mLoadMessagesTask.execute();
|
mLoadMessagesTask.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,12 +675,14 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
private class LoadMessagesTask extends AsyncTask<Void, Void, Cursor> {
|
private class LoadMessagesTask extends AsyncTask<Void, Void, Cursor> {
|
||||||
|
|
||||||
private long mMailboxKey;
|
private long mMailboxKey;
|
||||||
|
private long mAccountKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special constructor to cache some local info
|
* Special constructor to cache some local info
|
||||||
*/
|
*/
|
||||||
public LoadMessagesTask(long mailboxKey) {
|
public LoadMessagesTask(long mailboxKey, long accountKey) {
|
||||||
mMailboxKey = mailboxKey;
|
mMailboxKey = mailboxKey;
|
||||||
|
mAccountKey = accountKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -743,6 +751,13 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
if (cursor != null && cursor.getCount() == 0) {
|
if (cursor != null && cursor.getCount() == 0) {
|
||||||
onRefresh();
|
onRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the "new messages" count in the service, since we're seeing them now
|
||||||
|
if (mMailboxKey == QUERY_ALL_INBOXES) {
|
||||||
|
MailService.resetNewMessageCount(-1);
|
||||||
|
} else if (mMailboxKey >= 0 && mAccountKey != -1) {
|
||||||
|
MailService.resetNewMessageCount(mAccountKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,8 +881,7 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
int progress) {
|
int progress) {
|
||||||
if (progress == 0) {
|
if (progress == 0) {
|
||||||
mHandler.progress(true);
|
mHandler.progress(true);
|
||||||
}
|
} else if (result != null || progress == 100) {
|
||||||
else if (result != null || progress == 100) {
|
|
||||||
mHandler.progress(false);
|
mHandler.progress(false);
|
||||||
if (mWaitForMailboxType != -1) {
|
if (mWaitForMailboxType != -1) {
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
@ -880,11 +894,10 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
// TODO report errors into UI
|
// TODO report errors into UI
|
||||||
// TODO check accountKey and only react to relevant notifications
|
// TODO check accountKey and only react to relevant notifications
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
public void updateMailboxCallback(MessagingException result, long accountKey,
|
||||||
long mailboxKey, int progress, int totalMessagesInMailbox, int numNewMessages) {
|
long mailboxKey, int progress, int numNewMessages) {
|
||||||
if (progress == 0) {
|
if (progress == 0) {
|
||||||
mHandler.progress(true);
|
mHandler.progress(true);
|
||||||
}
|
} else if (result != null || progress == 100) {
|
||||||
else if (result != null || progress == 100) {
|
|
||||||
mHandler.progress(false);
|
mHandler.progress(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -892,6 +905,10 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
|
|||||||
public void loadAttachmentCallback(MessagingException result, long messageId,
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
long attachmentId, int progress) {
|
long attachmentId, int progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,10 +25,8 @@ import com.android.email.Utility;
|
|||||||
import com.android.email.mail.Address;
|
import com.android.email.mail.Address;
|
||||||
import com.android.email.mail.MessagingException;
|
import com.android.email.mail.MessagingException;
|
||||||
import com.android.email.mail.Part;
|
import com.android.email.mail.Part;
|
||||||
import com.android.email.mail.Message.RecipientType;
|
|
||||||
import com.android.email.mail.internet.EmailHtmlUtil;
|
import com.android.email.mail.internet.EmailHtmlUtil;
|
||||||
import com.android.email.mail.internet.MimeUtility;
|
import com.android.email.mail.internet.MimeUtility;
|
||||||
import com.android.email.mail.store.LocalStore.LocalMessage;
|
|
||||||
import com.android.email.provider.AttachmentProvider;
|
import com.android.email.provider.AttachmentProvider;
|
||||||
import com.android.email.provider.EmailContent.Account;
|
import com.android.email.provider.EmailContent.Account;
|
||||||
import com.android.email.provider.EmailContent.Attachment;
|
import com.android.email.provider.EmailContent.Attachment;
|
||||||
@ -59,7 +57,6 @@ import android.provider.Contacts;
|
|||||||
import android.provider.Contacts.Intents;
|
import android.provider.Contacts.Intents;
|
||||||
import android.provider.Contacts.People;
|
import android.provider.Contacts.People;
|
||||||
import android.text.util.Regex;
|
import android.text.util.Regex;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -1227,12 +1224,16 @@ public class MessageView extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountId,
|
public void updateMailboxCallback(MessagingException result, long accountId,
|
||||||
long mailboxId, int progress, int totalMessagesInMailbox, int numNewMessages) {
|
long mailboxId, int progress, int numNewMessages) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMailboxListCallback(MessagingException result, long accountId,
|
public void updateMailboxListCallback(MessagingException result, long accountId,
|
||||||
int progress) {
|
int progress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -242,27 +242,6 @@ public abstract class Store {
|
|||||||
|
|
||||||
public abstract void checkSettings() throws MessagingException;
|
public abstract void checkSettings() throws MessagingException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable or disable push mode delivery for a given Store.
|
|
||||||
*
|
|
||||||
* <p>For protocols that do not support push mode, be sure that push="true" is not
|
|
||||||
* set by the stores.xml definition file(s). This function need not be implemented.
|
|
||||||
*
|
|
||||||
* <p>For protocols that do support push mode, this will be called at startup (boot) time
|
|
||||||
* so that the Store can launch its own underlying connection service. It will also be called
|
|
||||||
* any time the user changes the settings for the account (because the user may switch back
|
|
||||||
* to polling mode (or disable checking completely).
|
|
||||||
*
|
|
||||||
* <p>This API will be called repeatedly, even after push mode has already been started or
|
|
||||||
* stopped. Stores that support push mode should return quickly if the configuration has not
|
|
||||||
* changed.
|
|
||||||
*
|
|
||||||
* @param enablePushMode start or stop push mode delivery
|
|
||||||
*/
|
|
||||||
public void enablePushModeDelivery(boolean enablePushMode) {
|
|
||||||
// does nothing for non-push protocols
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete Store and its corresponding resources.
|
* Delete Store and its corresponding resources.
|
||||||
* @throws MessagingException
|
* @throws MessagingException
|
||||||
|
@ -49,8 +49,6 @@ public class ExchangeStoreExample extends Store {
|
|||||||
private final ExchangeTransportExample mTransport;
|
private final ExchangeTransportExample mTransport;
|
||||||
private final HashMap<String, Folder> mFolders = new HashMap<String, Folder>();
|
private final HashMap<String, Folder> mFolders = new HashMap<String, Folder>();
|
||||||
|
|
||||||
private boolean mPushModeRunning = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method.
|
* Factory method.
|
||||||
*/
|
*/
|
||||||
@ -120,30 +118,7 @@ public class ExchangeStoreExample extends Store {
|
|||||||
getFolder(ExchangeTransportExample.FOLDER_INBOX),
|
getFolder(ExchangeTransportExample.FOLDER_INBOX),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For a store that supports push mode, this is the API that enables it or disables it.
|
|
||||||
* The store should use this API to start or stop its persistent connection service or thread.
|
|
||||||
*
|
|
||||||
* <p>Note, may be called multiple times, even after push mode has been started or stopped.
|
|
||||||
*
|
|
||||||
* @param enablePushMode start or stop push mode delivery
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void enablePushModeDelivery(boolean enablePushMode) {
|
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
|
||||||
if (enablePushMode && !mPushModeRunning) {
|
|
||||||
Log.d(Email.LOG_TAG, "start push mode");
|
|
||||||
} else if (!enablePushMode && mPushModeRunning) {
|
|
||||||
Log.d(Email.LOG_TAG, "stop push mode");
|
|
||||||
} else {
|
|
||||||
Log.d(Email.LOG_TAG, enablePushMode ?
|
|
||||||
"push mode already started" : "push mode already stopped");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPushModeRunning = enablePushMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get class of SettingActivity for this Store class.
|
* Get class of SettingActivity for this Store class.
|
||||||
* @return Activity class that has class method actionEditIncomingSettings().
|
* @return Activity class that has class method actionEditIncomingSettings().
|
||||||
|
@ -41,7 +41,6 @@ import android.content.Context;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -64,8 +63,6 @@ public class ExchangeStore extends Store {
|
|||||||
private final ExchangeTransport mTransport;
|
private final ExchangeTransport mTransport;
|
||||||
private final HashMap<String, Folder> mFolders = new HashMap<String, Folder>();
|
private final HashMap<String, Folder> mFolders = new HashMap<String, Folder>();
|
||||||
|
|
||||||
private boolean mPushModeRunning = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method.
|
* Factory method.
|
||||||
*/
|
*/
|
||||||
@ -164,29 +161,6 @@ public class ExchangeStore extends Store {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For a store that supports push mode, this is the API that enables it or disables it.
|
|
||||||
* The store should use this API to start or stop its persistent connection service or thread.
|
|
||||||
*
|
|
||||||
* <p>Note, may be called multiple times, even after push mode has been started or stopped.
|
|
||||||
*
|
|
||||||
* @param enablePushMode start or stop push mode delivery
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void enablePushModeDelivery(boolean enablePushMode) {
|
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
|
||||||
if (enablePushMode && !mPushModeRunning) {
|
|
||||||
Log.d(Email.LOG_TAG, "start push mode");
|
|
||||||
} else if (!enablePushMode && mPushModeRunning) {
|
|
||||||
Log.d(Email.LOG_TAG, "stop push mode");
|
|
||||||
} else {
|
|
||||||
Log.d(Email.LOG_TAG, enablePushMode ?
|
|
||||||
"push mode already started" : "push mode already stopped");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPushModeRunning = enablePushMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get class of SettingActivity for this Store class.
|
* Get class of SettingActivity for this Store class.
|
||||||
* @return Activity class that has class method actionEditIncomingSettings()
|
* @return Activity class that has class method actionEditIncomingSettings()
|
||||||
|
@ -16,52 +16,60 @@
|
|||||||
|
|
||||||
package com.android.email.service;
|
package com.android.email.service;
|
||||||
|
|
||||||
import com.android.email.Account;
|
import com.android.email.Controller;
|
||||||
import com.android.email.Email;
|
import com.android.email.Email;
|
||||||
import com.android.email.MessagingController;
|
|
||||||
import com.android.email.MessagingListener;
|
|
||||||
import com.android.email.R;
|
import com.android.email.R;
|
||||||
import com.android.email.activity.AccountFolderList;
|
|
||||||
import com.android.email.activity.MessageList;
|
import com.android.email.activity.MessageList;
|
||||||
import com.android.email.mail.MessagingException;
|
import com.android.email.mail.MessagingException;
|
||||||
import com.android.email.mail.Store;
|
import com.android.email.provider.EmailContent.Account;
|
||||||
import com.android.email.mail.store.LocalStore;
|
import com.android.email.provider.EmailContent.Mailbox;
|
||||||
import com.android.email.provider.EmailContent;
|
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.ContentUris;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Config;
|
import android.util.Config;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Background service for refreshing non-push email accounts.
|
||||||
*/
|
*/
|
||||||
public class MailService extends Service {
|
public class MailService extends Service {
|
||||||
|
/** DO NOT CHECK IN "TRUE" */
|
||||||
|
private static final boolean DEBUG_FORCE_QUICK_REFRESH = false; // force 1-minute refresh
|
||||||
|
|
||||||
|
public static int NEW_MESSAGE_NOTIFICATION_ID = 1;
|
||||||
|
|
||||||
private static final String ACTION_CHECK_MAIL =
|
private static final String ACTION_CHECK_MAIL =
|
||||||
"com.android.email.intent.action.MAIL_SERVICE_WAKEUP";
|
"com.android.email.intent.action.MAIL_SERVICE_WAKEUP";
|
||||||
private static final String ACTION_RESCHEDULE =
|
private static final String ACTION_RESCHEDULE =
|
||||||
"com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE";
|
"com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE";
|
||||||
private static final String ACTION_CANCEL =
|
private static final String ACTION_CANCEL =
|
||||||
"com.android.email.intent.action.MAIL_SERVICE_CANCEL";
|
"com.android.email.intent.action.MAIL_SERVICE_CANCEL";
|
||||||
|
|
||||||
private static final String EXTRA_CHECK_ACCOUNT = "com.android.email.intent.extra.ACCOUNT";
|
|
||||||
|
|
||||||
private Listener mListener = new Listener();
|
private static final String EXTRA_CHECK_ACCOUNT = "com.android.email.intent.extra.ACCOUNT";
|
||||||
|
private static final String EXTRA_ACCOUNT_INFO = "com.android.email.intent.extra.ACCOUNT_INFO";
|
||||||
|
|
||||||
|
private Controller.Result mControllerCallback = new ControllerResults();
|
||||||
|
|
||||||
private int mStartId;
|
private int mStartId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access must be synchronized, because there are accesses from the Controller callback
|
||||||
|
*/
|
||||||
|
private static HashMap<Long,AccountSyncReport> mSyncReports =
|
||||||
|
new HashMap<Long,AccountSyncReport>();
|
||||||
|
|
||||||
public static void actionReschedule(Context context) {
|
public static void actionReschedule(Context context) {
|
||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setClass(context, MailService.class);
|
i.setClass(context, MailService.class);
|
||||||
@ -75,6 +83,23 @@ public class MailService extends Service {
|
|||||||
i.setAction(MailService.ACTION_CANCEL);
|
i.setAction(MailService.ACTION_CANCEL);
|
||||||
context.startService(i);
|
context.startService(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset new message counts for one or all accounts
|
||||||
|
*
|
||||||
|
* TODO what about EAS service new message counts, where are they reset?
|
||||||
|
*
|
||||||
|
* @param accountId account to clear, or -1 for all accounts
|
||||||
|
*/
|
||||||
|
public static void resetNewMessageCount(long accountId) {
|
||||||
|
synchronized (mSyncReports) {
|
||||||
|
for (AccountSyncReport report : mSyncReports.values()) {
|
||||||
|
if (accountId == -1 || accountId == report.accountId) {
|
||||||
|
report.numNewMessages = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point for asynchronous message services (e.g. push mode) to post notifications of new
|
* Entry point for asynchronous message services (e.g. push mode) to post notifications of new
|
||||||
@ -82,66 +107,44 @@ public class MailService extends Service {
|
|||||||
* which will attempt to load the new messages. So the Store should expect to be opened and
|
* which will attempt to load the new messages. So the Store should expect to be opened and
|
||||||
* fetched from shortly after making this call.
|
* fetched from shortly after making this call.
|
||||||
*
|
*
|
||||||
* @param storeUri the Uri of the store that is reporting new messages
|
* @param accountId the id of the account that is reporting new messages
|
||||||
*/
|
*/
|
||||||
public static void actionNotifyNewMessages(Context context, String storeUri) {
|
public static void actionNotifyNewMessages(Context context, long accountId) {
|
||||||
Intent i = new Intent(ACTION_CHECK_MAIL);
|
Intent i = new Intent(ACTION_CHECK_MAIL);
|
||||||
i.setClass(context, MailService.class);
|
i.setClass(context, MailService.class);
|
||||||
i.putExtra(EXTRA_CHECK_ACCOUNT, storeUri);
|
i.putExtra(EXTRA_CHECK_ACCOUNT, accountId);
|
||||||
context.startService(i);
|
context.startService(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart(Intent intent, int startId) {
|
public void onStart(Intent intent, int startId) {
|
||||||
super.onStart(intent, startId);
|
super.onStart(intent, startId);
|
||||||
|
|
||||||
|
// TODO this needs to be passed through the controller and back to us
|
||||||
this.mStartId = startId;
|
this.mStartId = startId;
|
||||||
|
|
||||||
MessagingController controller = MessagingController.getInstance(getApplication());
|
Controller controller = Controller.getInstance(getApplication());
|
||||||
controller.addListener(mListener);
|
controller.addResultCallback(mControllerCallback);
|
||||||
|
|
||||||
if (ACTION_CHECK_MAIL.equals(intent.getAction())) {
|
if (ACTION_CHECK_MAIL.equals(intent.getAction())) {
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
if (Config.LOGD && Email.DEBUG) {
|
||||||
Log.d(Email.LOG_TAG, "*** MailService: checking mail");
|
Log.d(Email.LOG_TAG, "*** MailService: checking mail");
|
||||||
}
|
}
|
||||||
// Only check mail for accounts that have enabled automatic checking. There is still
|
// If we have the data, restore the last-sync-times for each account
|
||||||
// a bug here in that we check every enabled account, on every refresh - irrespective
|
// These are cached in the wakeup intent in case the process was killed.
|
||||||
// of that account's refresh frequency - but this fixes the worst case of checking
|
restoreSyncReports(intent);
|
||||||
// accounts that should not have been checked at all.
|
|
||||||
// Also note: Due to the organization of this service, you must gather the accounts
|
|
||||||
// and make a single call to controller.checkMail().
|
|
||||||
|
|
||||||
// TODO: Notification for single push account will fire up checks on all other
|
// Sync a specific account if given
|
||||||
// accounts. This needs to be cleaned up for better efficiency.
|
long checkAccountId = intent.getLongExtra(EXTRA_CHECK_ACCOUNT, -1);
|
||||||
String specificStoreUri = intent.getStringExtra(EXTRA_CHECK_ACCOUNT);
|
if (checkAccountId != -1) {
|
||||||
|
// launch an account sync in the controller
|
||||||
ArrayList<EmailContent.Account> accountsToCheck = new ArrayList<EmailContent.Account>();
|
syncOneAccount(controller, checkAccountId, startId);
|
||||||
|
} else {
|
||||||
Cursor c = null;
|
// Find next account to sync, and reschedule
|
||||||
try {
|
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
||||||
c = this.getContentResolver().query(
|
reschedule(alarmManager);
|
||||||
EmailContent.Account.CONTENT_URI,
|
stopSelf(startId);
|
||||||
EmailContent.Account.CONTENT_PROJECTION,
|
|
||||||
null, null, null);
|
|
||||||
while (c.moveToNext()) {
|
|
||||||
EmailContent.Account account = EmailContent.getContent(c,
|
|
||||||
EmailContent.Account.class);
|
|
||||||
int interval = account.getSyncInterval();
|
|
||||||
String storeUri = account.getStoreUri(this);
|
|
||||||
if (interval > 0 || (storeUri != null && storeUri.equals(specificStoreUri))) {
|
|
||||||
accountsToCheck.add(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each account, switch pushmail on or off
|
|
||||||
enablePushMail(account, interval == EmailContent.Account.CHECK_INTERVAL_PUSH);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (c != null) {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmailContent.Account[] accounts = accountsToCheck.toArray(
|
|
||||||
new EmailContent.Account[accountsToCheck.size()]);
|
|
||||||
controller.checkMail(this, accounts, mListener);
|
|
||||||
}
|
}
|
||||||
else if (ACTION_CANCEL.equals(intent.getAction())) {
|
else if (ACTION_CANCEL.equals(intent.getAction())) {
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
if (Config.LOGD && Email.DEBUG) {
|
||||||
@ -154,186 +157,366 @@ public class MailService extends Service {
|
|||||||
if (Config.LOGD && Email.DEBUG) {
|
if (Config.LOGD && Email.DEBUG) {
|
||||||
Log.d(Email.LOG_TAG, "*** MailService: reschedule");
|
Log.d(Email.LOG_TAG, "*** MailService: reschedule");
|
||||||
}
|
}
|
||||||
reschedule();
|
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
||||||
|
reschedule(alarmManager);
|
||||||
stopSelf(startId);
|
stopSelf(startId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
MessagingController.getInstance(getApplication()).removeListener(mListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancel() {
|
|
||||||
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
|
||||||
Intent i = new Intent();
|
|
||||||
i.setClassName("com.android.email", "com.android.email.service.MailService");
|
|
||||||
i.setAction(ACTION_CHECK_MAIL);
|
|
||||||
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
|
|
||||||
alarmMgr.cancel(pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reschedule() {
|
|
||||||
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
|
||||||
Intent i = new Intent();
|
|
||||||
i.setClassName("com.android.email", "com.android.email.service.MailService");
|
|
||||||
i.setAction(ACTION_CHECK_MAIL);
|
|
||||||
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
|
|
||||||
|
|
||||||
int shortestInterval = -1;
|
|
||||||
Cursor c = null;
|
|
||||||
try {
|
|
||||||
c = this.getContentResolver().query(
|
|
||||||
EmailContent.Account.CONTENT_URI,
|
|
||||||
EmailContent.Account.CONTENT_PROJECTION,
|
|
||||||
null, null, null);
|
|
||||||
while (c.moveToNext()) {
|
|
||||||
EmailContent.Account account = EmailContent.getContent(c,
|
|
||||||
EmailContent.Account.class);
|
|
||||||
int interval = account.getSyncInterval();
|
|
||||||
if (interval > 0 && (interval < shortestInterval || shortestInterval == -1)) {
|
|
||||||
shortestInterval = interval;
|
|
||||||
}
|
|
||||||
enablePushMail(account, interval == Account.CHECK_INTERVAL_PUSH);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (c != null) {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shortestInterval == -1) {
|
|
||||||
alarmMgr.cancel(pi);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
|
|
||||||
+ (shortestInterval * (60 * 1000)), pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Listener extends MessagingListener {
|
@Override
|
||||||
HashMap<EmailContent.Account, Integer> accountsWithNewMail =
|
public void onDestroy() {
|
||||||
new HashMap<EmailContent.Account, Integer>();
|
super.onDestroy();
|
||||||
|
Controller.getInstance(getApplication()).removeResultCallback(mControllerCallback);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO this should be redone because account is usually null, not very interesting.
|
private void cancel() {
|
||||||
// I think it would make more sense to pass Account[] here in case anyone uses it
|
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
||||||
// In any case, it should be noticed that this is called once per cycle
|
PendingIntent pi = createAlarmIntent(-1, null);
|
||||||
@Override
|
alarmMgr.cancel(pi);
|
||||||
public void checkMailStarted(Context context, EmailContent.Account account) {
|
}
|
||||||
accountsWithNewMail.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called once per checked account
|
/**
|
||||||
@Override
|
* Create and send an alarm with the entire list. This also sends a list of known last-sync
|
||||||
public void checkMailFailed(Context context, EmailContent.Account account, String reason) {
|
* times with the alarm, so if we are killed between alarms, we don't lose this info.
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
*
|
||||||
Log.d(Email.LOG_TAG, "*** MailService: checkMailFailed: " + reason);
|
* @param alarmMgr passed in so we can mock for testing.
|
||||||
}
|
*/
|
||||||
reschedule();
|
/* package */ void reschedule(AlarmManager alarmMgr) {
|
||||||
stopSelf(mStartId);
|
// restore the reports if lost
|
||||||
}
|
setupSyncReports(-1);
|
||||||
|
synchronized (mSyncReports) {
|
||||||
|
int numAccounts = mSyncReports.size();
|
||||||
|
long[] accountInfo = new long[numAccounts * 2]; // pairs of { accountId, lastSync }
|
||||||
|
int accountInfoIndex = 0;
|
||||||
|
|
||||||
// Called once per checked account
|
long nextCheckTime = Long.MAX_VALUE;
|
||||||
@Override
|
AccountSyncReport nextAccount = null;
|
||||||
public void synchronizeMailboxFinished(EmailContent.Account account,
|
long timeNow = SystemClock.elapsedRealtime();
|
||||||
EmailContent.Mailbox folder, int totalMessagesInMailbox, int numNewMessages) {
|
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
|
||||||
Log.d(Email.LOG_TAG, "*** MailService: synchronizeMailboxFinished: total=" +
|
|
||||||
totalMessagesInMailbox + " new=" + numNewMessages);
|
|
||||||
}
|
|
||||||
if (numNewMessages > 0 &&
|
|
||||||
((account.getFlags() & EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL) != 0)) {
|
|
||||||
accountsWithNewMail.put(account, numNewMessages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO this should be redone because account is usually null, not very interesting.
|
for (AccountSyncReport report : mSyncReports.values()) {
|
||||||
// I think it would make more sense to pass Account[] here in case anyone uses it
|
if (report.syncInterval <= 0) { // no timed checks - skip
|
||||||
// In any case, it should be noticed that this is called once per cycle
|
continue;
|
||||||
@Override
|
|
||||||
public void checkMailFinished(Context context, EmailContent.Account account) {
|
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
|
||||||
Log.d(Email.LOG_TAG, "*** MailService: checkMailFinished");
|
|
||||||
}
|
|
||||||
NotificationManager notifMgr = (NotificationManager)context
|
|
||||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
|
|
||||||
if (accountsWithNewMail.size() > 0) {
|
|
||||||
Notification notif = new Notification(R.drawable.stat_notify_email_generic,
|
|
||||||
getString(R.string.notification_new_title), System.currentTimeMillis());
|
|
||||||
boolean vibrate = false;
|
|
||||||
String ringtone = null;
|
|
||||||
if (accountsWithNewMail.size() > 1) {
|
|
||||||
for (EmailContent.Account account1 : accountsWithNewMail.keySet()) {
|
|
||||||
if ((account1.getFlags() & EmailContent.Account.FLAGS_VIBRATE) != 0) {
|
|
||||||
vibrate = true;
|
|
||||||
}
|
|
||||||
ringtone = account1.getRingtone();
|
|
||||||
}
|
|
||||||
Intent i = new Intent(context, AccountFolderList.class);
|
|
||||||
PendingIntent pi = PendingIntent.getActivity(context, 0, i, 0);
|
|
||||||
notif.setLatestEventInfo(context, getString(R.string.notification_new_title),
|
|
||||||
getResources().
|
|
||||||
getQuantityString(R.plurals.notification_new_multi_account_fmt,
|
|
||||||
accountsWithNewMail.size(),
|
|
||||||
accountsWithNewMail.size()), pi);
|
|
||||||
} else {
|
|
||||||
EmailContent.Account account1 = accountsWithNewMail.keySet().iterator().next();
|
|
||||||
int totalNewMails = accountsWithNewMail.get(account1);
|
|
||||||
Intent i = MessageList.actionHandleAccountIntent(context,
|
|
||||||
account1.mId, EmailContent.Mailbox.TYPE_INBOX);
|
|
||||||
PendingIntent pi = PendingIntent.getActivity(context, 0, i, 0);
|
|
||||||
notif.setLatestEventInfo(context, getString(R.string.notification_new_title),
|
|
||||||
getResources().
|
|
||||||
getQuantityString(R.plurals.notification_new_one_account_fmt,
|
|
||||||
totalNewMails, totalNewMails,
|
|
||||||
account1.getDisplayName()), pi);
|
|
||||||
vibrate = ((account1.getFlags() & EmailContent.Account.FLAGS_VIBRATE) != 0);
|
|
||||||
ringtone = account1.getRingtone();
|
|
||||||
}
|
}
|
||||||
notif.defaults = Notification.DEFAULT_LIGHTS;
|
// select next account to sync
|
||||||
notif.sound = TextUtils.isEmpty(ringtone) ? null : Uri.parse(ringtone);
|
if ((report.prevSyncTime == 0) // never checked
|
||||||
if (vibrate) {
|
|| (report.nextSyncTime < timeNow)) { // overdue
|
||||||
notif.defaults |= Notification.DEFAULT_VIBRATE;
|
nextCheckTime = 0;
|
||||||
|
nextAccount = report;
|
||||||
|
} else if (report.nextSyncTime < nextCheckTime) { // next to be checked
|
||||||
|
nextCheckTime = report.nextSyncTime;
|
||||||
|
nextAccount = report;
|
||||||
}
|
}
|
||||||
notifMgr.notify(1, notif);
|
// collect last-sync-times for all accounts
|
||||||
|
// this is using pairs of {long,long} to simplify passing in a bundle
|
||||||
|
accountInfo[accountInfoIndex++] = report.accountId;
|
||||||
|
accountInfo[accountInfoIndex++] = report.prevSyncTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
reschedule();
|
// set/clear alarm as needed
|
||||||
stopSelf(mStartId);
|
long idToCheck = (nextAccount == null) ? -1 : nextAccount.accountId;
|
||||||
|
PendingIntent pi = createAlarmIntent(idToCheck, accountInfo);
|
||||||
|
|
||||||
|
if (nextAccount == null) {
|
||||||
|
alarmMgr.cancel(pi);
|
||||||
|
Log.d(Email.LOG_TAG, "alarm cancel - no account to check");
|
||||||
|
} else {
|
||||||
|
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextCheckTime, pi);
|
||||||
|
Log.d(Email.LOG_TAG, "alarm set at " + nextCheckTime + " for " + nextAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For any account that wants push mail, get its Store and start the pushmail service.
|
* Return a pending intent for use by this alarm. Most of the fields must be the same
|
||||||
* This function makes no attempt to optimize, so accounts may have push enabled (or disabled)
|
* (in order for the intent to be recognized by the alarm manager) but the extras can
|
||||||
* repeatedly, and should handle this appropriately.
|
* be different, and are passed in here as parameters.
|
||||||
*
|
|
||||||
* @param account the account that needs push delivery enabled
|
|
||||||
*/
|
*/
|
||||||
private void enablePushMail(EmailContent.Account account, boolean enable) {
|
/* package */ PendingIntent createAlarmIntent(long checkId, long[] accountInfo) {
|
||||||
try {
|
Intent i = new Intent();
|
||||||
String localUri = account.getLocalStoreUri(this);
|
i.setClassName("com.android.email", "com.android.email.service.MailService");
|
||||||
String storeUri = account.getStoreUri(this);
|
i.setAction(ACTION_CHECK_MAIL);
|
||||||
if (localUri != null && storeUri != null) {
|
i.putExtra(EXTRA_CHECK_ACCOUNT, checkId);
|
||||||
LocalStore localStore = (LocalStore) Store.getInstance(
|
i.putExtra(EXTRA_ACCOUNT_INFO, accountInfo);
|
||||||
localUri, this.getBaseContext(), null);
|
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
|
||||||
Store store = Store.getInstance(storeUri, this.getBaseContext(),
|
return pi;
|
||||||
localStore.getPersistentCallbacks());
|
}
|
||||||
if (store != null) {
|
|
||||||
store.enablePushModeDelivery(enable);
|
/**
|
||||||
|
* Start a controller sync for a specific account
|
||||||
|
*/
|
||||||
|
private void syncOneAccount(Controller controller, long checkAccountId, int startId) {
|
||||||
|
long inboxId = Mailbox.findMailboxOfType(this, checkAccountId, Mailbox.TYPE_INBOX);
|
||||||
|
if (inboxId == Mailbox.NO_MAILBOX) {
|
||||||
|
// no inbox?? sync mailboxes
|
||||||
|
} else {
|
||||||
|
controller.serviceCheckMail(checkAccountId, inboxId, startId, mControllerCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: Times are relative to SystemClock.elapsedRealtime()
|
||||||
|
*/
|
||||||
|
private static class AccountSyncReport {
|
||||||
|
long accountId;
|
||||||
|
long prevSyncTime; // 0 == unknown
|
||||||
|
long nextSyncTime; // 0 == ASAP -1 == don't sync
|
||||||
|
int numNewMessages;
|
||||||
|
|
||||||
|
int syncInterval;
|
||||||
|
boolean notify;
|
||||||
|
boolean vibrate;
|
||||||
|
Uri ringtoneUri;
|
||||||
|
|
||||||
|
String displayName; // temporary, for debug logging
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return displayName + ": prevSync=" + prevSyncTime + " nextSync=" + nextSyncTime
|
||||||
|
+ " numNew=" + numNewMessages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scan accounts to create a list of { acct, prev sync, next sync, #new }
|
||||||
|
* use this to create a fresh copy. assumes all accounts need sync
|
||||||
|
*
|
||||||
|
* @param accountId -1 will rebuild the list if empty. other values will force loading
|
||||||
|
* of a single account (e.g if it was created after the original list population)
|
||||||
|
*/
|
||||||
|
/* package */ void setupSyncReports(long accountId) {
|
||||||
|
synchronized (mSyncReports) {
|
||||||
|
if (accountId == -1) {
|
||||||
|
// -1 == reload the list if empty, otherwise exit immediately
|
||||||
|
if (mSyncReports.size() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// load a single account if it doesn't already have a sync record
|
||||||
|
if (mSyncReports.containsKey(accountId)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (MessagingException me) {
|
|
||||||
if (Config.LOGD && Email.DEBUG) {
|
// setup to add a single account or all accounts
|
||||||
Log.d(Email.LOG_TAG, "Failed to enable push mail for account" +
|
Uri uri;
|
||||||
account.getSenderName() + " with exception " + me.toString());
|
if (accountId == -1) {
|
||||||
|
uri = Account.CONTENT_URI;
|
||||||
|
} else {
|
||||||
|
uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO use a narrower projection here
|
||||||
|
Cursor c = getContentResolver().query(uri, Account.CONTENT_PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
try {
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
AccountSyncReport report = new AccountSyncReport();
|
||||||
|
int syncInterval = c.getInt(Account.CONTENT_SYNC_INTERVAL_COLUMN);
|
||||||
|
int flags = c.getInt(Account.CONTENT_FLAGS_COLUMN);
|
||||||
|
String ringtoneString = c.getString(Account.CONTENT_RINGTONE_URI_COLUMN);
|
||||||
|
|
||||||
|
// For debugging only
|
||||||
|
if (DEBUG_FORCE_QUICK_REFRESH && syncInterval >= 0) {
|
||||||
|
syncInterval = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
report.accountId = c.getLong(Account.CONTENT_ID_COLUMN);
|
||||||
|
report.prevSyncTime = 0;
|
||||||
|
report.nextSyncTime = (syncInterval > 0) ? 0 : -1; // 0 == ASAP -1 == no sync
|
||||||
|
report.numNewMessages = 0;
|
||||||
|
|
||||||
|
report.syncInterval = syncInterval;
|
||||||
|
report.notify = (flags & Account.FLAGS_NOTIFY_NEW_MAIL) != 0;
|
||||||
|
report.vibrate = (flags & Account.FLAGS_VIBRATE) != 0;
|
||||||
|
report.ringtoneUri = (ringtoneString == null) ? null
|
||||||
|
: Uri.parse(ringtoneString);
|
||||||
|
|
||||||
|
report.displayName = c.getString(Account.CONTENT_DISPLAY_NAME_COLUMN);
|
||||||
|
|
||||||
|
// TODO lookup # new in inbox
|
||||||
|
mSyncReports.put(report.accountId, report);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update list with a single account's sync times and unread count
|
||||||
|
*
|
||||||
|
* @param accountId the account being udpated
|
||||||
|
* @param newCount the number of new messages, or -1 if not being reported (don't update)
|
||||||
|
* @return the report for the updated account, or null if it doesn't exist (e.g. deleted)
|
||||||
|
*/
|
||||||
|
/* package */ AccountSyncReport updateAccountReport(long accountId, int newCount) {
|
||||||
|
// restore the reports if lost
|
||||||
|
setupSyncReports(accountId);
|
||||||
|
synchronized (mSyncReports) {
|
||||||
|
AccountSyncReport report = mSyncReports.get(accountId);
|
||||||
|
if (report == null) {
|
||||||
|
// discard result - there is no longer an account with this id
|
||||||
|
Log.d(Email.LOG_TAG, "No account to update for id=" + Long.toString(accountId));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// report found - update it (note - editing the report while in-place in the hashmap)
|
||||||
|
report.prevSyncTime = SystemClock.elapsedRealtime();
|
||||||
|
if (report.syncInterval > 0) {
|
||||||
|
report.nextSyncTime = report.prevSyncTime + (report.syncInterval * 1000 * 60);
|
||||||
|
}
|
||||||
|
if (newCount != -1) {
|
||||||
|
report.numNewMessages = newCount;
|
||||||
|
}
|
||||||
|
Log.d(Email.LOG_TAG, "update account " + report.toString());
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when we receive an alarm, update the account sync reports list if necessary
|
||||||
|
* this will be the case when if we have restarted the process and lost the data
|
||||||
|
* in the global.
|
||||||
|
*
|
||||||
|
* @param restoreIntent the intent with the list
|
||||||
|
*/
|
||||||
|
/* package */ void restoreSyncReports(Intent restoreIntent) {
|
||||||
|
// restore the reports if lost
|
||||||
|
setupSyncReports(-1);
|
||||||
|
synchronized (mSyncReports) {
|
||||||
|
long[] accountInfo = restoreIntent.getLongArrayExtra(EXTRA_ACCOUNT_INFO);
|
||||||
|
if (accountInfo == null) {
|
||||||
|
Log.d(Email.LOG_TAG, "no data in intent to restore");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int accountInfoIndex = 0;
|
||||||
|
int accountInfoLimit = accountInfo.length;
|
||||||
|
while (accountInfoIndex < accountInfoLimit) {
|
||||||
|
long accountId = accountInfo[accountInfoIndex++];
|
||||||
|
long prevSync = accountInfo[accountInfoIndex++];
|
||||||
|
AccountSyncReport report = mSyncReports.get(accountId);
|
||||||
|
if (report != null) {
|
||||||
|
if (report.prevSyncTime == 0) {
|
||||||
|
report.prevSyncTime = prevSync;
|
||||||
|
Log.d(Email.LOG_TAG, "restore prev sync for account" + report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ControllerResults implements Controller.Result {
|
||||||
|
|
||||||
|
public void loadAttachmentCallback(MessagingException result, long messageId,
|
||||||
|
long attachmentId, int progress) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMailboxCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, int numNewMessages) {
|
||||||
|
if (result == null) {
|
||||||
|
updateAccountReport(accountId, numNewMessages);
|
||||||
|
if (numNewMessages > 0) {
|
||||||
|
notifyNewMessages(accountId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateAccountReport(accountId, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMailboxListCallback(MessagingException result, long accountId,
|
||||||
|
int progress) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
||||||
|
long mailboxId, int progress, long tag) {
|
||||||
|
if (progress == 100) {
|
||||||
|
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
||||||
|
reschedule(alarmManager);
|
||||||
|
int serviceId = MailService.this.mStartId;
|
||||||
|
if (tag != 0) {
|
||||||
|
serviceId = (int) tag;
|
||||||
|
}
|
||||||
|
stopSelf(serviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare notifications for a given new account having received mail
|
||||||
|
* The notification is organized around the account that has the new mail (e.g. selecting
|
||||||
|
* the alert preferences) but the notification will include a summary if other
|
||||||
|
* accounts also have new mail.
|
||||||
|
*/
|
||||||
|
private void notifyNewMessages(long accountId) {
|
||||||
|
boolean notify = false;
|
||||||
|
boolean vibrate = false;
|
||||||
|
Uri ringtone = null;
|
||||||
|
int accountsWithNewMessages = 0;
|
||||||
|
int numNewMessages = 0;
|
||||||
|
String reportName = null;
|
||||||
|
synchronized (mSyncReports) {
|
||||||
|
for (AccountSyncReport report : mSyncReports.values()) {
|
||||||
|
if (report.numNewMessages == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
numNewMessages += report.numNewMessages;
|
||||||
|
accountsWithNewMessages += 1;
|
||||||
|
if (report.accountId == accountId) {
|
||||||
|
notify = report.notify;
|
||||||
|
vibrate = report.vibrate;
|
||||||
|
ringtone = report.ringtoneUri;
|
||||||
|
reportName = report.displayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!notify) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up to post a notification
|
||||||
|
Intent intent;
|
||||||
|
String reportString;
|
||||||
|
|
||||||
|
if (accountsWithNewMessages == 1) {
|
||||||
|
// Prepare a report for a single account
|
||||||
|
// "12 unread (gmail)"
|
||||||
|
reportString = getResources().getQuantityString(
|
||||||
|
R.plurals.notification_new_one_account_fmt, numNewMessages,
|
||||||
|
numNewMessages, reportName);
|
||||||
|
intent = MessageList.actionHandleAccountIntent(this,
|
||||||
|
accountId, -1, Mailbox.TYPE_INBOX);
|
||||||
|
} else {
|
||||||
|
// Prepare a report for multiple accounts
|
||||||
|
// "4 accounts"
|
||||||
|
reportString = getResources().getQuantityString(
|
||||||
|
R.plurals.notification_new_multi_account_fmt, accountsWithNewMessages,
|
||||||
|
accountsWithNewMessages);
|
||||||
|
intent = MessageList.actionHandleAccountIntent(this,
|
||||||
|
-1, MessageList.QUERY_ALL_INBOXES, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare appropriate pending intent, set up notification, and send
|
||||||
|
PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
|
||||||
|
|
||||||
|
Notification notification = new Notification(
|
||||||
|
R.drawable.stat_notify_email_generic,
|
||||||
|
getString(R.string.notification_new_title),
|
||||||
|
System.currentTimeMillis());
|
||||||
|
notification.setLatestEventInfo(this,
|
||||||
|
getString(R.string.notification_new_title),
|
||||||
|
reportString,
|
||||||
|
pending);
|
||||||
|
|
||||||
|
notification.sound = ringtone;
|
||||||
|
notification.defaults = vibrate
|
||||||
|
? Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE
|
||||||
|
: Notification.DEFAULT_LIGHTS;
|
||||||
|
|
||||||
|
NotificationManager notificationManager =
|
||||||
|
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.notify(NEW_MESSAGE_NOTIFICATION_ID, notification);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,7 +472,7 @@ public class EmailSyncAdapter extends AbstractSyncAdapter {
|
|||||||
Notification notif = new Notification(R.drawable.stat_notify_email_generic,
|
Notification notif = new Notification(R.drawable.stat_notify_email_generic,
|
||||||
mContext.getString(R.string.notification_new_title),
|
mContext.getString(R.string.notification_new_title),
|
||||||
System.currentTimeMillis());
|
System.currentTimeMillis());
|
||||||
Intent i = MessageList.actionHandleAccountIntent(mContext, mAccount.mId,
|
Intent i = MessageList.actionHandleAccountIntent(mContext, mAccount.mId, -1,
|
||||||
Mailbox.TYPE_INBOX);
|
Mailbox.TYPE_INBOX);
|
||||||
PendingIntent pi = PendingIntent.getActivity(mContext, 0, i, 0);
|
PendingIntent pi = PendingIntent.getActivity(mContext, 0, i, 0);
|
||||||
notif.setLatestEventInfo(mContext,
|
notif.setLatestEventInfo(mContext,
|
||||||
|
Loading…
Reference in New Issue
Block a user