PendingIntent is basically an object that wraps another Intent object. Then it can be passed to a foreign application where you’re granting that app the right to perform the operation, i.e., execute the intent as if it were executed from your own app’s process (same permission and identity). For security reasons you should always pass explicit intents to a PendingIntent rather than being implicit.
It can be used for various purposes like declaring an Intent which is executed at some point of time in future via the AlarmManager
class or one which is executed when the user performs some action with your app Notification.
What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.
A PendingIntent itself is a token referencing the original data (Intent action, data, categories, etc.) maintained by the system. Hence if the owning app’s (creator) process is killed, the PendingIntent will still remain usable from other app proesses that had received it. The owning app can later re-retrieve the PendingIntent token if that’s still valid by specifying the same set of data and then even cancel()
it.
Each explicit intent is supposed to be handled by a specific app component like Activity, BroadcastReceiver or a Service. Hence PendingIntent has different methods to handle different types of Intents that it wraps:
-
PendingIntent.getActivity()
– Retrieve a PendingIntent to start an Activity. -
PendingIntent.getBroadcast()
– Retrieve a PendingIntent to perform a broadcast. -
PendingIntent.getService()
– Retrieve a PendingIntent to start a Service.
Let’s get into some code now. We’ll create an Intent and wrap it into a PendingIntent:
// Explicit intent to wrap Intent intent = new Intent(this, LoginActivity.class); // Create pending intent and wrap our intent PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_CANCEL_CURRENT); try { // Perform the operation associated with our pendingIntent pendingIntent.send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); }
So we created an intent, wrapped it inside a PendingIntent and executed the operation associated with the pending intent (using send()
which is invoking LoginActivity
. Let’s once go through the arguments passed to getActivity()
:
-
this
(context) – This is the context in which the `PendingIntent` should start the activity. -
1
(requestCode) – This is a private request code for the sender. Use it later with the same method again to get back the same pending intent later. Then you can do various things like cancelling the pending intent withcancel()
, etc. -
intent
(intent) – Explicit intent of the activity to be launched. -
PendingIntent.FLAG_CANCEL_CURRENT
(flags) – One of the flags that can be passed that. This one states that if the described PendingIntent already exists, then the current one will be cancelled first and then the new one will be generated. I’ve seen some code samples where simply0
is passed which isn’t the value of any flags which probably means no flag is passed and the behaviour isn’t documented but I guess it’s similar toFLAG_CANCEL_CURRENT
.
Although this code sample wasn’t any useful as the same could have been done with just an Intent and startActivity()
, let’s see a better usage of pending intents.
int seconds = 3; // Create an intent that will be wrapped in PendingIntent Intent intent = new Intent(this, MyReceiver.class); // Create the pending intent and wrap our intent PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0); // Get the alarm manager service and schedule it to go off after 3s AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (seconds * 1000), pendingIntent); Toast.makeText(this, "Alarm set in " + seconds + " seconds", Toast.LENGTH_LONG).show();
We kick off with in a similar fashion, i.e., create and Intent and wrap it inside a PendingIntent. Next we get the alarm manager to which we pass the pendingIntent
and specify it to go off in 3 seconds. AlarmManager.RTC_WAKEUP
passed to AlarmManager.set()
is explained well here.
In your BroadcastReceiver’s onReceiver()
method you can add a simple piece of code like this:
@Override public void onReceive(Context context, Intent intent) { // Vibrate for 2 seconds Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); vibrator.vibrate(2000); }
As soon as the broadcast event is sent, the device will vibrate for 2 seconds.
So hopefully you understood how an Intent can be passed on to other native or third party apps via PendingIntent for execution. Hope that helps!