page.title=Preserving Navigation when Starting an Activity page.tags=notifications helpoutsWidget=true trainingnavtop=true @jd:body

This lesson teaches you to

  1. Set up a regular activity PendingIntent
  2. Set up a special activity PendingIntent

You should also read

Part of designing a notification is preserving the user's expected navigation experience. For a detailed discussion of this topic, see the Notifications API guide. There are two general situations:

Regular activity
You're starting an {@link android.app.Activity} that's part of the application's normal workflow.
Special activity
The user only sees this {@link android.app.Activity} if it's started from a notification. In a sense, the {@link android.app.Activity} extends the notification by providing information that would be hard to display in the notification itself.

Set Up a Regular Activity PendingIntent

To set up a {@link android.app.PendingIntent} that starts a direct entry {@link android.app.Activity}, follow these steps:

  1. Define your application's {@link android.app.Activity} hierarchy in the manifest. The final XML should look like this:

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".ResultActivity"
        android:parentActivityName=".MainActivity">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".MainActivity"/>
    </activity>
    
  2. Create a back stack based on the {@link android.content.Intent} that starts the {@link android.app.Activity}. For example:

    int id = 1;
    ...
    Intent resultIntent = new Intent(this, ResultActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    // Adds the back stack
    stackBuilder.addParentStack(ResultActivity.class);
    // Adds the Intent to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    // Gets a PendingIntent containing the entire back stack
    PendingIntent resultPendingIntent =
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    ...
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setContentIntent(resultPendingIntent);
    NotificationManager mNotificationManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(id, builder.build());
    

    Set Up a Special Activity PendingIntent

    A special {@link android.app.Activity} doesn't need a back stack, so you don't have to define its {@link android.app.Activity} hierarchy in the manifest, and you don't have to call {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options, and create the {@link android.app.PendingIntent} by calling {@link android.app.PendingIntent#getActivity getActivity()}:

    1. In your manifest, add the following attributes to the <activity> element for the {@link android.app.Activity}:
      android:name="activityclass"
      The activity's fully-qualified class name.
      android:taskAffinity=""
      Combined with the {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag that you set in code, this ensures that this {@link android.app.Activity} doesn't go into the application's default task. Any existing tasks that have the application's default affinity are not affected.
      android:excludeFromRecents="true"
      Excludes the new task from Recents, so that the user can't accidentally navigate back to it.

      This snippet shows the element:

      <activity
          android:name=".ResultActivity"
      ...
          android:launchMode="singleTask"
          android:taskAffinity=""
          android:excludeFromRecents="true">
      </activity>
      ...
      
    2. Build and issue the notification:
      1. Create an {@link android.content.Intent} that starts the {@link android.app.Activity}.
      2. Set the {@link android.app.Activity} to start in a new, empty task by calling {@link android.content.Intent#setFlags setFlags()} with the flags {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} and {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
      3. Set any other options you need for the {@link android.content.Intent}.
      4. Create a {@link android.app.PendingIntent} from the {@link android.content.Intent} by calling {@link android.app.PendingIntent#getActivity getActivity()}. You can then use this {@link android.app.PendingIntent} as the argument to {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.

      The following code snippet demonstrates the process:

      // Instantiate a Builder object.
      NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
      // Creates an Intent for the Activity
      Intent notifyIntent =
              new Intent(new ComponentName(this, ResultActivity.class));
      // Sets the Activity to start in a new, empty task
      notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 
              Intent.FLAG_ACTIVITY_CLEAR_TASK);
      // Creates the PendingIntent
      PendingIntent notifyIntent =
              PendingIntent.getActivity(
              this,
              0,
              notifyIntent,
              PendingIntent.FLAG_UPDATE_CURRENT
      );
      
      // Puts the PendingIntent into the notification builder
      builder.setContentIntent(notifyIntent);
      // Notifications are issued by sending them to the
      // NotificationManager system service.
      NotificationManager mNotificationManager =
          (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      // Builds an anonymous Notification object from the builder, and
      // passes it to the NotificationManager
      mNotificationManager.notify(id, builder.build());