1page.title=Preserving Navigation when Starting an Activity
2page.tags=notifications
3helpoutsWidget=true
4
5trainingnavtop=true
6
7@jd:body
8
9<div id="tb-wrapper">
10<div id="tb">
11
12<!-- table of contents -->
13<h2>This lesson teaches you to</h2>
14<ol>
15  <li><a href="#DirectEntry">Set up a regular activity PendingIntent</a></li>
16  <li><a href="#ExtendedNotification">Set up a special activity PendingIntent</a></li>
17</ol>
18
19<!-- other docs (NOT javadocs) -->
20<h2>You should also read</h2>
21
22<ul>
23    <li>
24        <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a> API Guide
25    </li>
26    <li>
27        <a href="{@docRoot}guide/components/intents-filters.html">
28        Intents and Intent Filters
29        </a>
30    </li>
31    <li>
32        <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design Guide
33    </li>
34</ul>
35
36
37</div>
38</div>
39<p>
40    Part of designing a notification is preserving the user's expected navigation experience.
41    For a detailed discussion of this topic, see the
42    <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#NotificationResponse">Notifications</a>
43    API guide.
44    There are two general situations:
45</p>
46<dl>
47    <dt>
48        Regular activity
49    </dt>
50    <dd>
51        You're starting an {@link android.app.Activity} that's part of the application's normal
52        workflow.
53    </dd>
54    <dt>
55        Special activity
56    </dt>
57    <dd>
58        The user only sees this {@link android.app.Activity} if it's started from a notification.
59        In a sense, the {@link android.app.Activity} extends the notification by providing
60        information that would be hard to display in the notification itself.
61    </dd>
62</dl>
63<!-- ------------------------------------------------------------------------------------------ -->
64<h2 id="DirectEntry">Set Up a Regular Activity PendingIntent</h2>
65<p>
66    To set up a {@link android.app.PendingIntent} that starts a direct entry
67    {@link android.app.Activity}, follow these steps:
68</p>
69<ol>
70    <li>
71        Define your application's {@link android.app.Activity} hierarchy in the manifest. The final XML should look like this:
72        </p>
73<pre>
74&lt;activity
75    android:name=".MainActivity"
76    android:label="&#64;string/app_name" &gt;
77    &lt;intent-filter&gt;
78        &lt;action android:name="android.intent.action.MAIN" /&gt;
79        &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
80    &lt;/intent-filter&gt;
81&lt;/activity&gt;
82&lt;activity
83    android:name=".ResultActivity"
84    android:parentActivityName=".MainActivity"&gt;
85    &lt;meta-data
86        android:name="android.support.PARENT_ACTIVITY"
87        android:value=".MainActivity"/&gt;
88&lt;/activity&gt;
89</pre>
90    </li>
91    <li>
92        Create a back stack based on the {@link android.content.Intent} that starts the
93        {@link android.app.Activity}. For example:
94</p>
95<pre>
96int id = 1;
97...
98Intent resultIntent = new Intent(this, ResultActivity.class);
99TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
100// Adds the back stack
101stackBuilder.addParentStack(ResultActivity.class);
102// Adds the Intent to the top of the stack
103stackBuilder.addNextIntent(resultIntent);
104// Gets a PendingIntent containing the entire back stack
105PendingIntent resultPendingIntent =
106        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
107...
108NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
109builder.setContentIntent(resultPendingIntent);
110NotificationManager mNotificationManager =
111    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
112mNotificationManager.notify(id, builder.build());
113</pre>
114<!-- ------------------------------------------------------------------------------------------ -->
115<h2 id="ExtendedNotification">Set Up a Special Activity PendingIntent</h2>
116
117<p>
118    A special {@link android.app.Activity} doesn't need a back stack, so you don't have to
119    define its {@link android.app.Activity} hierarchy in the manifest, and you don't have
120    to call
121    {@link android.support.v4.app.TaskStackBuilder#addParentStack  addParentStack()} to build a
122    back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options,
123    and create the {@link android.app.PendingIntent} by calling
124    {@link android.app.PendingIntent#getActivity getActivity()}:
125</p>
126<ol>
127    <li>
128        In your manifest, add the following attributes to the
129<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
130        element for the {@link android.app.Activity}:
131        <dl>
132            <dt>
133<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
134            </dt>
135            <dd>
136                The activity's fully-qualified class name.
137            </dd>
138            <dt>
139<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
140            </dt>
141            <dd>
142                Combined with the
143                {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag
144                that you set in code, this ensures that this {@link android.app.Activity} doesn't
145                go into the application's default task. Any existing tasks that have the
146                application's default affinity are not affected.
147            </dd>
148            <dt>
149<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
150            </dt>
151            <dd>
152                Excludes the new task from <i>Recents</i>, so that the user can't accidentally
153                navigate back to it.
154            </dd>
155        </dl>
156        <p>
157            This snippet shows the element:
158        </p>
159<pre>
160&lt;activity
161    android:name=".ResultActivity"
162...
163    android:launchMode="singleTask"
164    android:taskAffinity=""
165    android:excludeFromRecents="true"&gt;
166&lt;/activity&gt;
167...
168</pre>
169    </li>
170    <li>
171        Build and issue the notification:
172        <ol style="list-style-type: lower-alpha;">
173            <li>
174                Create an {@link android.content.Intent} that starts the
175                {@link android.app.Activity}.
176            </li>
177            <li>
178                Set the {@link android.app.Activity} to start in a new, empty task by calling
179                {@link android.content.Intent#setFlags setFlags()} with the flags
180                {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
181                and
182                {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
183            </li>
184            <li>
185                Set any other options you need for the {@link android.content.Intent}.
186            </li>
187            <li>
188                Create a {@link android.app.PendingIntent} from the {@link android.content.Intent}
189                by calling {@link android.app.PendingIntent#getActivity getActivity()}.
190                You can then use this {@link android.app.PendingIntent} as the argument to
191                {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
192                setContentIntent()}.
193            </li>
194        </ol>
195    <p>
196        The following code snippet demonstrates the process:
197    </p>
198<pre>
199// Instantiate a Builder object.
200NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
201// Creates an Intent for the Activity
202Intent notifyIntent =
203        new Intent(new ComponentName(this, ResultActivity.class));
204// Sets the Activity to start in a new, empty task
205notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
206        Intent.FLAG_ACTIVITY_CLEAR_TASK);
207// Creates the PendingIntent
208PendingIntent notifyIntent =
209        PendingIntent.getActivity(
210        this,
211        0,
212        notifyIntent,
213        PendingIntent.FLAG_UPDATE_CURRENT
214);
215
216// Puts the PendingIntent into the notification builder
217builder.setContentIntent(notifyIntent);
218// Notifications are issued by sending them to the
219// NotificationManager system service.
220NotificationManager mNotificationManager =
221    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
222// Builds an anonymous Notification object from the builder, and
223// passes it to the NotificationManager
224mNotificationManager.notify(id, builder.build());
225</pre>
226    </li>
227</ol>
228