diff --git a/k9mail/src/main/java/com/fsck/k9/activity/NotificationDeleteConfirmation.java b/k9mail/src/main/java/com/fsck/k9/activity/NotificationDeleteConfirmation.java index dbd7d45ee..b3fed982f 100644 --- a/k9mail/src/main/java/com/fsck/k9/activity/NotificationDeleteConfirmation.java +++ b/k9mail/src/main/java/com/fsck/k9/activity/NotificationDeleteConfirmation.java @@ -10,7 +10,10 @@ import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.os.Parcel; +import android.support.annotation.NonNull; import com.fsck.k9.Account; import com.fsck.k9.K9; @@ -54,11 +57,17 @@ public class NotificationDeleteConfirmation extends Activity { i.putExtra(EXTRA_ACCOUNT, account.getUuid()); i.putExtra(EXTRA_MESSAGE_LIST, refs); i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); + + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/notifydelete/" + refs.hashCode())); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); // we can not use FLAG_UPDATE_CURRENT here because with Android Wear we may have // PendingIntents for all new messages and for each individual new message at the same time. - return PendingIntent.getActivity(context, account.getAccountNumber(), i, PendingIntent.FLAG_ONE_SHOT); + return PendingIntent.getActivity(context, account.getAccountNumber(), i, 0); } @Override diff --git a/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java b/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java index bc866ffa0..6a7956057 100644 --- a/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -4982,6 +4982,11 @@ public class MessagingController implements Runnable { // no sound, no vibrate, no LED because these are for the summary notification only // and depend on quiet time and user settings + // discarding the notification means this one message is no longer bening notified for + ArrayList subAllRefs = new ArrayList(); + subAllRefs.add(message.makeMessageReference()); + subBuilder.setDeleteIntent(NotificationActionService.getAcknowledgeIntent(context, account, realnID, subAllRefs)); + // this must be done before the summary notification notifMgr.notify(realnID, subBuilder.build()); data.addStackedChildNotification(m, realnID); @@ -5068,7 +5073,7 @@ public class MessagingController implements Runnable { builder.setContentIntent(stack.getPendingIntent( account.getAccountNumber(), PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT)); - builder.setDeleteIntent(NotificationActionService.getAcknowledgeIntent(context, account, account.getAccountNumber())); + builder.setDeleteIntent(NotificationActionService.getAcknowledgeIntent(context, account, account.getAccountNumber(), allRefs)); // Only ring or vibrate if we have not done so already on this account and fetch boolean ringAndVibrate = false; diff --git a/k9mail/src/main/java/com/fsck/k9/service/NotificationActionService.java b/k9mail/src/main/java/com/fsck/k9/service/NotificationActionService.java index 1cd92dbfc..fb16a9c51 100644 --- a/k9mail/src/main/java/com/fsck/k9/service/NotificationActionService.java +++ b/k9mail/src/main/java/com/fsck/k9/service/NotificationActionService.java @@ -20,6 +20,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.util.Log; /** @@ -35,7 +36,13 @@ public class NotificationActionService extends CoreService { private final static String ACKNOWLEDGE_ACTION = "com.fsck.k9.service.NotificationActionService.ACKNOWLEDGE_ACTION"; private final static String EXTRA_ACCOUNT = "account"; + /** + * Single message reference. + */ private final static String EXTRA_MESSAGE = "message"; + /** + * Serialized message list of references. + */ private final static String EXTRA_MESSAGE_LIST = "messages"; /** * ID of the notification that triggered an intent. @@ -60,6 +67,12 @@ public class NotificationActionService extends CoreService { i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); i.setAction(REPLY_ACTION); + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/reply/" + ref.getUid())); + return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT); } @@ -79,6 +92,12 @@ public class NotificationActionService extends CoreService { i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); i.setAction(READ_ALL_ACTION); + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/read/" + refs.hashCode())); + return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT); } @@ -90,12 +109,36 @@ public class NotificationActionService extends CoreService { * @return the requested intent. To be used in a Notification. * @see #EXTRA_NOTIFICATION_ID */ - public static PendingIntent getAcknowledgeIntent(Context context, final Account account, final int notificationID) { + /* public static PendingIntent getAcknowledgeIntent(Context context, final Account account, final int notificationID) { Intent i = new Intent(context, NotificationActionService.class); i.putExtra(EXTRA_ACCOUNT, account.getUuid()); i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); i.setAction(ACKNOWLEDGE_ACTION); + return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT); + }*/ + /** + * + * @param context context to use for creating the {@link Intent} + * @param account the account for the intent to act on + * @param notificationID ID of the notification, this intent is for. + * @param refs these messages are acknowledged and shoud not be notified for anymore. + * @return the requested intent. To be used in a Notification. + * @see #EXTRA_NOTIFICATION_ID + */ + public static PendingIntent getAcknowledgeIntent(Context context, final Account account, final int notificationID, final Serializable refs) { + Intent i = new Intent(context, NotificationActionService.class); + i.putExtra(EXTRA_ACCOUNT, account.getUuid()); + i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); + i.putExtra(EXTRA_MESSAGE_LIST, refs); + i.setAction(ACKNOWLEDGE_ACTION); + + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/ack/" + refs.hashCode())); + return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT); } @@ -115,6 +158,12 @@ public class NotificationActionService extends CoreService { i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); i.setAction(DELETE_ALL_ACTION); + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/delete/" + refs.hashCode())); + return i; } @@ -149,6 +198,12 @@ public class NotificationActionService extends CoreService { i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); i.setAction(ARCHIVE_ALL_ACTION); + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/archive/" + refs.hashCode())); + return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT); } @@ -184,6 +239,12 @@ public class NotificationActionService extends CoreService { i.putExtra(EXTRA_NOTIFICATION_ID, notificationID); i.setAction(SPAM_ALL_ACTION); + // this is needed because Android considers 2 PendingIntents that only differ in Extras, the same + // and will return the already created PendingIntent instead. + // This MUST NOT lead to us returning a PendingIntent that deletes any other messages but the + // ones we have as parameters right now!!! + i.setData(Uri.parse("dummy://" + account.getUuid() + "/" + notificationID + "/spam/" + refs.hashCode())); + return PendingIntent.getService(context, account.getAccountNumber(), i, PendingIntent.FLAG_UPDATE_CURRENT); } @@ -305,6 +366,8 @@ public class NotificationActionService extends CoreService { // nothing to do here, we just want to cancel the notification so the list // of unseen messages is reset Log.i(K9.LOG_TAG, "notification acknowledged"); + + refs = intent.getParcelableArrayListExtra(EXTRA_MESSAGE_LIST); } // if this was a stacked notification on Android Wear, update the summary