124

Background:

I'm using PendingIntent for alarms via AlarmManager.

The problem:

At first I thought that in order to cancel previous ones, I must provide the exact requestCode that I've used before to start the alarm.

But then I've found out I was wrong, as the cancellation API says:

Remove any alarms with a matching Intent. Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled.

looking at "filterEquals", the documentation says:

Determine if two intents are the same for the purposes of intent resolution (filtering). That is, if their action, data, type, class, and categories are the same. This does not compare any extra data included in the intents.

so I don't get what the "requestCode" is for...

The question:

What is "requestCode" used for?

What if I create multiple alarms with the same "requestCode" ? do they override each other?

android developer
  • 106,412
  • 122
  • 641
  • 1,128
  • if you use the same requestCode you will get the same PendingIntent – pskink Feb 03 '14 at 11:44
  • 3
    For PendingIntent.getBroadcast(), requestCode is apparently ignored by Android. As of API 22, it won't make your Pending Intent unique. Does for getActivity() (and perhaps getService() but I haven't tested). http://stackoverflow.com/a/33203752/2301224 – Baker Oct 19 '15 at 06:01
  • @Baker Isn't this considered a bug? If it is a bug, you should write about it here: https://code.google.com/p/android/issues/list – android developer Oct 19 '15 at 07:43
  • 1
    Well, actually, the documentation does specify the usaga of the requestiCode: `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. ` – Eir Apr 25 '20 at 08:13
  • @Eir Right, so what's the point in using the requestCode? Where can it be used? – android developer Apr 26 '20 at 06:10
  • @androiddeveloper one example is given in the documentation I posted: `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 can distinguish them by the requestCode, because everything else about them is same. In my app I have five different PendingIntents, all of them for a different purpose. I use a different requestCode so that they are not mixed by the system. – Eir Apr 26 '20 at 07:16
  • @Eir I'm confused. You just said that requestCode doesn't affect the differentiation, and now you say the opposite. Please explain what's the real behavior with it. According to what I've tested (or at least from what I remember), it's useless as it doesn't differentiate at all, and you could just put some extra data to make them different instead. – android developer Apr 26 '20 at 20:41
  • @androiddeveloper Ok, I'll make that an answer, so that there is no confusion. – Eir Apr 27 '20 at 08:30

6 Answers6

87
  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.
stkent
  • 18,470
  • 14
  • 80
  • 99
Minhaj Arfin
  • 931
  • 8
  • 8
  • 6
    is setting the requestCode to be unique needed even in case the alarms' intents are very different (one for service A and one for service B , for example ) ? Also, how come the documentation doesn't say anything about it? Is it possible to remove all alarms of a certain type, no matter what is the requestCode? – android developer Feb 03 '14 at 12:36
  • 1
    No, It is not necessary for different intents. And I don't know why the documentation doesn't say anything about it, but I learnt this when setting repeating alarms and also when using the same intent. – Minhaj Arfin Feb 03 '14 at 12:46
  • is it only useful for cancelling alarms, or does it have additional uses? – android developer Feb 03 '14 at 12:48
  • It is also used in onActivityResult() when you use startActivityForResult. But there are not any other significant uses that I know of. I have only used it for cancelling alarms though. – Minhaj Arfin Feb 03 '14 at 13:05
  • 2
    I was talking about PendingIntent . startActivityForResult uses a normal intent. – android developer Feb 03 '14 at 13:41
  • You could also use startActivityForResult with PendingIntent using a proxy activity, well that's another topic.Like I said I don't think there's some other significant use other than for cancelling. – Minhaj Arfin Feb 04 '14 at 05:11
  • 2
    what is the purpose of "startActivityForResult with PendingIntent using a proxy activity" ? can you give an example? – android developer Feb 04 '14 at 06:27
  • There might not be any purpose. I'm just saying you can do it with pending intents using proxy activity, there might be some case where you'd need to. – Minhaj Arfin Feb 04 '14 at 06:44
  • but what does it mean to do it? isn't PendingIntent used for allowing other apps to have some functionalities/permissions of your app? what does it mean to use it for startActivityForResult ? – android developer Feb 04 '14 at 07:26
  • OK my bad, forget it. Simply put: -Request Code with Pending Intents are used for cancelling. -Request Code with Intents are used for onActivityResult. – Minhaj Arfin Feb 04 '14 at 07:37
  • wait, so it was a mistake? ok. so the request code for pendingIntent is used only for cancelling alarms, right? – android developer Feb 04 '14 at 07:41
  • it wasn't a mistake, i said you could do that with proxy activity, but there is no use for it. And yes, it is used for cancelling alarms. – Minhaj Arfin Feb 04 '14 at 07:48
  • what do you mean "you could do that" ? do what? put a request code when calling startActivityForResult ? – android developer Feb 04 '14 at 08:42
  • I meant you could use start activity for result with pending intent though there is no use of it. So that case is closed. Don't get confused on that statement, Coming back to your question the request code with pending intent is used for cancelling if the intents have the same action, data, type, class, and categories. – Minhaj Arfin Feb 04 '14 at 08:50
  • "have the same action, data, type, class, and categories." - and the request code, as it seems. about the " startActivityForResult ", I don't get how and why will it be useful when being used with PendingIntent, but thanks anyway... – android developer Feb 04 '14 at 08:58
  • 4
    I agree; the documentation for PendingIntent and AlarmManager are total sh!t - made worse by the fact that it's not possible to list alarms programmatically. – Someone Somewhere Aug 03 '15 at 19:27
  • I wonder if the documentation is purposefully bad in order to discourage people from using resources that may make the battery drain faster. – arthropod Nov 20 '17 at 22:32
  • Maybe my answer can give more clarity and certainty https://stackoverflow.com/a/38759473/3940133 – HendraWD May 08 '19 at 15:29
38

I just want to add to @Minhaj Arfin answer

1- requestCode is used to get the same pending intent later on (for cancelling etc)

2- Yes, they will get override as long as your specify the same Receiver to your Intent that you specify on your PendingIntent

example:

Intent startIntent1 = new Intent(context, AlarmReceiverFirst.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, startIntent1, 0);

Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, 0);

From above example, they will not override each other because the receiver is different(AlarmReceiverFirst and AlarmReceiverSecond)

Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, 0);

Intent startIntent3 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent3 = PendingIntent.getBroadcast(context, 0, startIntent3, 0);

From above example, they will override each other, because the receiver is same(AlarmReceiverSecond)

HendraWD
  • 2,646
  • 2
  • 27
  • 45
  • Intent startIntent4 = new Intent(context, AlarmReceiverSecond.class); PendingIntent pendingIntent4 = PendingIntent.getService(context, 0, startIntent4, 0); would be okay then? I mean, won't this override because it's calling getService() instead of getBroadcast()? – Jenix Oct 20 '16 at 10:03
  • Sorry to ask another question but because stackoverflow doesn't allow me to write a question without a single code line.. Doesn't the last argument of PendingIntent's methods like getBroadcast() have something to do with overriding? I used to put 0 there just like your example code above but I also saw many people were putting some specific option value instead of 0. – Jenix Oct 20 '16 at 10:12
  • 1
    @Jenix uou use `AlarmReceiverSecond.class` on the intent and then use `PendingIntent.getService()`. It will not work, since `AlarmReceiverSecond.class` is a `BroadcastReceiver`, not a `Service` – HendraWD Oct 20 '16 at 13:03
  • 1
    About flags, it is properties that you can set, that will make the behavior of your PendingIntent according to the flags you provided. 0 means all the flags off – HendraWD Oct 20 '16 at 13:08
  • Ah I was stupid haha What in the world was I thinking.. I was a little bit confused about PendingIntent and your answer was really helpful. And I just wanted to make it clearer but now realized my question didn't make any sense at first. Thanks! – Jenix Oct 20 '16 at 13:35
  • If I set different action on intent, what'd happen? – Mostafa Imran Oct 30 '16 at 13:23
  • @MostafaImran by action here, did you mean Intent.setAction();? – HendraWD Oct 31 '16 at 03:00
6

Actually, the documentation clearly states what the request code is used for:

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).

Since it seems that it still isn't that clear, let me try to explain:

When you want to use a PendingIntent object, you don't just instantiate one. Rather, you obtain one from the system using the PendingIntent static methods (getActivity, getBroadcast, getService etc). The system keeps a bunch of PendingIntent instances and gives you one. Which one it gives you, it depends on the input parameters you pass to these getter methods. Those input parameters are: Context, i.e. the target receiver of the intent, the Intent to use, requestCode and flags. When you pass the same Context, the same requestCode and the same Intent (meaning an intent that filterEquals with another intent), you get the same PendingIntent object. The point is that the system wants to have as few PendingIntent objects as possible, so it tends to reuse the existing ones, as much as possible.

For example, you have two calendar notifications, for two different dates. When you click on one of them, you want your app to open to the corresponding date of that notification. In that scenario, you have the same Context target, and the Intent object you are passing differ only in the EXTRA_DATA (which specifies the date that should be open). If you provide the same requestCode when obtaining the PendingIntent object, then you will end up with the same PendingIntent object. So, when creating the second notification, you will replace the old Intent object with the new EXTRA_DATA, and end up with two notifications pointing to the same date.

If you want to have two different PendingIntent objects, as you should in this scenario, you should specify a different requestCode when obtaining the PendingIntent object.

Eir
  • 767
  • 7
  • 20
  • But as I've mentioned, to cancel alarms, you can't use just the requestCode. It doesn't mean anything for it. You will have to put extra data to differentiate between them. I don't remember but I think you can even use the same requestCode for multiple alarms. – android developer Apr 27 '20 at 20:12
  • @androiddeveloper what you just said is incorrect. Try it. – Eir Apr 28 '20 at 08:19
2

in my case i want to open the same activity with two different intents so if two or more FCMS are there in the tray, any one of them will only open other will not, so i changed the requests codes of pending intent then it worked.

 PendingIntent pendingIntent =
                            PendingIntent.getActivity(this, **Some unique id for all GCMS** /* Request code */, intent,
                                    PendingIntent.FLAG_ONE_SHOT);
JSONParser
  • 1,071
  • 2
  • 12
  • 27
  • there was no need to check the code further for my case , can you tell in which case the pending intent instance will be required. With respect to question changing request code helped me to goto correct screen, I dont know whether is this the correct way and for me error was happening only when multiple FCMs were there in tray – JSONParser Dec 15 '18 at 09:06
  • So why set a different request-code, if you don't need it? – android developer Dec 15 '18 at 11:01
  • ok i will explain in detail , i had some ACTIVITY A , it is meant to show questions i will pass the id from notifications through intent and then make a network request for that id and fetch the particular question, so what was happening that when there are more than 1 notifications in notification tray and then I click on the any one of them i get the id of question which was in the first GCM , after changing the pending intent request code to some unique value it worked. I hope i made it clear now , if any more discussion is required i am there, i also want to learn more, thank you – JSONParser Dec 16 '18 at 08:51
  • Oh you meant that otherwise it wouldn't have worked at all, right? Sorry about the confusion. This question was asked a long time ago and I don't remember it well at all... – android developer Dec 16 '18 at 12:25
2

one important thing about requestCode that will seriously trouble your app is when using widgets. widgets will not work after phone reboot if their requestCode are the same. that means the pendingIndent you set on the remoteViews of your widget must be set unique requestCode, usually the widgetId accompanying a number.

Alireza Jamali
  • 603
  • 2
  • 4
  • 16
0

when building a PendingIntent, you are required to provide an integer called requestCode. The official documentation states that this is a “private request code for the sender”. However, request codes are also a fundamental way to distinguish between PendingIntent instances. You see, the getBroadcast() method is much more than a just a static factory for creating a PendingIntent instance

Lakshay Sharma
  • 1,039
  • 9
  • 12