17

Solved while writing this question, but posting in case it helps anyone:

I'm setting multiple alarms like this, with different values of id:

AlarmManager alarms = (AlarmManager)context.getSystemService(
        Context.ALARM_SERVICE);
Intent i = new Intent(MyReceiver.ACTION_ALARM);  // "com.example.ALARM"
i.putExtra(MyReceiver.EXTRA_ID, id);  // "com.example.ID", 2
PendingIntent p = PendingIntent.getBroadcast(context, 0, i, 0);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, nextMillis, 300000, p);  // 5 mins

...and receiving them like this:

public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(ACTION_ALARM)) {
        // It's time to sound/show an alarm
        final long id = intent.getLongExtra(EXTRA_ID, -1);

The alarm is delivered to my receiver at the right times, but often with EXTRA_ID set to the wrong value: it's a value that I have used at some point, just not the one that I wanted delivered at that particular time.

Chris Boyle
  • 11,423
  • 7
  • 48
  • 63

3 Answers3

25

The documentation for PendingIntent.getBroadcast() says:

Returns

Returns an existing or new PendingIntent matching the given parameters.

The problem is that two Intents differing only in extras seem to match for this purpose. So getBroadcast() will return some random old PendingIntent (with a different EXTRA_ID) instead of a new one around the Intent I just created. The fix is to supply a data Uri and make it differ with the id, like this:

Intent i = new Intent(MyReceiver.ACTION_ALARM, Uri.parse("timer:"+id));

You can then retrieve the id number using:

Long.parseLong(intent.getData().getSchemeSpecificPart());

...or of course supply the extra as well and use that.

Chris Boyle
  • 11,423
  • 7
  • 48
  • 63
  • Just wondering, if I new an intent with Intent i = new Intent(context, Cls); Do I have this mixed id problem? In my case, the Cls is different for different Alarms. It should be OK, right? – Safecoder Feb 04 '12 at 05:31
  • I currently can't find the exact place I looked before to see the point about extras, but yes, with a different class it's a completely different Intent so I would very much expect that to work. – Chris Boyle Feb 05 '12 at 14:30
  • 1
    @ChrisBoyle, Thanks very much. But in my case, it doesn't work. However this works: `Intent intent = new Intent(null, Uri.parse(Long.toString(id)), context, AlarmActivity.class);`. Note that I can use activity. –  Mar 21 '12 at 06:18
  • After adding this line my AlarmReceiver(Broadcast Receiver) doesnt work at all. I want to set multiple alarms at a single point of time. Can I get some help? Thank you. – Ahmed Dec 10 '13 at 20:25
7

You could also use the flag PendingIntent.FLAG_UPDATE_CURRENT

PendingIntent p = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);

this should the work too

pankajagarwal
  • 13,462
  • 14
  • 54
  • 65
  • 2
    If you were only going to use it once at a time, then yes, but for an alarm with multiple timers set, you need multiple PendingIntents to be valid concurrently, and FLAG_UPDATE_CURRENT would leave you with all alarms sending the single most recent Intent. – Chris Boyle Jan 06 '11 at 09:23
3

The solution for your problem is use Intent.FLAG_ACTIVITY_NEW_TASK

  p = PendingIntent.getBroadcast(context, 0, i, Intent.FLAG_ACTIVITY_NEW_TASK);
DineshKumar
  • 1,641
  • 15
  • 13