From cbe513d4305893edde60aca645b290f31f7643da Mon Sep 17 00:00:00 2001 From: Andrew Stadler Date: Tue, 18 Aug 2009 19:50:18 -0700 Subject: [PATCH] Integrate EAS push notifications with the main notifications. * Use the new account-based field for number of new messages * Add support for async notifications in MailService * Change EAS to call MailService to notify user --- .../android/email/activity/MessageList.java | 4 +- .../android/email/service/MailService.java | 62 +++++++++++++++---- .../exchange/adapter/EmailSyncAdapter.java | 46 +++++++------- 3 files changed, 75 insertions(+), 37 deletions(-) diff --git a/src/com/android/email/activity/MessageList.java b/src/com/android/email/activity/MessageList.java index dfcbae5b4..983ee74bf 100644 --- a/src/com/android/email/activity/MessageList.java +++ b/src/com/android/email/activity/MessageList.java @@ -754,9 +754,9 @@ public class MessageList extends ListActivity implements OnItemClickListener, On // Reset the "new messages" count in the service, since we're seeing them now if (mMailboxKey == QUERY_ALL_INBOXES) { - MailService.resetNewMessageCount(-1); + MailService.resetNewMessageCount(MessageList.this, -1); } else if (mMailboxKey >= 0 && mAccountKey != -1) { - MailService.resetNewMessageCount(mAccountKey); + MailService.resetNewMessageCount(MessageList.this, mAccountKey); } } } diff --git a/src/com/android/email/service/MailService.java b/src/com/android/email/service/MailService.java index 01537fd82..89cac8351 100644 --- a/src/com/android/email/service/MailService.java +++ b/src/com/android/email/service/MailService.java @@ -30,6 +30,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.ContentUris; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -56,9 +57,12 @@ public class MailService extends Service { "com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE"; private static final String ACTION_CANCEL = "com.android.email.intent.action.MAIL_SERVICE_CANCEL"; + private static final String ACTION_NOTIFY_MAIL = + "com.android.email.intent.action.MAIL_SERVICE_NOTIFY"; 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 static final String EXTRA_MESSAGE_COUNT = "com.android.email.intent.extra.COUNT"; private Controller.Result mControllerCallback = new ControllerResults(); @@ -70,6 +74,15 @@ public class MailService extends Service { private static HashMap mSyncReports = new HashMap(); + /** + * Simple template used for clearing new message count in accounts + */ + static ContentValues mClearNewMessages; + static { + mClearNewMessages = new ContentValues(); + mClearNewMessages.put(Account.NEW_MESSAGE_COUNT, 0); + } + public static void actionReschedule(Context context) { Intent i = new Intent(); i.setClass(context, MailService.class); @@ -85,13 +98,12 @@ public class MailService extends Service { } /** - * Reset new message counts for one or all accounts - * - * TODO what about EAS service new message counts, where are they reset? + * Reset new message counts for one or all accounts. This clears both our local copy and + * the values (if any) stored in the account records. * * @param accountId account to clear, or -1 for all accounts */ - public static void resetNewMessageCount(long accountId) { + public static void resetNewMessageCount(Context context, long accountId) { synchronized (mSyncReports) { for (AccountSyncReport report : mSyncReports.values()) { if (accountId == -1 || accountId == report.accountId) { @@ -99,20 +111,30 @@ public class MailService extends Service { } } } + // now do the database - all accounts, or just one of them + Uri uri; + if (accountId == -1) { + uri = Account.CONTENT_URI; + } else { + uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId); + } + context.getContentResolver().update(uri, mClearNewMessages, null, null); } /** * Entry point for asynchronous message services (e.g. push mode) to post notifications of new - * messages. Note: Although this is not a blocking call, it will start the MessagingController - * which will attempt to load the new messages. So the Store should expect to be opened and - * fetched from shortly after making this call. + * messages. This assumes that the push provider has already synced the messages into the + * appropriate database - this simply triggers the notification mechanism. * + * @param context a context * @param accountId the id of the account that is reporting new messages + * @param newCount the number of new messages */ - public static void actionNotifyNewMessages(Context context, long accountId) { - Intent i = new Intent(ACTION_CHECK_MAIL); + public static void actionNotifyNewMessages(Context context, long accountId, int newCount) { + Intent i = new Intent(ACTION_NOTIFY_MAIL); i.setClass(context, MailService.class); i.putExtra(EXTRA_CHECK_ACCOUNT, accountId); + i.putExtra(EXTRA_MESSAGE_COUNT, newCount); context.startService(i); } @@ -122,11 +144,12 @@ public class MailService extends Service { // TODO this needs to be passed through the controller and back to us this.mStartId = startId; + String action = intent.getAction(); Controller controller = Controller.getInstance(getApplication()); controller.addResultCallback(mControllerCallback); - if (ACTION_CHECK_MAIL.equals(intent.getAction())) { + if (ACTION_CHECK_MAIL.equals(action)) { if (Config.LOGD && Email.DEBUG) { Log.d(Email.LOG_TAG, "*** MailService: checking mail"); } @@ -146,23 +169,36 @@ public class MailService extends Service { stopSelf(startId); } } - else if (ACTION_CANCEL.equals(intent.getAction())) { + else if (ACTION_CANCEL.equals(action)) { if (Config.LOGD && Email.DEBUG) { Log.d(Email.LOG_TAG, "*** MailService: cancel"); } cancel(); stopSelf(startId); } - else if (ACTION_RESCHEDULE.equals(intent.getAction())) { + else if (ACTION_RESCHEDULE.equals(action)) { if (Config.LOGD && Email.DEBUG) { Log.d(Email.LOG_TAG, "*** MailService: reschedule"); } AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE); reschedule(alarmManager); stopSelf(startId); + } else if (ACTION_NOTIFY_MAIL.equals(action)) { + long accountId = intent.getLongExtra(EXTRA_CHECK_ACCOUNT, -1); + int newMessageCount = intent.getIntExtra(EXTRA_MESSAGE_COUNT, -1); + if (Config.LOGD && Email.DEBUG) { + Log.d(Email.LOG_TAG, "*** MailService: notify accountId=" + Long.toString(accountId) + + " count=" + newMessageCount); + } + if (accountId != -1) { + updateAccountReport(accountId, newMessageCount); + notifyNewMessages(accountId); + } + stopSelf(startId); } } + @Override public IBinder onBind(Intent intent) { return null; } @@ -273,6 +309,8 @@ public class MailService extends Service { String displayName; // temporary, for debug logging + + @Override public String toString() { return displayName + ": prevSync=" + prevSyncTime + " nextSync=" + nextSyncTime + " numNew=" + numNewMessages; diff --git a/src/com/android/exchange/adapter/EmailSyncAdapter.java b/src/com/android/exchange/adapter/EmailSyncAdapter.java index 3d98f15cd..328dd30a5 100644 --- a/src/com/android/exchange/adapter/EmailSyncAdapter.java +++ b/src/com/android/exchange/adapter/EmailSyncAdapter.java @@ -22,11 +22,13 @@ import com.android.email.activity.MessageList; import com.android.email.mail.Address; import com.android.email.provider.EmailContent; import com.android.email.provider.EmailProvider; +import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Attachment; import com.android.email.provider.EmailContent.Mailbox; import com.android.email.provider.EmailContent.Message; import com.android.email.provider.EmailContent.MessageColumns; import com.android.email.provider.EmailContent.SyncColumns; +import com.android.email.service.MailService; import com.android.exchange.Eas; import com.android.exchange.EasSyncService; @@ -465,31 +467,29 @@ public class EmailSyncAdapter extends AbstractSyncAdapter { } } - // TODO Remove this temporary notification code + // TODO: This should be implemented using an "add to unread messages" URI, + // and then it could be handled in the previous section as just another "op" + int totalNewCount = 0; if (notifyCount > 0) { - NotificationManager notifMgr = - (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); - Notification notif = new Notification(R.drawable.stat_notify_email_generic, - mContext.getString(R.string.notification_new_title), - System.currentTimeMillis()); - Intent i = MessageList.actionHandleAccountIntent(mContext, mAccount.mId, -1, - Mailbox.TYPE_INBOX); - PendingIntent pi = PendingIntent.getActivity(mContext, 0, i, 0); - notif.setLatestEventInfo(mContext, - mContext.getString(R.string.notification_new_title), - "You've got new mail!", pi); - boolean vibrate = ((mAccount.getFlags() & EmailContent.Account.FLAGS_VIBRATE) != 0); - String ringtone = mAccount.getRingtone(); - notif.flags = Notification.FLAG_SHOW_LIGHTS; - notif.sound = TextUtils.isEmpty(ringtone) ? null : Uri.parse(ringtone); - notif.ledARGB = 0xFF00FF00; - notif.ledOnMS = 500; - notif.ledOffMS = 500; - if (vibrate) { - notif.defaults |= Notification.DEFAULT_VIBRATE; + Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, mAccount.mId); + Cursor c = mContentResolver.query(uri, + new String[] { Account.NEW_MESSAGE_COUNT }, null, null, null); + try { + if (c.moveToNext()) { + int oldCount = c.getInt(0); + ContentValues cv = new ContentValues(); + totalNewCount = oldCount + notifyCount; + cv.put(Account.NEW_MESSAGE_COUNT, totalNewCount); + mContentResolver.update(uri, cv, null, null); + } + } finally { + c.close(); } - notifMgr.notify(1, notif); - } + } + + if (totalNewCount > 0) { + MailService.actionNotifyNewMessages(mContext, mAccount.mId, totalNewCount); + } } }