How to dismiss notification after action has been clicked
Solution 1
When you called notify on the notification manager you gave it an id - that is the unique id you can use to access it later (this is from the notification manager:
notify(int id, Notification notification)
To cancel, you would call:
cancel(int id)
with the same id. So, basically, you need to keep track of the id or possibly put the id into a Bundle you add to the Intent inside the PendingIntent?
Solution 2
Found this to be an issue when using Lollipop's Heads Up Display notification. See design guidelines. Here's the complete(ish) code to implement.
Until now, having a 'Dismiss' button was less important, but now it's more in your face.
Building the Notification
int notificationId = new Random().nextInt(); // just use a counter in some util class...
PendingIntent dismissIntent = NotificationActivity.getDismissIntent(notificationId, context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setPriority(NotificationCompat.PRIORITY_MAX) //HIGH, MAX, FULL_SCREEN and setDefaults(Notification.DEFAULT_ALL) will make it a Heads Up Display Style
.setDefaults(Notification.DEFAULT_ALL) // also requires VIBRATE permission
.setSmallIcon(R.drawable.ic_action_refresh) // Required!
.setContentTitle("Message from test")
.setContentText("message")
.setAutoCancel(true)
.addAction(R.drawable.ic_action_cancel, "Dismiss", dismissIntent)
.addAction(R.drawable.ic_action_boom, "Action!", someOtherPendingIntent);
// Gets an instance of the NotificationManager service
NotificationManager notifyMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// Builds the notification and issues it.
notifyMgr.notify(notificationId, builder.build());
NotificationActivity
public class NotificationActivity extends Activity {
public static final String NOTIFICATION_ID = "NOTIFICATION_ID";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(getIntent().getIntExtra(NOTIFICATION_ID, -1));
finish(); // since finish() is called in onCreate(), onDestroy() will be called immediately
}
public static PendingIntent getDismissIntent(int notificationId, Context context) {
Intent intent = new Intent(context, NotificationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra(NOTIFICATION_ID, notificationId);
PendingIntent dismissIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return dismissIntent;
}
}
AndroidManifest.xml (attributes required to prevent SystemUI from focusing to a back stack)
<activity
android:name=".NotificationActivity"
android:taskAffinity=""
android:excludeFromRecents="true">
</activity>
Solution 3
I found that when you use the action buttons in expanded notifications, you have to write extra code and you are more constrained.
You have to manually cancel your notification when the user clicks an action button. The notification is only cancelled automatically for the default action.
Also if you start a broadcast receiver from the button, the notification drawer doesn't close.
I ended up creating a new NotificationActivity to address these issues. This intermediary activity without any UI cancels the notification and then starts the activity I really wanted to start from the notification.
I've posted sample code in a related post Clicking Android Notification Actions does not close Notification drawer.
Solution 4
You will need to run the following code after your intent is fired to remove the notification.
NotificationManagerCompat.from(this).cancel(null, notificationId);
NB: notificationId is the same id passed to run your notification
Solution 5
In my opinion using a BroadcastReceiver
is a cleaner way to cancel a Notification:
In AndroidManifest.xml:
<receiver
android:name=.NotificationCancelReceiver" >
<intent-filter android:priority="999" >
<action android:name="com.example.cancel" />
</intent-filter>
</receiver>
In java File:
Intent cancel = new Intent("com.example.cancel");
PendingIntent cancelP = PendingIntent.getBroadcast(context, 0, cancel, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Action actions[] = new NotificationCompat.Action[1];
NotificationCancelReceiver
public class NotificationCancelReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//Cancel your ongoing Notification
};
}
Related videos on Youtube
endowzoner
I'm curious about any kind of innovation in the area of mobile computing as well as great products using web and mobile technologies. As the mobile world cannot be reduced to one platform and there is not one kind of mobile technology at all, I'm open-minded for new and alternative evolutions and do not focus on only one specific technology. Therefore, I'm also highly interested in the international technology start-up scene. I admire everyone who comes up with a great new idea and product and brings it to the market successfully. Currently, in my rare spare time I'm trying to get into great presentation techniques and improve my presentation skills. I think having a great idea is one part, but presenting it accordingly and to the right people is even more important than the ideal itself.
Updated on April 09, 2022Comments
-
endowzoner about 2 years
Since API level 16 (Jelly Bean), there is the possibility to add actions to a notification with
builder.addAction(iconId, title, intent);
But when I add an action to a notification and the action is pressed, the notification is not going to be dismissed. When the notification itself is being clicked, it can be dismissed with
notification.flags = Notification.FLAG_AUTO_CANCEL;
or
builder.setAutoCancel(true);
But obviously, this has nothing to with the actions associated to the notification.
Any hints? Or is this not part of the API yet? I did not find anything.
-
endowzoner almost 12 yearsBut how do I get access to the notification in the activity which has been called?
-
endowzoner almost 12 yearsThanks, that solved my issue. However, I still think it is a little bit over-complicated. Instead of just providing an API to auto-dismiss the notification when an action is pressed, you have to work with intent and notification id passing to achieve the same.
-
CommonsWare almost 12 years@FleshWound:
cancel()
takes the ID of theNotification
, which you used when you callednotify()
. You do not need theNotification
object. -
Travis over 11 yearsIf you think this is complicated, don't look into updating a notification (don't lose track of that id), or checking whether it's displayed or not (the api doesn't track it, you have to)... :P
-
Daksh over 11 yearsHow did you do that @FleshWound ? Can you please supply me with your code? thanks!
-
endowzoner over 11 years@Daksh: Basically, you add the notification tag and id to your intent which gets started when your action is pressed. With that extra information, you can check in the starting activity whether it was started via a notifcation action.
-
endowzoner over 11 yearsCode sample from onCreate(): Bundle extras = getIntent().getExtras(); if (extras != null) { String tag = extras.getString(NotificationReceiver.INTENT_EXTRA_NOTIFICATION_TAG); int id = extras.getInt(NotificationReceiver.INTENT_EXTRA_NOTIFICATION_ID); if (NotificationReceiver.NOTIFICATION_ID == id && NotificationReceiver.NOTIFICATION_TAG.equals(tag)) { // activity has been started via notification action, dismiss // notification NotificationManager manager = (NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE); manager.cancel(tag, id); } }
-
Daksh over 11 yearsmy action is to Call a specific number. thus it opens up the Phone app and dials the number. so then how do i do it? is there a way to set up a listener for the call intent Intent.ACTION_DIAL and then check the data in the intent extras? if i'm on some sort of right path, then i would really appreciate code for that too!
-
Kaediil over 11 years@Daksh I would open up a new question for what you want to do. Tell people what you have tried and add other info like sample code they can correct.
-
Prasad about 9 yearsi have multiple notifications from one application and the notifaaction are set to ongoing notification. I want to clear the notification when addaction performs on perticular notification
-
Bogdan Zurac about 9 yearsToo bad they still haven't baked this into the API... It's pretty hackish to do it like this. But still the only way, especially if you don't have any control over the destination intent, like viewing a URL.
-
alice.harrison about 9 yearsWould it not be more effective to use a BroadcastReceiver here to dismiss the notification instead? Here is a good example that shows the implementation, but it can be even further reduced: stackoverflow.com/a/19745745/793150
-
Baschi over 8 yearsSolutions works, except the extras set are forwarded with the intent. They are not forwarded to onCreate. One way is to use static variables. Does anybody know, why the intent extras are not forwarded?
-
Tim about 8 yearsThanks for the info, you're correct. However I would use an intentservice rather than an intermediary activity
-
Marco Zanetti about 8 yearsThat's what I do but how do you get the notification ID (in this example, 0) from the onReceive method? It's not in the Intent, since it's not been added to it. I tried adding it as an extra but it seems like the real notification ID is not the one I was adding as an extra in the creating activity... :-/
-
Christophe Moine over 7 yearsI really like this approach of using Broadcast services instead of Activities, it is much lighter approach imho.
-
Christophe Moine over 7 yearsBut I had to use <intent.setAction(Integer.toString(notificationId));> in adidition to be able to dismiss any of the notification shown.
-
Ray Li about 7 yearsWhy does getDismissIntent only work when placed in the NotificationActivity? The dismiss Intent does not work if the PendingIntent creation code is placed in the notification builder class. I just spent 2 hours on this issue and I cannot figure out why the Pending Intent MUST be created in the Activity. Can anyone explain why this is the case?
-
Ray Hunter almost 7 years@MarcoZanetti you need to generate a notification id that you pass to the pending intent and also to the notify method when sending the notification. If you do that, then when user clicks the action to cancel it will call the broadcast receiver and then you can get the notification id from the extras.
-
Kushan over 6 yearsThis no longer works if setGroup is set to true and there is a group summary. In this case, the cancel somehow has no effect despite using correct id
-
Kushan over 6 years@CommonsWare cancel(id) has stopped working if the setGroup is set and there is a Group summary notification. In this case, the cancel does not do anything for some reason. Without the group summary, cancel works fine though
-
Mike about 6 yearsgetDismissIntent() is a static "helper" function that builds the correct Intent to use to communicate with the NotificationActivity. As such, these are usually bundled with the Activity. But I don't see why this static function could not be placed in the notification builder class, as long as you are careful to set the NOTIFICATION_ID and context correctly.
-
Malachiasz over 5 yearsIn new API you have notify(String tag, int id, Notification notification) and correspondingly cancel(String tag, int id)
-
Alix about 5 yearsAutoCancel seems to have no effect when targetting Android 9 (worked fine when targetting Android 8.1)
-
Vadim Kotov almost 5 years@ChristopheMoine you can put id via
intent.putExtra()
and get it inBroadcastReceiver
-
sud007 about 4 yearsYou were right! although
cancel()
function has 2 implementations; one with TAG and one without. But we have to provide aTAG
. Here iscancel
function from docspublic void cancel(@Nullable String tag, int id)
. Last checked on Android Q -
Someone Somewhere almost 4 yearsthe distinction here is with action's
-
Someone Somewhere almost 4 yearsThis sucks - it means every action in a notification needs to be captured by my app when the user wants to do something, i.e. [SHARE]
-
Someone Somewhere almost 4 yearsif my pending intent is
ACTION_VIEW
and the type isimage/jpeg
(to share an image with another app) then how is that cancel supposed to be triggered ? IMO Android should auto-cancel, I'm puzzled as to why Android doesn't just take care of it ?! -
CommonsWare almost 4 years@SomeoneSomewhere: "then how is that cancel supposed to be triggered ?" -- it can't. While there is nothing stopping you from pointing to a third-party app in a
Notification
-relatedPendingIntent
, that's not really how it was designed to work, and so you will run into issues like this one. "IMO Android should auto-cancel" -- I could see offering a flag for that on the action, but it should not be an all-the-time thing. If it were, skipping a track in a music player notification would close the notification. -
Someone Somewhere almost 4 yearsWhat I've ended up implementing is: notification Action triggers IntentService, that IntentService cancels the notification and either 1) creates a new intent and triggers the intent chooser or 2) performs a specific action within the app
-
DIRTY DAVE over 2 yearsTested on API 24, 27, 30, 31 and the notification does indeed close after clicking on it.