143

i am creating a notification inside a BroadcastReceiver via this code:

String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(ns);
        int icon = R.drawable.ic_stat_notification;
        CharSequence tickerText = "New Notification";
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, tickerText, when);
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        long[] vibrate = {0,100,200,200,200,200};
        notification.vibrate = vibrate;
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        CharSequence contentTitle = "Title";
        CharSequence contentText = "Text";
        Intent notificationIntent = new Intent(context, NotificationActivity.class);
        notificationIntent.putExtra(Global.INTENT_EXTRA_FOO_ID, foo_id);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

        notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

        int mynotification_id = 1;

        mNotificationManager.notify(mynotification_id, notification);

When I click on the notification, it opens the NotificationActivity and inside the Activity i can retrieve the foo_id from the Intent-Bundle (e.g. 1)

However if another notification is triggered and i click on it again, the activity still receives the "old" value (1) from the Intent-Bundle. I've tried to clear the bundle with clear(), but am receiving the same effect. I think sth is wrong with my code..

Sujatha Girijala
  • 953
  • 7
  • 20
BrianM
  • 1,463
  • 2
  • 9
  • 5

6 Answers6

281

You are sending the same request code for your pending intens. Change this:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

To:

PendingIntent contentIntent = PendingIntent.getActivity(context, UNIQUE_INT_PER_CALL, notificationIntent, 0);

intents are not created if you send the same params. They are reused.

IncrediApp
  • 10,083
  • 2
  • 29
  • 24
  • 1
    so the UNIQUE_INT_PER_CALL is an Integer I have to provide? or is this a static variable declared somewhere? – BrianM Sep 10 '11 at 08:17
  • 23
    android gotcha #147 - so an `Intent` that has *different* extras (via `putExtra`) are considered the same and re-used because i did not provide a unique id to some pending intent call - terrible api – wal Nov 30 '16 at 07:07
  • you know what, I were so careless. Just thinking how could it remain 0 in one block (in my case) :( – Exigente05 Jan 27 '17 at 15:31
  • 3
    This was incredibly useful for me, just a tip for others, it is likely that you are building your notification in the same method, and so you can just set the id for the new pending intent to the same as the one you are going to use for the notifications unique id! – James McNee Jan 31 '17 at 15:39
  • 1
    @IncrediApp, is it same with PendingIntent.getBroadcast(); ? – Shruti Apr 20 '17 at 06:54
144

Alternatively, you can use the following code to generate your PendingIntent:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

From the doc for PendingIntent.FLAG_UPDATE_CURRENT:

If the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent. This can be used if you are creating intents where only the extras change, and don't care that any entities that received your previous PendingIntent will be able to launch it with your new extras even if they are not explicitly given to it.

ChristophK
  • 3,009
  • 2
  • 22
  • 28
43

You are passing the same ID. In this kind of situation, make a unique id from time like this:

int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);

And put it as this:

PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),iUniqueId, intentForNotification, 0);
Rishabh Maurya
  • 1,272
  • 3
  • 19
  • 37
hderanga
  • 1,229
  • 12
  • 12
  • 3
    why not use new Random().nextInt() – exloong Dec 05 '16 at 05:58
  • @hderanga what does adding "& 0xfffffff" do to the int above? – AJW May 23 '18 at 19:54
  • 3
    @AJW `System.currentTimeMillis()` returns a long, while the `requestId` parameter of `PendingIntent.getActivity()` takes an int. `0xffffffff` is a bitmask. While there's a bit more to it, the simple explanation is that doing `long & 0xffffffff' gives the lowest 32-bits from the long and discards the highest 32-bits, leaving you with essentially a 32-bit int. This is better than simply casting to an int because it won't muck up the sign bit (if you cast a long that is bigger than an int to an int the sign bit will overflow and you'll potentially wind up with a negative value) – Jordan Dec 12 '18 at 22:57
9

For anyone looking for the best approach after a long time all, you need to pass the PendingIntent.FLAG_UPDATE_CURRENT as the last argument as shown below

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

you don't even need to provide a new unique id.

You need to do this for next time onwards not for the first time

Gentle
  • 428
  • 6
  • 11
0

Your request code is 0 for all the notification. Change following line:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

With:

PendingIntent contentIntent = PendingIntent.getActivity(context, new Random().nextInt(), notificationIntent, 0);
Faisal Shaikh
  • 3,131
  • 2
  • 34
  • 66
  • 1
    Is there any benefit to using "new Random().nextInt()" rather than "System.currentTimeMillis()"? – AJW May 23 '18 at 19:56
  • using random can easily regenerate the same integer value again on accident, thus causing a very hard to find bug of old intents being passed. – Sam May 30 '18 at 16:36
  • @AJW there was in my case. I created 2 different notifications in exact same millisecond, so one of them got wrong extras. – artman Jul 23 '18 at 09:47
0

Just wanted to add another option

 PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
pellucide
  • 2,868
  • 2
  • 18
  • 23