35

This questions somehow relates to the question when I was looking to get the extras back in startActivityForResult but now I face another challenge.

I have subscribed to receive ProximityAlerts and I have explicitly constructed the Intent to include some Extras. But when I got the service the extras are not there.

After the answers here is the working code:

Intent intent = new Intent(this, PlacesProximityHandlerService.class);
intent.setAction("PlacesProximityHandlerService");
intent.putExtra("lat", objPlace.getLat());
intent.putExtra("lon", objPlace.getLon());
intent.putExtra("error_m", objPlace.getError()+ALERT_RANGE_IN_METERS);
PendingIntent sender=PendingIntent.getService(this, 0, intent, 0);
LocationUtils.addProximity(this, objPlace.getLat(), objPlace.getLon(),objPlace.getError()+ALERT_RANGE_IN_METERS, -1, sender);

The documentation says param PendingIntent to be sent for each location update

Community
  • 1
  • 1
Pentium10
  • 190,605
  • 114
  • 394
  • 474

5 Answers5

43

For some unspecified reason, extras will be delivered only if you've set some action, for example setAction("foo"). What CommonsWare refers to applies only when obtaining PendingIntent instances, if you haven't set FLAG_ONE_SHOT. That can be fixed by the requestCode argument in PendingIntent.get... factory methods. Although documentation says it's currently not used, it actually takes into count when distinguishing PendingIntents.

In your case, you don't need to set anything else than some dummy action string. LocationManagerService reuses the PendingIntent you have subscribed for proximity alerts, and only adds a flag if phone has entered or exited the alarm range.

ognian
  • 11,291
  • 4
  • 32
  • 33
  • 1
    i tried this and it diddnt work. i set an action on my intent first and then the extras and after i then created a pending intent that fires off a broadcast reciever that fires this using a alarm manager – Jonathan Mar 02 '18 at 16:38
25

If you have multiple outstanding PendingIntents, you need to make sure that the underlying Intents differ on more than their extras. Otherwise, Android will keep reusing the first PendingIntent you created for your first Intent, using that first Intent's extras all of the time.

For example, you could add a unique action via setAction() -- that will not change your Intent routing (since you are specifying the component), but it will make your Intents different.

CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
  • I was able to get it to work with setAction as well. In my case I created a unique string for every setAction call. – drogon Oct 21 '12 at 21:26
  • What about PendingIntent.FLAG_ONE_SHOT? I thought this solved the problem. – Sotti Sep 03 '15 at 17:15
  • @Sotti: `FLAG_ONE_SHOT` says that the `PendingIntent` can only be executed once. Now, ideally, that would *also* mean that an attempt to create a new `PendingIntent` on an equivalent `Intent` would return a distinct `PendingIntent`... and it might. However, that's not documented behavior, and so I'm hesitant to recommend `FLAG_ONE_SHOT`. Now, the accepted answer on this question says it works, and it's been upvoted a fair bit, so perhaps it is safe. Personally, given Google's track record, I tend to be a bit conservative on edge cases like this. – CommonsWare Sep 03 '15 at 17:19
8

I had this problem and the solution I found was quite simple, though I can't explain why it worked.

Initially my pending intent looked like this:

     notificationIntent = new Intent(ctx, FragmentTabsPager.class);
     notificationIntent.setData(Uri.parse("content://com.sbs.mobile.workorder.WorkOrder/notes/"));
     notificationIntent.putExtra("NOTIFICATION", true);   
     notificationIntent.putExtra(WorkOrder.WorkOrderColumns.WORKORDERID, submessage);

When creating the intent like this, no extras would be passed when the notification was clicked, the extras map would be empty in the receiving activity. I made the following change to the line initializing the notificationIntent:

     notificationIntent = new Intent().setClass(ctx, FragmentTabsPager.class);

Now the extras are populated in the receiving activity. Again, I can't explain why this works but it fixed my problem.

  • 1
    i tried this out of desperation, and surprisingly it worked... looking at the code, there doesn't seem to be any reason why doing it this way would be any different. sigh. – handler Jan 20 '15 at 23:37
2

None of the answers worked for me. Setting action to a specific string works for the first time but if you use the same notification with different extras at a later time, it would not work. I replaced the string for the setAction method with a randomly generated one and it works without any issues:

intent.setAction(new Random().nextInt(50) + "_action");
  • If you think that you might use the notification a lot (Like for downloading different files) then pass a larger number to nextInt()
Vahid Amiri
  • 10,522
  • 12
  • 59
  • 102
1

The key is to set the extras and the unique action into the intent before calling

PendingIntent sender=PendingIntent.getService(this, 0, intent, 0);

if you set the extras and action into the intent after calling the above, it won't work. This will not work:

Intent intent;  
PendingIntent sender=PendingIntent.getService(this, 0,   
   intent=new Intent(this, PlacesProximityHandlerService.class), 0);  

intent.setAction("PlacesProximityHandlerService");  
intent.putExtra("lat", objPlace.getLat());  
inor
  • 2,423
  • 2
  • 22
  • 39