6

I have an alarm receiver that does some checks and then creates a Notification for each check. This means it can create more than one Notification. This all works fine. However, I have an Intent connected to the notification to start an activity when the notification is tapped.

This is the notification code:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, CHANNEL_OUTPUT_LEVELS)
                .setSmallIcon(icon)
                .setContentTitle(title)
                .setContentText(message)
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText(longmessage))
                .setContentIntent(getPendingIntent(solarEdge, reason))
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);

// notificationId is a unique int for each notification that you must define
// we use the installation's ID to make sure all notifications get sent
notificationManager.notify(solarEdge.getInfo().getId(), mBuilder.build());

The method that creates the PendingIntent is:

private PendingIntent getPendingIntent(SolarEdge solarEdge, int reason) {
    String apikey = solarEdge.getApikey();
    int installationId = solarEdge.getInfo().getId();

    Intent intent = new Intent(context, InstallationActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    intent.putExtra(EXTRA_API_KEY, apikey);
    intent.putExtra(EXTRA_INSTALLATION_ID, installationId);
    intent.putExtra(EXTRA_REASON, reason);

    return PendingIntent.getActivity(context, 0, intent, 0);
}

Problem I have, is that even I create a different intent, it still always calls the Activity with the same extras (apikey and installid). It always takes the first one created.

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195

3 Answers3

16

It seems that the problem is caused by the arguments you passed to the getActivity method.

Try the following code

PendingIntent.getActivity(context, <unique_value_per_every_call>, intent, 0);

The second argument is requestCode so it should be unique.

CROSP
  • 4,499
  • 4
  • 38
  • 89
  • @BartFriederichs you are welcome, docs sometime doesn't contain important information. – CROSP Feb 14 '19 at 21:47
  • 1
    @BartFriederichs it being a request code implies that it should be unique for that request, but I've fallen for it too. – TheWanderer Feb 14 '19 at 21:49
  • 1
    To get a unique `PendingIntent` on every call, the call to `PendingIntent.getActivity()` needs to provide **either** a unique requestCode **or** a unique `Intent`. To make the `Intent` unique it is necessary to provide **either** a unique ACTION, DATA, or COMPONENT. There are therefore several ways to solve this problem. – David Wasser Feb 15 '19 at 14:49
2

The accepted answer is one way to solve the problem, but it isn't the only way.

To get a unique PendingIntent on every call, the call to PendingIntent.getActivity() needs to provide either a unique requestCode or a unique Intent. To make the Intent unique it is necessary to provide either a unique ACTION, DATA, or COMPONENT. There are therefore several ways to solve this problem.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
0

Known "problem"/quirk/design and we programmers keep running into it. The request code parameter must be something other than 0 if the intent is the same (action, data or component the same, not only extra data differs).

int requestCode = 1;
PendingIntent.getActivity(context, requestCode, intent, 0);

Additionally:

If you want to update a notification/pending intent later on you can use the same requestCode.

If you add multiple pending intents they must all be different. Example: A stop and a pause action.

I usually follow this pattern:

requestCode = 1 for the content intent.
requestCode = 2 for first action
requestCode = 3 for second action
etc
Mattias Isegran Bergander
  • 11,811
  • 2
  • 41
  • 49
  • It actually has to be unique per call. If I put in just 1, it still doesn't work correctly. – Bart Friederichs Feb 14 '19 at 21:47
  • Not per call, but per intent you intend to add. If you want to update it later on, for exampel changing a "play" intent to a "pause" intent , you use the same. – Mattias Isegran Bergander Feb 14 '19 at 21:51
  • This is just wrong. The request code does not need to be non-zero. To get a unique `PendingIntent` on every call, the call to `PendingIntent.getActivity()` needs to provide **either** a unique requestCode **or** a unique `Intent`. To make the `Intent` unique it is necessary to provide **either** a unique ACTION, DATA, or COMPONENT. There are therefore several ways to solve this problem, but changing the requestCode to "1" isn't one of them. – David Wasser Feb 15 '19 at 14:46
  • Oh yes totally agree on that you can also make the intent unique as you say. – Mattias Isegran Bergander Feb 16 '19 at 13:24