How to Create Multiple Pendingintents with the Same Requestcode and Different Extras

Is it possible to create multiple PendingIntents with the same requestCode and different extras?

Actually, you don't "create" PendingIntents. You request them from the Android framework. When you request a PendingIntent from the Android framework, it checks to see if there is already a PendingIntent that matches the criteria you pass as arguments. If so, it does not create a new PendingIntent, it just gives you back a "token" that points to the existing PendingIntent. If it doesn't find a matching PendingIntent, it will create one and then give you back a "token" that points to the one it just created. There are some flags that you can set to modify this behaviour, but not that much. The most important thing to understand here is the way the Android framework does the matching.

To do this it checks if the following parameters match (comparing the existing PendingIntent with the parameters you have passed):

  • Request codes must be the same. Otherwise they do not match.
  • The "action" in the Intent must be the same (or both null). Otherwise they do not match.
  • The "data" in the Intent must be the same (or both null). Otherwise they do not match.
  • The "type" (of the data) in the Intent must be the same (or both null). Otherwise they do not match.
  • The "package" and/or "component" in the Intent must be the same (or both null). Otherwise they do not match. "package" and "component" fields are set for "explicit" Intents.
  • The list of "categories" in the Intent must be the same. Otherwise they do not match.

You should notice that "extras" is not in the list above. That means that if you request a PendingIntent the "extras" are not taken into consideration when the Android framework tries to find a matching PendingIntent. This is a common mistake that developers make.

We can now address the additional flags that you can add to modify the behaviour of a PendingIntent request:

FLAG_CANCEL_CURRENT - When you specify this flag, if a matching PendingIntent is found, that PendingIntent is cancelled (removed, deleted, invalidated) and a new one is created. This means that any applications that are holding a "token" pointing to the old PendingIntent will not be able to use it, because it is no longer valid.

FLAG_NO_CREATE - When you specify this flag, if a matching PendingIntent is found, a "token" pointing to the existing PendingIntent is returned (this is the usual behaviour). However, if no matching PendingIntent is found, a new one is not created and the call just returns null. This can be used to determine if there is an active PendingIntent for a specific set of parameters.

FLAG_ONE_SHOT - When you specify this flag, the PendingIntent that is created can only be used once. That means that if you give the "token" for this PendingIntent to multiple applications, after the first use of the PendingIntent it will be canceled (removed, deleted, invalidated) so that any future attempt to use it will fail.

FLAG_UPDATE_CURRENT - When you specify this flag, if a matching PendingIntent is found, the "extras" in that PendingIntent will be replaced by the "extras" in the Intent that you pass as a parameter to the getxxx() method. If no matching PendingIntent is found, a new one is created (this is the normal behaviour). This can be used to change the "extras" on an existing PendingIntent where you have already given the "token" to other applications and don't want to invalidate the existing PendingIntent.

Let me try to address your specific problem:

You cannot have more than one active PendingIntent in the system if the request code, action, data, type and package/component parameters are the same. So your requirement to be able to have up to 35 active PendingIntents all with the same request code, action, data, type and package/component parameters, but with different "extras", is not possible.

I would suggest that you either use 35 different request codes, or create 35 different unique "action" parameters for your Intent.

Multiple Pending Intents?

A solution was found here: here.

You've to use setAction on the intent to a unique value so that there will be no matching PendingIntents

Here's what I used:

setAction(Long.toString(System.currentTimeMillis()))

What's requestCode used for on PendingIntent?

  1. requestCode is used to retrieve the same pending intent instance later on (for cancelling, etc).
  2. Yes, my guess is the alarms will override each other. I would keep the request codes unique.

Multiple Instances of Pending Intent

So happens that after posting my question, I came up with an answer. I pass in my appWidgetId as the "unique" request code and voila! Here is the snippet now:

Intent openApp = new Intent(context, RunningTally.class);
openApp.putExtra("widgetId", appWidgetId);
PendingIntent pendingAppIntent =
PendingIntent.getActivity(context, appWidgetId, openApp,
PendingIntent.FLAG_CANCEL_CURRENT);
views.setOnClickPendingIntent(R.id.openFull, pendingAppIntent);

Keep both pendingIntents with the same requestCode

I am asking if there exists a certain type of flag that will be able to differentiate them

There is not, and it makes sense because this is already the purpose of the requestCode parameter.

For information, these are your options regarding flags:

Sample Image

You will have to change your mechanism to make it possible to have different requestCodes for Pending Intents. It may be a lot of work, but it is what you have to do.

Android SDK - Set multiple alarms with same Intent different extras

Problem is that AlarmManager.setRepeative is not accurate as written in the official doc.

I was starting my program at 2:50AM so with the above code, first alarm should have been started 50 minutes beforeso it needs to be triggered but since another alarm is scheduled at 31M, the Android OS decides to wait for the 3AM alarm to trigger both (to lower battery consumption I guess).

Solution is to add 24h to the alarms if needed in order to be sure they are scheduled in the future and not in the past and to use AlarmManager.setExact which is exact but not repeative. Then Reschedule a new AlarmManager.setExact every day.

I would suggest to never use AlarmManager.setRepeative if you need better accuracy than 1 hour.

How to create unique pendingIntents without requestCode

this question maybe a duplicate of this.

Your requestCode must be unique otherwise PendingIntent will be updated to last intent if you use the same requestCode(old Api <22).

If your are not using action, you can add your UUID as de dummy action to make them unique.
You have to store the requestCode to be able to cancel old PendingIntent.

Why do the PendingIntents I create all carry the same extra?

Android considers your Intents to be equal because they only differ in the extras. Intents are considered equals if their action, data, type, class, and categories are the same. To make sure that each intent is kept, you need to change one of those five things.

From the PendingIntent documentation:

Because of this behavior, it is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals. If you use two Intent objects that are equivalent as per Intent.filterEquals, then you will get the same PendingIntent for both of them.

How can I correctly pass unique extras to a pending intent?

Possibly two different issues here:

1) If you've already created your PendingIntent before and it "matches" an existing PendingIntent, then you must specify the PendingIntent.FLAG_UPDATE_CURRENT flag or it will not pass the extras. A "match" is based on the criteria that Intent.filterEquals() uses, so definitely read the docs there and make sure you understand the data, action, type, etc.

2) I've read that if you do NOT set an action on your intent, then it will not propagate the extras, so perhaps try intent.setAction("com.blah.Action").

What is the request code in PendingIntent in android studio

The integer parameter requestCode is a way to differentiate between multiple intents that have the same action, data, type, identity, class, and categories. Otherwise if you create a second intent with those same properties, even if the extras are different, it will not work.

From the documentation

A PendingIntent itself is simply a reference to a token maintained by
the system describing the original data used to retrieve it. This
means that, even if its owning application's process is killed, the
PendingIntent itself will remain usable from other processes that have
been given it. If the creating application later re-retrieves the same
kind of PendingIntent (same operation, same Intent action, data,
categories, and components, and same flags), it will receive a
PendingIntent representing the same token if that is still valid, and
can thus call cancel() to remove it.

Because of this behavior, it is important to know when two Intents are
considered to be the same for purposes of retrieving a PendingIntent.
A common mistake people make is to create multiple PendingIntent
objects with Intents that only vary in their "extra" contents,
expecting to get a different PendingIntent each time. This does not
happen. The parts of the Intent that are used for matching are the
same ones defined by Intent#filterEquals(Intent). If you use two
Intent objects that are equivalent as per Intent#filterEquals(Intent),
then you will get the same PendingIntent for both of them.

There are two typical ways to deal with this.

If you truly need multiple distinct PendingIntent objects active at
the same time (such as to use as two notifications that are both shown
at the same time), then you will need to ensure there is something
that is different about them to associate them with different
PendingIntents. This may be any of the Intent attributes considered by
Intent#filterEquals(Intent), or different request code integers
supplied to getActivity(Context, int, Intent, int),
getActivities(Context, int, Intent[], int), getBroadcast(Context, int,
Intent, int), or getService(Context, int, Intent, int).

You are right by the way, the documentation on the specific parameter, Private request code for the sender is not very helpful in my opinion.



Related Topics



Leave a reply



Submit