page.title=Preserving Navigation when Starting an Activity parent.title=Notifying the User parent.link=index.html trainingnavtop=true next.title=Updating Notifications next.link=managing.html @jd:body <div id="tb-wrapper"> <div id="tb"> <!-- table of contents --> <h2>This lesson teaches you to</h2> <ol> <li><a href="#DirectEntry">Set up a regular activity PendingIntent</a></li> <li><a href="#ExtendedNotification">Set up a special activity PendingIntent</a></li> </ol> <!-- other docs (NOT javadocs) --> <h2>You should also read</h2> <ul> <li> <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a> API Guide </li> <li> <a href="{@docRoot}guide/components/intents-filters.html"> Intents and Intent Filters </a> </li> <li> <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design Guide </li> </ul> </div> </div> <p> Part of designing a notification is preserving the user's expected navigation experience. For a detailed discussion of this topic, see the <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#NotificationResponse">Notifications</a> API guide. There are two general situations: </p> <dl> <dt> Regular activity </dt> <dd> You're starting an {@link android.app.Activity} that's part of the application's normal workflow. </dd> <dt> Special activity </dt> <dd> 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. </dd> </dl> <!-- ------------------------------------------------------------------------------------------ --> <h2 id="DirectEntry">Set Up a Regular Activity PendingIntent</h2> <p> To set up a {@link android.app.PendingIntent} that starts a direct entry {@link android.app.Activity}, follow these steps: </p> <ol> <li> Define your application's {@link android.app.Activity} hierarchy in the manifest. The final XML should look like this: </p> <pre> <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> </pre> </li> <li> Create a back stack based on the {@link android.content.Intent} that starts the {@link android.app.Activity}. For example: </p> <pre> ... 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()); </pre> <!-- ------------------------------------------------------------------------------------------ --> <h2 id="ExtendedNotification">Set Up a Special Activity PendingIntent</h2> <p> 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()}: </p> <ol> <li> In your manifest, add the following attributes to the <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> element for the {@link android.app.Activity}: <dl> <dt> <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code> </dt> <dd> The activity's fully-qualified class name. </dd> <dt> <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code> </dt> <dd> 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. </dd> <dt> <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code> </dt> <dd> Excludes the new task from <i>Recents</i>, so that the user can't accidentally navigate back to it. </dd> </dl> <p> This snippet shows the element: </p> <pre> <activity android:name=".ResultActivity" ... android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity> ... </pre> </li> <li> Build and issue the notification: <ol style="list-style-type: lower-alpha;"> <li> Create an {@link android.content.Intent} that starts the {@link android.app.Activity}. </li> <li> 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}. </li> <li> Set any other options you need for the {@link android.content.Intent}. </li> <li> 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()}. </li> </ol> <p> The following code snippet demonstrates the process: </p> <pre> // 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()); </pre> </li> </ol>