| page.title=Preserving Navigation when Starting an Activity |
| page.tags=notifications |
| helpoutsWidget=true |
| |
| trainingnavtop=true |
| |
| @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> |
| 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()); |
| </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> |