I am writing an Android application where the user can choose several stocks to watch and gets alerted if an predefined alert condition is matched. The stock data is saved to 5 objects of a custom Parcelable class “alert” (one object per stock and condition). The periodic data update is done via a service started by an AlarmManager. The alert objects are passed to the service via putting them into the Intent which is put into the PendingIntent of the AlarmManager.
Intent intent = new Intent(this, UpdateService.class);
Bundle b = new Bundle();
saveAlertsToBundle(b);
intent.putExtras(b);
intent.setData(Uri.parse("updateManager"));
PendingIntent pendIntent = PendingIntent.getService(this,0,intent,0);
// 1min intervall
long intervall = DateUtils.MINUTE_IN_MILLIS * 1;
// time of first start
long firstStartDelay = DateUtils.SECOND_IN_MILLIS * 30;
long firstStart = System.currentTimeMillis() + firstStartDelay;
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// kill running
am.cancel(pendIntent);
//start new
am.setRepeating(AlarmManager.RTC_WAKEUP,firstStart,intervall,pendIntent);
My problem is:
When starting the service for the first time when there is only one object of alert passed to the service everything works fine. As soon as there are more alerts objects existing they also need to be passed to the service but this does not work with the code above. The service does not receive the updated intent with the additional alert objects , but only the initial one with only one alert object. The code above correctly creates an Intent holding the additional alert object, but they never get to the service.
So my question is, how to pass the updated intent to the already running AlarmManager.
I already tried stopping the AlarmManager (the line at the // kill running comment) and restarting it, but this does not work. Perhaps because of the intent not holding the same alert objects as at the time when he was created ? I tried to fix this by setting an uri in the data part of the intent but this also did not help.
Thanks for help.
Your problem is the way
PendingIntentworks. The system manages a pool ofPengingIntents. When your code does:This causes the system to search for a
PendingIntentthat matches the parameters you’ve passed in (in this case, yourIntent. However, the matching algorithm thatPendingIntentuses only compares certain fields of theIntentto determine if it is the one that you are looking for. In particular, it does not compare extras. So this means after you’ve created the firstPendingIntent, the call toPendingIntent.getService()will always return the samePendingIntentfrom the pool (and not create a new one, which is what you want).In order to make the call to
PendingIntent.getService()create a newPendingIntentevery time you call it, try making the parameters you pass to the call unique, like this:Since
requestCodewill be different for each call toPendingIntent.getService(), this should solve your problem.EDIT Based on OP’s comments below
You want to cancel the existing alarm and create a new one with new data. In that case you don’t need to use unique identifiers because you only want to have a single
PendingIntentin the pool. But, you want to change the data for that. Try this: