13168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy/* 23168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Copyright (C) 2012 The Android Open Source Project 33168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * 43168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Licensed under the Apache License, Version 2.0 (the "License"); 53168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * you may not use this file except in compliance with the License. 63168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * You may obtain a copy of the License at 73168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * 83168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * http://www.apache.org/licenses/LICENSE-2.0 93168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * 103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Unless required by applicable law or agreed to in writing, software 113168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 123168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * See the License for the specific language governing permissions and 143168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * limitations under the License. 153168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 163168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedypackage com.android.mail.utils; 173168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 183168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.app.AlarmManager; 193168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.app.Notification; 203168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.app.NotificationManager; 213168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.app.PendingIntent; 223168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.content.ContentResolver; 233168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.content.ContentValues; 243168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.content.Context; 253168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.content.Intent; 2608a079c3d2857e365736432b2691187767eb116fScott Kennedyimport android.database.DataSetObserver; 273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.net.Uri; 283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.os.Parcel; 293168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.os.Parcelable; 303168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.os.SystemClock; 313168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.support.v4.app.NotificationCompat; 32439aa5d7d9226de4682c3697c68c0703b8847518Alan Lauimport android.support.v4.app.RemoteInput; 333168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.support.v4.app.TaskStackBuilder; 343168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport android.widget.RemoteViews; 353168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 36f2566a42b5dec4e846391ee0d7ecae0891356653Scott Kennedyimport com.android.mail.MailIntentService; 373168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.NotificationActionIntentService; 383168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.R; 393168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.compose.ComposeActivity; 403168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.providers.Account; 413168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.providers.Conversation; 423168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.providers.Folder; 433168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.providers.Message; 443168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.android.mail.providers.UIProvider; 45143eb6ca9acb2d41e56efa5b3ceb2d82dfedf755Scott Kennedyimport com.android.mail.providers.UIProvider.ConversationOperations; 463168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport com.google.common.collect.ImmutableMap; 47828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sappersteinimport com.google.common.collect.Sets; 483168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 493168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport java.util.ArrayList; 50d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedyimport java.util.Collection; 513168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport java.util.List; 523168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport java.util.Map; 533168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedyimport java.util.Set; 543168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 553168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedypublic class NotificationActionUtils { 56781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy private static final String LOG_TAG = "NotifActionUtils"; 57781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 5815490239c82cdb4765e87e926c8c1945adedd1edAlan Lau public static final String WEAR_REPLY_INPUT = "wear_reply"; 5915490239c82cdb4765e87e926c8c1945adedd1edAlan Lau 60a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy private static long sUndoTimeoutMillis = -1; 613168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 623168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * If an {@link NotificationAction} exists here for a given notification key, then we should 643168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * display this undo notification rather than an email notification. 653168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 6608a079c3d2857e365736432b2691187767eb116fScott Kennedy public static final ObservableSparseArrayCompat<NotificationAction> sUndoNotifications = 6708a079c3d2857e365736432b2691187767eb116fScott Kennedy new ObservableSparseArrayCompat<NotificationAction>(); 683168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 693168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 70828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein * If a {@link Conversation} exists in this set, then the undo notification for this 71828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein * {@link Conversation} was tapped by the user in the notification drawer. 72828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein * We need to properly handle notification actions for this case. 73828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein */ 74828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein public static final Set<Conversation> sUndoneConversations = Sets.newHashSet(); 75828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein 76828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein /** 773168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * If an undo notification is displayed, its timestamp 783168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * ({@link android.app.Notification.Builder#setWhen(long)}) is stored here so we can use it for 793168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * the original notification if the action is undone. 803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static final SparseLongArray sNotificationTimestamps = new SparseLongArray(); 823168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 833168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public enum NotificationActionType { 847750adb207c55d61ba4693a461ba1e133940f39fAndrew Sapperstein ARCHIVE_REMOVE_LABEL("archive", true, R.drawable.ic_archive_wht_24dp, 85d90a3bb006296443ea35ec3062cad11092ac2f95Andrew Sapperstein R.drawable.ic_remove_label_wht_24dp, R.string.notification_action_archive, 863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy R.string.notification_action_remove_label, new ActionToggler() { 873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy @Override 883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public boolean shouldDisplayPrimary(final Folder folder, 893168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Conversation conversation, final Message message) { 90962a6922af499db189ace88ed3ba518946764197Scott Kennedy return folder == null || folder.isInbox(); 913168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 923168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy }), 937750adb207c55d61ba4693a461ba1e133940f39fAndrew Sapperstein DELETE("delete", true, R.drawable.ic_delete_wht_24dp, 9408a079c3d2857e365736432b2691187767eb116fScott Kennedy R.string.notification_action_delete), 95d90a3bb006296443ea35ec3062cad11092ac2f95Andrew Sapperstein REPLY("reply", false, R.drawable.ic_reply_wht_24dp, R.string.notification_action_reply), 96d90a3bb006296443ea35ec3062cad11092ac2f95Andrew Sapperstein REPLY_ALL("reply_all", false, R.drawable.ic_reply_all_wht_24dp, 9721934896faadf6e740ec87797a9b0d1092c6bc6bScott Kennedy R.string.notification_action_reply_all); 983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 993168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final String mPersistedValue; 10008a079c3d2857e365736432b2691187767eb116fScott Kennedy private final boolean mIsDestructive; 1013168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final int mActionIcon; 1033168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final int mActionIcon2; 1043168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1053168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final int mDisplayString; 1063168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final int mDisplayString2; 1073168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1083168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final ActionToggler mActionToggler; 1093168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private static final Map<String, NotificationActionType> sPersistedMapping; 1113168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1123168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private interface ActionToggler { 1133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 1143168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Determines if we should display the primary or secondary text/icon. 1153168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * 1163168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * @return <code>true</code> to display primary, <code>false</code> to display secondary 1173168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 1183168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy boolean shouldDisplayPrimary(Folder folder, Conversation conversation, Message message); 1193168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1203168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1213168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy static { 1223168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationActionType[] values = values(); 1233168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final ImmutableMap.Builder<String, NotificationActionType> mapBuilder = 1243168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy new ImmutableMap.Builder<String, NotificationActionType>(); 1253168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1263168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy for (int i = 0; i < values.length; i++) { 1273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mapBuilder.put(values[i].getPersistedValue(), values[i]); 1283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1293168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1303168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy sPersistedMapping = mapBuilder.build(); 1313168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1323168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 13308a079c3d2857e365736432b2691187767eb116fScott Kennedy private NotificationActionType(final String persistedValue, final boolean isDestructive, 13408a079c3d2857e365736432b2691187767eb116fScott Kennedy final int actionIcon, final int displayString) { 1353168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mPersistedValue = persistedValue; 13608a079c3d2857e365736432b2691187767eb116fScott Kennedy mIsDestructive = isDestructive; 1373168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mActionIcon = actionIcon; 1383168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mActionIcon2 = -1; 1393168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mDisplayString = displayString; 1403168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mDisplayString2 = -1; 1413168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mActionToggler = null; 1423168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1433168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 14408a079c3d2857e365736432b2691187767eb116fScott Kennedy private NotificationActionType(final String persistedValue, final boolean isDestructive, 14508a079c3d2857e365736432b2691187767eb116fScott Kennedy final int actionIcon, final int actionIcon2, final int displayString, 14608a079c3d2857e365736432b2691187767eb116fScott Kennedy final int displayString2, final ActionToggler actionToggler) { 1473168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mPersistedValue = persistedValue; 14808a079c3d2857e365736432b2691187767eb116fScott Kennedy mIsDestructive = isDestructive; 1493168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mActionIcon = actionIcon; 1503168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mActionIcon2 = actionIcon2; 1513168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mDisplayString = displayString; 1523168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mDisplayString2 = displayString2; 1533168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mActionToggler = actionToggler; 1543168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1553168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1563168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static NotificationActionType getActionType(final String persistedValue) { 1573168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return sPersistedMapping.get(persistedValue); 1583168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1593168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1603168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public String getPersistedValue() { 1613168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mPersistedValue; 1623168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 16408a079c3d2857e365736432b2691187767eb116fScott Kennedy public boolean getIsDestructive() { 16508a079c3d2857e365736432b2691187767eb116fScott Kennedy return mIsDestructive; 16608a079c3d2857e365736432b2691187767eb116fScott Kennedy } 16708a079c3d2857e365736432b2691187767eb116fScott Kennedy 1683168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public int getActionIconResId(final Folder folder, final Conversation conversation, 1693168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Message message) { 1703168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy if (mActionToggler == null || mActionToggler.shouldDisplayPrimary(folder, conversation, 1713168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy message)) { 1723168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mActionIcon; 1733168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1743168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1753168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mActionIcon2; 1763168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1773168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1783168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public int getDisplayStringResId(final Folder folder, final Conversation conversation, 1793168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Message message) { 1803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy if (mActionToggler == null || mActionToggler.shouldDisplayPrimary(folder, conversation, 1813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy message)) { 1823168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mDisplayString; 1833168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1843168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1853168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mDisplayString2; 1863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 1883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 1893168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 1903168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Adds the appropriate notification actions to the specified 191d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy * {@link android.support.v4.app.NotificationCompat.Builder} 1923168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * 1933168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * @param notificationIntent The {@link Intent} used when the notification is clicked 1943168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * @param when The value passed into {@link android.app.Notification.Builder#setWhen(long)}. 1953168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * This is used for maintaining notification ordering with the undo bar 196d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy * @param notificationActions A {@link Set} set of the actions to display 1973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 1983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void addNotificationActions(final Context context, 199d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final Intent notificationIntent, final NotificationCompat.Builder notification, 200439aa5d7d9226de4682c3697c68c0703b8847518Alan Lau NotificationCompat.WearableExtender wearExtender, final Account account, 20115490239c82cdb4765e87e926c8c1945adedd1edAlan Lau final Conversation conversation, final Message message, 2023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Folder folder, final int notificationId, final long when, 203d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final Set<String> notificationActions) { 204d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final List<NotificationActionType> sortedActions = 205d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy getSortedNotificationActions(folder, notificationActions); 2063168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 207d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy for (final NotificationActionType notificationAction : sortedActions) { 208e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final PendingIntent pendingIntent = getNotificationActionPendingIntent( 20915490239c82cdb4765e87e926c8c1945adedd1edAlan Lau context, account, conversation, message, 21015490239c82cdb4765e87e926c8c1945adedd1edAlan Lau folder, notificationIntent, notificationAction, notificationId, when); 211e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final int actionIconResId = notificationAction.getActionIconResId(folder, conversation, 21215490239c82cdb4765e87e926c8c1945adedd1edAlan Lau message); 213e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final String title = context.getString(notificationAction.getDisplayStringResId( 21415490239c82cdb4765e87e926c8c1945adedd1edAlan Lau folder, conversation, message)); 21515490239c82cdb4765e87e926c8c1945adedd1edAlan Lau 216ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau // Always add all actions to both standard and wearable notifications. 217ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau notification.addAction(actionIconResId, title, pendingIntent); 218ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau 219e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau // Use a different intent for wear because it triggers different set of behavior: 220e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau // no undo for archive/delete, and mark conversation as read after reply. 221e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final PendingIntent wearPendingIntent = getWearNotificationActionPendingIntent( 222e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau context, account, conversation, message, 223e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau folder, notificationIntent, notificationAction, notificationId, when); 224e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 225e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final NotificationCompat.Action.Builder wearableActionBuilder = 226781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau new NotificationCompat.Action.Builder( 227781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau mapWearActionResId(notificationAction, actionIconResId), title, 228e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau wearPendingIntent); 229781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau 230ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau if (notificationAction == NotificationActionType.REPLY 231ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau || notificationAction == NotificationActionType.REPLY_ALL) { 232e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final String[] choices = context.getResources().getStringArray( 233e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau R.array.reply_choices); 234ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau wearableActionBuilder.addRemoteInput( 235dbf09e5f9614abe2cf672463b1da3993093694a0Alan Lau new RemoteInput.Builder(WEAR_REPLY_INPUT) 236dbf09e5f9614abe2cf672463b1da3993093694a0Alan Lau .setLabel(title) 237dbf09e5f9614abe2cf672463b1da3993093694a0Alan Lau .setChoices(choices) 238781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau .build()); 23915490239c82cdb4765e87e926c8c1945adedd1edAlan Lau } 240ecb8ce46f50042c9b67362e57349d3eae39f6182Alan Lau 241439aa5d7d9226de4682c3697c68c0703b8847518Alan Lau wearExtender.addAction(wearableActionBuilder.build()); 242781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau LogUtils.d(LOG_TAG, "Adding wearable action!!"); 243781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau } 244781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau } 245781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau 246781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau private static int mapWearActionResId(NotificationActionType notificationAction, 247781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau int defActionIconResId) { 248781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau switch (notificationAction) { 249781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau case REPLY: 250781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau return R.drawable.ic_wear_full_reply; 251781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau case REPLY_ALL: 252781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau return R.drawable.ic_wear_full_reply_all; 253781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau case ARCHIVE_REMOVE_LABEL: 254781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau return R.drawable.ic_wear_full_archive; 255781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau case DELETE: 256781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau return R.drawable.ic_wear_full_delete; 257781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau default: 258781d1b0449ecdf74064f42df07e24c7e962c88ebAlan Lau return defActionIconResId; 2593168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 2603168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 2613168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 2623168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 2633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Sorts the notification actions into the appropriate order, based on current label 2643168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * 2653168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * @param folder The {@link Folder} being notified 266d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy * @param notificationActionStrings The action strings to sort 2673168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 268d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy private static List<NotificationActionType> getSortedNotificationActions( 269d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final Folder folder, final Collection<String> notificationActionStrings) { 270d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final List<NotificationActionType> unsortedActions = 271d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy new ArrayList<NotificationActionType>(notificationActionStrings.size()); 272d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy for (final String action : notificationActionStrings) { 273d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy unsortedActions.add(NotificationActionType.getActionType(action)); 274d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy } 275d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy 276d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final List<NotificationActionType> sortedActions = 277d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy new ArrayList<NotificationActionType>(unsortedActions.size()); 2783168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 2798c1058ee75ec4a5824a68c3c5275bc48d56bbad8Scott Kennedy if (folder.isInbox()) { 2803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Inbox 2813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /* 2823168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Action 1: Archive, Delete, Mute, Mark read, Add star, Mark important, Reply, Reply 2833168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * all, Forward 2843168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 2853168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /* 2863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Action 2: Reply, Reply all, Forward, Mark important, Add star, Mark read, Mute, 2873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Delete, Archive 2883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 289d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.ARCHIVE_REMOVE_LABEL)) { 290d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.ARCHIVE_REMOVE_LABEL); 2913168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 292d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.DELETE)) { 293d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.DELETE); 2943168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 295d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.REPLY)) { 296d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.REPLY); 2973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 298d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.REPLY_ALL)) { 299d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.REPLY_ALL); 3003168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 3013168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } else if (folder.isProviderFolder()) { 3023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Gmail system labels 3033168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /* 3043168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Action 1: Delete, Mute, Mark read, Add star, Mark important, Reply, Reply all, 3053168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Forward 3063168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 3073168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /* 3083168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Action 2: Reply, Reply all, Forward, Mark important, Add star, Mark read, Mute, 3093168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Delete 3103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 311d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.DELETE)) { 312d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.DELETE); 3133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 314d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.REPLY)) { 315d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.REPLY); 3163168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 317d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.REPLY_ALL)) { 318d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.REPLY_ALL); 3193168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 3203168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } else { 3213168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Gmail user created labels 3223168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /* 3233168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Action 1: Remove label, Delete, Mark read, Add star, Mark important, Reply, Reply 3243168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * all, Forward 3253168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 3263168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /* 3273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Action 2: Reply, Reply all, Forward, Mark important, Add star, Mark read, Delete 3283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 329d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.ARCHIVE_REMOVE_LABEL)) { 330d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.ARCHIVE_REMOVE_LABEL); 3313168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 332d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.DELETE)) { 333d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.DELETE); 3343168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 335d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.REPLY)) { 336d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.REPLY); 3373168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 338d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy if (unsortedActions.contains(NotificationActionType.REPLY_ALL)) { 339d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy sortedActions.add(NotificationActionType.REPLY_ALL); 3403168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 3413168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 342d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy 343d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy return sortedActions; 3443168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 3453168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 3463168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 3473168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Creates a {@link PendingIntent} for the specified notification action. 3483168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 3493168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private static PendingIntent getNotificationActionPendingIntent(final Context context, 3503168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Account account, final Conversation conversation, final Message message, 3513168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Folder folder, final Intent notificationIntent, 3523168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationActionType action, final int notificationId, final long when) { 3533168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Uri messageUri = message.uri; 3543168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 3553168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationAction notificationAction = new NotificationAction(action, account, 356e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau conversation, message, folder, conversation.id, message.serverId, message.id, when, 3573806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau NotificationAction.SOURCE_LOCAL, notificationId); 3583168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 3593168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy switch (action) { 3603168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy case REPLY: { 3613168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Build a task stack that forces the conversation view on the stack before the 3623168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // reply activity. 3633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 36407342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 365d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final Intent intent = createReplyIntent(context, account, messageUri, false); 366d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy intent.setPackage(context.getPackageName()); 367804490c46d54741018917cc7f033acb7e6b7e824Alan Lau intent.setData(conversation.uri); 368d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy intent.putExtra(ComposeActivity.EXTRA_NOTIFICATION_FOLDER, folder); 36907342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 370d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy taskStackBuilder.addNextIntent(notificationIntent).addNextIntent(intent); 37107342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 3725680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy return taskStackBuilder.getPendingIntent( 3733168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy notificationId, PendingIntent.FLAG_UPDATE_CURRENT); 3743168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } case REPLY_ALL: { 3753168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Build a task stack that forces the conversation view on the stack before the 3763168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // reply activity. 3773168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 37807342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 379d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final Intent intent = createReplyIntent(context, account, messageUri, true); 380d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy intent.setPackage(context.getPackageName()); 381804490c46d54741018917cc7f033acb7e6b7e824Alan Lau intent.setData(conversation.uri); 382d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy intent.putExtra(ComposeActivity.EXTRA_NOTIFICATION_FOLDER, folder); 38307342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 384d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy taskStackBuilder.addNextIntent(notificationIntent).addNextIntent(intent); 38507342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 3865680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy return taskStackBuilder.getPendingIntent( 3873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy notificationId, PendingIntent.FLAG_UPDATE_CURRENT); 3883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } case ARCHIVE_REMOVE_LABEL: { 3893168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final String intentAction = 3903168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy NotificationActionIntentService.ACTION_ARCHIVE_REMOVE_LABEL; 39107342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 3923168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Intent intent = new Intent(intentAction); 393d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy intent.setPackage(context.getPackageName()); 394804490c46d54741018917cc7f033acb7e6b7e824Alan Lau intent.setData(conversation.uri); 395621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy putNotificationActionExtra(intent, notificationAction); 39607342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 3973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return PendingIntent.getService( 3983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT); 3993168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } case DELETE: { 4003168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final String intentAction = NotificationActionIntentService.ACTION_DELETE; 40107342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 4023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Intent intent = new Intent(intentAction); 403d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy intent.setPackage(context.getPackageName()); 404804490c46d54741018917cc7f033acb7e6b7e824Alan Lau intent.setData(conversation.uri); 405621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy putNotificationActionExtra(intent, notificationAction); 40607342eff9ca95b9db665f1453565ea895f3b125fScott Kennedy 4073168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return PendingIntent.getService( 4083168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT); 4093168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 4103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 4113168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 4123168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy throw new IllegalArgumentException("Invalid NotificationActionType"); 4133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 4143168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 4153168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 416e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau * Creates a {@link PendingIntent} for the specified Wear notification action. 417e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau */ 418e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau private static PendingIntent getWearNotificationActionPendingIntent(final Context context, 419e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final Account account, final Conversation conversation, final Message message, 420e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final Folder folder, final Intent notificationIntent, 421e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final NotificationActionType action, final int notificationId, final long when) { 422e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final Uri messageUri = message.uri; 423e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 424e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final NotificationAction notificationAction = new NotificationAction(action, account, 425e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau conversation, message, folder, conversation.id, message.serverId, message.id, when, 4263806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau NotificationAction.SOURCE_REMOTE, notificationId); 427e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 428e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau switch (action) { 429e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau case REPLY: 430e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau case REPLY_ALL: { 431e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau // Build a task stack that forces the conversation view on the stack before the 432e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau // reply activity. 433e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 434e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 435e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final Intent intent = createReplyIntent(context, account, messageUri, 436e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau (action == NotificationActionType.REPLY_ALL)); 437e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau intent.setPackage(context.getPackageName()); 438e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau intent.setData(buildWearUri(conversation.uri)); 439e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau intent.putExtra(ComposeActivity.EXTRA_NOTIFICATION_FOLDER, folder); 440e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau intent.putExtra(ComposeActivity.EXTRA_NOTIFICATION_CONVERSATION, conversation.uri); 441e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 442e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau taskStackBuilder.addNextIntent(notificationIntent).addNextIntent(intent); 443e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 444e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau return taskStackBuilder.getPendingIntent(notificationId, 445e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau PendingIntent.FLAG_UPDATE_CURRENT); 446e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau } 447e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau case ARCHIVE_REMOVE_LABEL: 448e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau case DELETE: { 449e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final String intentAction = (action == NotificationActionType.ARCHIVE_REMOVE_LABEL) 450e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau ? NotificationActionIntentService.ACTION_ARCHIVE_REMOVE_LABEL 451e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau : NotificationActionIntentService.ACTION_DELETE; 452e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 453e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau final Intent intent = new Intent(intentAction); 454e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau intent.setPackage(context.getPackageName()); 455e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau intent.setData(buildWearUri(conversation.uri)); 456e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau putNotificationActionExtra(intent, notificationAction); 457e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 458e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau return PendingIntent.getService(context, notificationId, intent, 459e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau PendingIntent.FLAG_UPDATE_CURRENT); 460e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau } 461e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau } 462e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 463e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau throw new IllegalArgumentException("Invalid NotificationActionType"); 464e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau } 465e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 466e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau private static Uri buildWearUri(Uri uri) { 467e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau return uri.buildUpon().appendQueryParameter("type", "wear").build(); 468e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau } 469e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 470e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau /** 4713168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * @return an intent which, if launched, will reply to the conversation 4723168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 4733168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static Intent createReplyIntent(final Context context, final Account account, 4743168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Uri messageUri, final boolean isReplyAll) { 4753168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Intent intent = ComposeActivity.createReplyIntent(context, account, messageUri, 4763168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy isReplyAll); 4774fe0af81874976a1995191321e35c844b2229811Andy Huang intent.putExtra(Utils.EXTRA_FROM_NOTIFICATION, true); 4783168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return intent; 4793168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 4803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 4813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static class NotificationAction implements Parcelable { 482e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau public static final int SOURCE_LOCAL = 0; 483e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau public static final int SOURCE_REMOTE = 1; 484e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 4853168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final NotificationActionType mNotificationActionType; 4863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final Account mAccount; 4873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final Conversation mConversation; 4883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final Message mMessage; 4893168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final Folder mFolder; 4903168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final long mConversationId; 4913168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final String mMessageId; 4923168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final long mLocalMessageId; 4933168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private final long mWhen; 494e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau private final int mSource; 4953806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau private final int mNotificationId; 4963168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 4973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public NotificationAction(final NotificationActionType notificationActionType, 4983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Account account, final Conversation conversation, final Message message, 4993168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Folder folder, final long conversationId, final String messageId, 5003806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau final long localMessageId, final long when, final int source, 5013806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau final int notificationId) { 5023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mNotificationActionType = notificationActionType; 5033168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mAccount = account; 5043168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mConversation = conversation; 5053168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mMessage = message; 5063168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mFolder = folder; 5073168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mConversationId = conversationId; 5083168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mMessageId = messageId; 5093168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mLocalMessageId = localMessageId; 5103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mWhen = when; 511e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau mSource = source; 5123806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau mNotificationId = notificationId; 5133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5143168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5153168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public NotificationActionType getNotificationActionType() { 5163168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mNotificationActionType; 5173168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5183168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5193168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public Account getAccount() { 5203168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mAccount; 5213168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5223168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5233168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public Conversation getConversation() { 5243168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mConversation; 5253168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5263168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public Message getMessage() { 5283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mMessage; 5293168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5303168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5313168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public Folder getFolder() { 5323168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mFolder; 5333168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5343168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5353168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public long getConversationId() { 5363168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mConversationId; 5373168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5383168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5393168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public String getMessageId() { 5403168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mMessageId; 5413168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5423168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5433168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public long getLocalMessageId() { 5443168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mLocalMessageId; 5453168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5463168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5473168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public long getWhen() { 5483168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return mWhen; 5493168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5503168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 551e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau public int getSource() { 552e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau return mSource; 553e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau } 554e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau 5553806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau public int getNotificationId() { 5563806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau return mNotificationId; 5573806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau } 5583806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau 5593168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public int getActionTextResId() { 5603168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy switch (mNotificationActionType) { 5613168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy case ARCHIVE_REMOVE_LABEL: 5628c1058ee75ec4a5824a68c3c5275bc48d56bbad8Scott Kennedy if (mFolder.isInbox()) { 5633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return R.string.notification_action_undo_archive; 5643168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } else { 5653168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return R.string.notification_action_undo_remove_label; 5663168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5673168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy case DELETE: 5683168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return R.string.notification_action_undo_delete; 5693168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy default: 5703168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy throw new IllegalStateException( 5713168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy "There is no action text for this NotificationActionType."); 5723168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5733168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5743168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5753168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy @Override 5763168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public int describeContents() { 5773168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return 0; 5783168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5793168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 5803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy @Override 5813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public void writeToParcel(final Parcel out, final int flags) { 5823168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeInt(mNotificationActionType.ordinal()); 5833168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeParcelable(mAccount, 0); 5843168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeParcelable(mConversation, 0); 5853168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeParcelable(mMessage, 0); 5863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeParcelable(mFolder, 0); 5873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeLong(mConversationId); 5883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeString(mMessageId); 5893168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeLong(mLocalMessageId); 5903168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy out.writeLong(mWhen); 591e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau out.writeInt(mSource); 5923806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau out.writeInt(mNotificationId); 5933168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 5943168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 595b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy public static final Parcelable.ClassLoaderCreator<NotificationAction> CREATOR = 596b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy new Parcelable.ClassLoaderCreator<NotificationAction>() { 5973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy @Override 5983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public NotificationAction createFromParcel(final Parcel in) { 599b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy return new NotificationAction(in, null); 6003168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 6013168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy @Override 6033168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public NotificationAction[] newArray(final int size) { 6043168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return new NotificationAction[size]; 6053168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 606b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy 607b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy @Override 608b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy public NotificationAction createFromParcel( 609b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy final Parcel in, final ClassLoader loader) { 610b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy return new NotificationAction(in, loader); 611b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy } 6123168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy }; 6133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 614b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy private NotificationAction(final Parcel in, final ClassLoader loader) { 6153168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mNotificationActionType = NotificationActionType.values()[in.readInt()]; 616b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy mAccount = in.readParcelable(loader); 617b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy mConversation = in.readParcelable(loader); 618b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy mMessage = in.readParcelable(loader); 619b2ce334a6109aa79e8e6b5a4e74e4f011e8eae1dScott Kennedy mFolder = in.readParcelable(loader); 6203168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mConversationId = in.readLong(); 6213168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mMessageId = in.readString(); 6223168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mLocalMessageId = in.readLong(); 6233168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy mWhen = in.readLong(); 624e806c9447c7137d2a7a828e7ccdc1f8961aa1c2aAlan Lau mSource = in.readInt(); 6253806cb53f880094d811ced050342fd6ee7c4bf99Alan Lau mNotificationId = in.readInt(); 6263168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 6273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 6283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6293168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static Notification createUndoNotification(final Context context, 6303168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationAction notificationAction, final int notificationId) { 631781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "createUndoNotification for %s", 632781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 633781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 6343168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationCompat.Builder builder = new NotificationCompat.Builder(context); 6353168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 636722c8c8e9797a021178c9feb7f2902a2a095ab36Rohan Shah builder.setSmallIcon(R.drawable.ic_notification_mail_24dp); 6373168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy builder.setWhen(notificationAction.getWhen()); 63876fb85a30a41254537c0ad26cabec06030fcdbbaPaul Westbrook builder.setCategory(NotificationCompat.CATEGORY_EMAIL); 6393168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6403168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final RemoteViews undoView = 6413168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy new RemoteViews(context.getPackageName(), R.layout.undo_notification); 6423168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy undoView.setTextViewText( 6433168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy R.id.description_text, context.getString(notificationAction.getActionTextResId())); 6443168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 645d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final String packageName = context.getPackageName(); 646d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy 6473168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Intent clickIntent = new Intent(NotificationActionIntentService.ACTION_UNDO); 648d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy clickIntent.setPackage(packageName); 649804490c46d54741018917cc7f033acb7e6b7e824Alan Lau clickIntent.setData(notificationAction.mConversation.uri); 650621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy putNotificationActionExtra(clickIntent, notificationAction); 6513168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final PendingIntent clickPendingIntent = PendingIntent.getService(context, notificationId, 6523168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); 6533168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6543168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy undoView.setOnClickPendingIntent(R.id.status_bar_latest_event_content, clickPendingIntent); 6553168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6563168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy builder.setContent(undoView); 6573168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6583168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // When the notification is cleared, we perform the destructive action 6593168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Intent deleteIntent = new Intent(NotificationActionIntentService.ACTION_DESTRUCT); 660d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy deleteIntent.setPackage(packageName); 661735cbbd8a4676c1d36a25c061c8697668786227fAlan Lau deleteIntent.setData(notificationAction.mConversation.uri); 662621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy putNotificationActionExtra(deleteIntent, notificationAction); 6633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final PendingIntent deletePendingIntent = PendingIntent.getService(context, 6643168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy notificationId, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT); 6653168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy builder.setDeleteIntent(deletePendingIntent); 6663168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6673168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Notification notification = builder.build(); 6683168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6693168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return notification; 6703168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 6713168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6723168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 6733168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Registers a timeout for the undo notification such that when it expires, the undo bar will 6743168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * disappear, and the action will be performed. 6753168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 6763168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void registerUndoTimeout( 6773168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Context context, final NotificationAction notificationAction) { 678781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "registerUndoTimeout for %s", 679781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 680781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 681a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy if (sUndoTimeoutMillis == -1) { 682a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy sUndoTimeoutMillis = 683a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy context.getResources().getInteger(R.integer.undo_notification_timeout); 684a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy } 685a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy 6863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final AlarmManager alarmManager = 6873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 6883168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 689a61f99847d48938589bc7f7740e2385eee5626abScott Kennedy final long triggerAtMills = SystemClock.elapsedRealtime() + sUndoTimeoutMillis; 6903168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6913168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final PendingIntent pendingIntent = 6923168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy createUndoTimeoutPendingIntent(context, notificationAction); 6933168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6943168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy alarmManager.set(AlarmManager.ELAPSED_REALTIME, triggerAtMills, pendingIntent); 6953168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 6963168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 6973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 6983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Cancels the undo timeout for a notification action. This should be called if the undo 6993168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * notification is clicked (to prevent the action from being performed anyway) or cleared (since 7003168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * we have already performed the action). 7013168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 7023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void cancelUndoTimeout( 7033168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Context context, final NotificationAction notificationAction) { 704781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "cancelUndoTimeout for %s", 705781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 706781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 7073168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final AlarmManager alarmManager = 7083168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 7093168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final PendingIntent pendingIntent = 7113168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy createUndoTimeoutPendingIntent(context, notificationAction); 7123168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7133168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy alarmManager.cancel(pendingIntent); 7143168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7153168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7163168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 7173168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Creates a {@link PendingIntent} to be used for creating and canceling the undo timeout 7183168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * alarm. 7193168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 7203168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy private static PendingIntent createUndoTimeoutPendingIntent( 7213168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Context context, final NotificationAction notificationAction) { 7223168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Intent intent = new Intent(NotificationActionIntentService.ACTION_UNDO_TIMEOUT); 7232d8f3094d69b7ebbd9376dde7f61eb4334e86075Scott Kennedy intent.setPackage(context.getPackageName()); 724804490c46d54741018917cc7f033acb7e6b7e824Alan Lau intent.setData(notificationAction.mConversation.uri); 725621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy putNotificationActionExtra(intent, notificationAction); 7263168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final int requestCode = notificationAction.getAccount().hashCode() 7283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy ^ notificationAction.getFolder().hashCode(); 7293168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final PendingIntent pendingIntent = 7303168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy PendingIntent.getService(context, requestCode, intent, 0); 7313168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7323168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy return pendingIntent; 7333168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7343168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7353168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 7363168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Processes the specified destructive action (archive, delete, mute) on the message. 7373168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 7383168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void processDestructiveAction( 7393168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Context context, final NotificationAction notificationAction) { 740781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "processDestructiveAction: %s", 741781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 742781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 7433168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationActionType destructAction = 7443168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy notificationAction.getNotificationActionType(); 7453168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Conversation conversation = notificationAction.getConversation(); 7463168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Folder folder = notificationAction.getFolder(); 7473168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7483168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final ContentResolver contentResolver = context.getContentResolver(); 7491007e70b1abad47c84d19890809e2b3727419607Scott Kennedy final Uri uri = conversation.uri.buildUpon().appendQueryParameter( 7501007e70b1abad47c84d19890809e2b3727419607Scott Kennedy UIProvider.FORCE_UI_NOTIFICATIONS_QUERY_PARAMETER, Boolean.TRUE.toString()).build(); 7513168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7523168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy switch (destructAction) { 7533168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy case ARCHIVE_REMOVE_LABEL: { 7548c1058ee75ec4a5824a68c3c5275bc48d56bbad8Scott Kennedy if (folder.isInbox()) { 7553168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Inbox, so archive 7563168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final ContentValues values = new ContentValues(1); 7573168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy values.put(UIProvider.ConversationOperations.OPERATION_KEY, 7583168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy UIProvider.ConversationOperations.ARCHIVE); 7593168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7603168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy contentResolver.update(uri, values, null, null); 7613168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } else { 7623168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy // Not inbox, so remove label 7633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final ContentValues values = new ContentValues(1); 764143eb6ca9acb2d41e56efa5b3ceb2d82dfedf755Scott Kennedy 765259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedy final String removeFolderUri = folder.folderUri.fullUri.buildUpon() 766259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedy .appendPath(Boolean.FALSE.toString()).toString(); 767143eb6ca9acb2d41e56efa5b3ceb2d82dfedf755Scott Kennedy values.put(ConversationOperations.FOLDERS_UPDATED, removeFolderUri); 7683168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7693168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy contentResolver.update(uri, values, null, null); 7703168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7713168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy break; 7723168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7733168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy case DELETE: { 7743168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy contentResolver.delete(uri, null, null); 7753168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy break; 7763168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7773168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy default: 7783168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy throw new IllegalArgumentException( 7793168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy "The specified NotificationActionType is not a destructive action."); 7803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 7823168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7833168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 7843168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Creates and displays an Undo notification for the specified {@link NotificationAction}. 7853168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 7863168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void createUndoNotification(final Context context, 7873168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationAction notificationAction) { 788781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "createUndoNotification for %s", 789781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 790781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 791d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final int notificationId = NotificationUtils.getNotificationId( 792b90a813b107d8f43236e2d3fe12f299d94c82ce8Tony Mantler notificationAction.getAccount().getAccountManagerAccount(), 793b90a813b107d8f43236e2d3fe12f299d94c82ce8Tony Mantler notificationAction.getFolder()); 7943168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7953168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final Notification notification = 7963168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy createUndoNotification(context, notificationAction, notificationId); 7973168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 7983168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationManager notificationManager = 7993168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 8003168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy notificationManager.notify(notificationId, notification); 8013168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 8023168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy sUndoNotifications.put(notificationId, notificationAction); 8033168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy sNotificationTimestamps.put(notificationId, notificationAction.getWhen()); 8043168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 8053168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 806828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein /** 807828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein * Called when an Undo notification has been tapped. 808828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein */ 8093168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void cancelUndoNotification(final Context context, 8103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationAction notificationAction) { 811781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "cancelUndoNotification for %s", 812781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 813781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 814ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein final Account account = notificationAction.getAccount(); 815ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein final Folder folder = notificationAction.getFolder(); 816828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein final Conversation conversation = notificationAction.getConversation(); 817b90a813b107d8f43236e2d3fe12f299d94c82ce8Tony Mantler final int notificationId = 818b90a813b107d8f43236e2d3fe12f299d94c82ce8Tony Mantler NotificationUtils.getNotificationId(account.getAccountManagerAccount(), folder); 819828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein 820828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein // Note: we must add the conversation before removing the undo notification 821828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein // Otherwise, the observer for sUndoNotifications gets called, which calls 822828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein // handleNotificationActions before the undone conversation has been added to the set. 823828bc86ffcb1274fb461fbb25cdc2a07ae76b6c8Andrew Sapperstein sUndoneConversations.add(conversation); 824caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy removeUndoNotification(context, notificationId, false); 825ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein resendNotifications(context, account, folder); 8263168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 8273168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 8283168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 8293168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * If an undo notification is left alone for a long enough time, it will disappear, this method 8303168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * will be called, and the action will be finalized. 8313168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 8323168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy public static void processUndoNotification(final Context context, 8333168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy final NotificationAction notificationAction) { 834781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "processUndoNotification, %s", 835781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy notificationAction.getNotificationActionType()); 836781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 837ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein final Account account = notificationAction.getAccount(); 838ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein final Folder folder = notificationAction.getFolder(); 839d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy final int notificationId = NotificationUtils.getNotificationId( 840b90a813b107d8f43236e2d3fe12f299d94c82ce8Tony Mantler account.getAccountManagerAccount(), folder); 841caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy removeUndoNotification(context, notificationId, true); 8423168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy sNotificationTimestamps.delete(notificationId); 8433168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy processDestructiveAction(context, notificationAction); 8443168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 8453168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy 846606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy /** 847606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy * Removes the undo notification. 848caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy * 849caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy * @param removeNow <code>true</code> to remove it from the drawer right away, 850caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy * <code>false</code> to just remove the reference to it 851606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy */ 852caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy private static void removeUndoNotification( 853caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy final Context context, final int notificationId, final boolean removeNow) { 854606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy sUndoNotifications.delete(notificationId); 855606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy 856caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy if (removeNow) { 857caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy final NotificationManager notificationManager = 858caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 859caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy notificationManager.cancel(notificationId); 860caa952b4074b3d8a9f9d869355c4a98fcb904dd1Scott Kennedy } 861606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy } 862606893390dcb49a88833aa17955dbe96fa41ae4aScott Kennedy 8633168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy /** 8643168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy * Broadcasts an {@link Intent} to inform the app to resend its notifications. 8653168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy */ 866ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein public static void resendNotifications(final Context context, final Account account, 867ddd17bc2963b67ba07dfd1e2d9b1f17abf8c8e4aAndrew Sapperstein final Folder folder) { 868781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy LogUtils.i(LOG_TAG, "resendNotifications account: %s, folder: %s", 869de56df00df1f02977a0013b3c474794b5264fe9fRégis Décamps account == null ? null : LogUtils.sanitizeName(LOG_TAG, account.getEmailAddress()), 870de56df00df1f02977a0013b3c474794b5264fe9fRégis Décamps folder == null ? null : LogUtils.sanitizeName(LOG_TAG, folder.name)); 871781f7e322283229483b048776fcb6857c38a72b5Scott Kennedy 872f2566a42b5dec4e846391ee0d7ecae0891356653Scott Kennedy final Intent intent = new Intent(MailIntentService.ACTION_RESEND_NOTIFICATIONS); 873612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps intent.setPackage(context.getPackageName()); // Make sure we only deliver this to ourselves 874612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps if (account != null) { 875612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps intent.putExtra(Utils.EXTRA_ACCOUNT_URI, account.uri); 876612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps } 877612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps if (folder != null) { 878612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps intent.putExtra(Utils.EXTRA_FOLDER_URI, folder.folderUri.fullUri); 879612eb3287c1261952f16dff7bdf5715b9b92b8daRégis Décamps } 8803168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy context.startService(intent); 8813168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy } 88208a079c3d2857e365736432b2691187767eb116fScott Kennedy 88308a079c3d2857e365736432b2691187767eb116fScott Kennedy public static void registerUndoNotificationObserver(final DataSetObserver observer) { 88408a079c3d2857e365736432b2691187767eb116fScott Kennedy sUndoNotifications.getDataSetObservable().registerObserver(observer); 88508a079c3d2857e365736432b2691187767eb116fScott Kennedy } 88608a079c3d2857e365736432b2691187767eb116fScott Kennedy 88708a079c3d2857e365736432b2691187767eb116fScott Kennedy public static void unregisterUndoNotificationObserver(final DataSetObserver observer) { 88808a079c3d2857e365736432b2691187767eb116fScott Kennedy sUndoNotifications.getDataSetObservable().unregisterObserver(observer); 88908a079c3d2857e365736432b2691187767eb116fScott Kennedy } 890621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy 891621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy /** 892621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * <p> 893621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * This is a slight hack to avoid an exception in the remote AlarmManagerService process. The 894621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * AlarmManager adds extra data to this Intent which causes it to inflate. Since the remote 895621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * process does not know about the NotificationAction class, it throws a ClassNotFoundException. 896621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * </p> 897621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * <p> 898621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * To avoid this, we marshall the data ourselves and then parcel a plain byte[] array. The 899621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * NotificationActionIntentService class knows to build the NotificationAction object from the 900621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * byte[] array. 901621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy * </p> 902621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy */ 903621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy private static void putNotificationActionExtra(final Intent intent, 904621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy final NotificationAction notificationAction) { 905621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy final Parcel out = Parcel.obtain(); 906621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy notificationAction.writeToParcel(out, 0); 907621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy out.setDataPosition(0); 908621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy intent.putExtra(NotificationActionIntentService.EXTRA_NOTIFICATION_ACTION, out.marshall()); 909621981ca3fb5f7b461edeac7ac4df765fe72f582Scott Kennedy } 9103168c2a75edbf597932ab9edfd96037ceba99b35Scott Kennedy} 911