Wednesday, September 26, 2012

PendingIntents in Android

PendingIntents in Android are fundamentally used for allowing other apps to perform actions on behalf of your app regardless of your app is alive or not. For example, if you want to perform some action in the future, you just create a PendingIntent and populate with an Intent and then giving this to the AlarmManager to wake you up at the specified time. Simple enough!. 

Complexity appears when you want to control the pending intents. Just think about a scenario in which you created a PendingIntent and want to perform an operation in the future. However, you realized that you no longer need to perform this operation which means you now need to cancel it. Android provides cancel operation in AlarmManager so no problem. In order to cancel it you need to create the same PendingIntent with the same intent in it. Newly created intent should return true for the intent.filterEquals(Intent otherOne) method. If it fails, then cancel operation will not succeed. This method basically looks for the same action, data, type, class, and categories for the same intents. So far so good!. Now think about a scenario where you need to create multiple pending intents, but want to use the same BroadcastReceiver. There are two alternatives here: first you can create an intent with different intentFilters, i.e. action. So you need to register your broadcast receiver to every different intentFilter you create. Sigh!. And the worst part is when you want to unregister, there is no option of unregistering for a particular intentFilter. If you unregister your receiver, all of the intentFilters goes away automatically. 

There is a hidden parameter called requestCode while creating the PendingIntent and it basically serves this purpose. If you create exactly the same pending intents but differ only in requestCode then canceling one doesn't cancel the other one. It means requestCode can be used to uniquely identify pending intents. Therefore, you can use the same BroadcastReceiver (and registers one) with the same intent, but with different PendingIntents if you change the requestCode. The funny and sad thing about this is: Android documentation states that "request code is currently not used". On the other hand, it is actually used to differentiate PendingIntents and it is quite useful.

1 comment:

  1. I don't really want a loud alarm but maybe I could use vibrate. I definitely don't want to wake up any device. My scenario is the user already has their device on and now they want to set a timer to notify them every 5 minutes and a different notification at the end of one hour. The beeper thing seemed perfect but I cannot figure out how to make it work and maybe it is deprecated and no longer a valid technique.

    Also alarm manager seems to want intervals longer than 5 minutes, every 15 minutes or 30 or every hour are day or 10 days.

    ReplyDelete