15

I want to reset a variable of my service when user clears my notification: that's all!

Looking around I see that everyone suggest to add a delete intent on my notification, but intent is used to start an activity, a service o whatever while I just need a thing like this:

void onClearPressed(){
   aVariable = 0;
}

how to obtain this result?

Phate
  • 6,066
  • 15
  • 73
  • 138

2 Answers2

45

Notifications are not managed by your app and all things like showing notifications and clearing them are actually happening in another process. You can't make another app directly execute a piece of code just because of security reasons.

The only possibility in your case is to provide a PendingIntent which just wraps around a regular Intent and will be started on behalf of your app when notification is cleared. You need to use PendingIntent for sending broadcast or starting a service and then doing what you want in the broadcast receiver or in the service. What exactly to use depends on from which application component you are showing notifications.

In case of broadcast receiver you can just create an anonymous inner class for broadcast receiver and register it dynamically before showing notification. It will look something like that:

public class NotificationHelper {
    private static final String NOTIFICATION_DELETED_ACTION = "NOTIFICATION_DELETED";

    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            aVariable = 0; // Do what you want here
            unregisterReceiver(this);
        }
    };

    public void showNotification(Context ctx, String text) {
        Intent intent = new Intent(NOTIFICATION_DELETED_ACTION);
        PendingIntent pendintIntent = PendingIntent.getBroadcast(ctx, 0, intent, 0);
        registerReceiver(receiver, new IntentFilter(NOTIFICATION_DELETED_ACTION));
        Notification n = new Notification.Builder(mContext).
          setContentText(text).
          setDeleteIntent(pendintIntent).
          build();
        NotificationManager.notify(0, n);
    }
}
raukodraug
  • 11,519
  • 4
  • 35
  • 37
Andrei Mankevich
  • 2,253
  • 16
  • 15
  • 1
    I am trying this with intentService. Getting an exception intent receiver is leaked. "Are you missing a call to unregisterReceiver?" Can anyone throw any light on it? – Yasir Nov 27 '14 at 20:31
  • 3
    Register and unregister Receiver should be call from an unreference context, so using getApplicationContext() in your in intentService should resolve your problem. – smora Jan 02 '15 at 20:06
  • 1
    I'd recommend to register static receiver (e.g. that is registered in AndroidManifest), because application might be killed at the time user dismissed notification. Static receiver ensures that code will be executed even if application is dead already. – pepyakin Apr 17 '15 at 11:08
  • It's only possible to register a broadcast receiver statically if it's a public class or static nested class. So then you don't have the context to the variable you're trying to change – Rule Aug 18 '15 at 09:54
1

Andrei is correct.
If you want multiple messages back such as:

  • you want to know if the message was clicked
  • you attached an action with an icon that you want to catch
  • AND you want to know if the message was canceled

you must register each of those response filters:

public void showNotification(Context ctx, String text) ()
{
    /… create intents and pending intents same format as Andrie did../
    /… you could also set up the style of your message box etc. …/

    //need to register each response filter
    registerReceiver(receiver, new IntentFilter(CLICK_ACTION));
    registerReceiver(receiver, new IntentFilter(USER_RESPONSE_ACTION));
    registerReceiver(receiver, new IntentFilter(NOTIFICATION_DELETED_ACTION));

    Notification n = new Notification.Builder(mContext)
      .setContentText(text)
      .setContentIntent(pendingIntent)                          //Click action
      .setDeleteIntent(pendingCancelIntent)                     //Cancel/Deleted action
      .addAction(R.drawable.icon, "Title", pendingActionIntent) //Response action
      .build();

    NotificationManager.notify(0, n);

}

Then you can catch the different responses with if, else statements (as Andrei did), or with a switch statement.

Note: I make this response primarily because I could not find this anywhere, and I had to figure it out on my own. (perhaps I will remember it better for that :-) Have Fun!

Chuck
  • 339
  • 2
  • 7