1 page.title=Preserving Navigation when Starting an Activity 2 page.tags=notifications 3 helpoutsWidget=true 4 5 trainingnavtop=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 <activity 75 android:name=".MainActivity" 76 android:label="@string/app_name" > 77 <intent-filter> 78 <action android:name="android.intent.action.MAIN" /> 79 <category android:name="android.intent.category.LAUNCHER" /> 80 </intent-filter> 81 </activity> 82 <activity 83 android:name=".ResultActivity" 84 android:parentActivityName=".MainActivity"> 85 <meta-data 86 android:name="android.support.PARENT_ACTIVITY" 87 android:value=".MainActivity"/> 88 </activity> 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> 96 int id = 1; 97 ... 98 Intent resultIntent = new Intent(this, ResultActivity.class); 99 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 100 // Adds the back stack 101 stackBuilder.addParentStack(ResultActivity.class); 102 // Adds the Intent to the top of the stack 103 stackBuilder.addNextIntent(resultIntent); 104 // Gets a PendingIntent containing the entire back stack 105 PendingIntent resultPendingIntent = 106 stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 107 ... 108 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 109 builder.setContentIntent(resultPendingIntent); 110 NotificationManager mNotificationManager = 111 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 112 mNotificationManager.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"><activity></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 <activity 161 android:name=".ResultActivity" 162 ... 163 android:launchMode="singleTask" 164 android:taskAffinity="" 165 android:excludeFromRecents="true"> 166 </activity> 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. 200 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 201 // Creates an Intent for the Activity 202 Intent notifyIntent = 203 new Intent(new ComponentName(this, ResultActivity.class)); 204 // Sets the Activity to start in a new, empty task 205 notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 206 Intent.FLAG_ACTIVITY_CLEAR_TASK); 207 // Creates the PendingIntent 208 PendingIntent 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 217 builder.setContentIntent(notifyIntent); 218 // Notifications are issued by sending them to the 219 // NotificationManager system service. 220 NotificationManager mNotificationManager = 221 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 222 // Builds an anonymous Notification object from the builder, and 223 // passes it to the NotificationManager 224 mNotificationManager.notify(id, builder.build()); 225 </pre> 226 </li> 227 </ol> 228