Understanding Android Pending Intents

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:

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 with cancel(), 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 simply 0 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 to FLAG_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!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Author: Rishabh

Rishabh is a full stack web and mobile developer from India. Follow me on Twitter.

10 thoughts on “Understanding Android Pending Intents”

  1. In the second code snippet shouldnt the code in third code line be
    PendingIntent pendingIntent = PendingIntent.getReceiver(this, 1, intent, 0);

    instead of

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, 0);

  2. Sorry, If I am wrong, but you have mentioned “int seconds = 2;”, then how will the alarm manager service go off after 3 second? Should it be 2 second?

Leave a Reply

Your email address will not be published. Required fields are marked *

*