notifications.jd revision 3701cbef0f76144d66924b1724abb856e938e340
1page.title=Notifications 2@jd:body 3 4<div id="qv-wrapper"> 5<div id="qv"> 6<h2>In this document</h2> 7<ol> 8 <li><a href="#NotificationUI">Notification Display Elements</a> 9 <ol> 10 <li><a href="#NormalNotify">Normal view</a></li> 11 <li><a href="#BigNotify">Big view</a></li> 12 </ol> 13 </li> 14 <li><a href="#CreateNotification">Creating a Notification</a> 15 <ol> 16 <li><a href="#Required">Required notification contents</a></li> 17 <li><a href="#Optional">Optional notification contents and settings</a></li> 18 <li><a href="#Actions">Notification actions</a></li> 19 <li><a href="#Priority">Notification priority</a></li> 20 <li><a href="#SimpleNotification">Creating a simple notification</a></li> 21 <li><a href="#ApplyStyle">Applying a big view style to a notification</a></li> 22 <li><a href="#Compatibility">Handling compatibility</a></li> 23 </ol> 24 </li> 25 <li><a href="#Managing">Managing Notifications</a> 26 <ol> 27 <li><a href="#Updating">Updating notifications</a></li> 28 <li><a href="#Removing">Removing notifications</a></li> 29 </ol> 30 </li> 31 <li><a href="#NotificationResponse">Preserving Navigation when Starting an Activity</a> 32 <ol> 33 <li><a href="#DirectEntry">Setting up a regular activity PendingIntent</a></li> 34 <li><a href="#ExtendedNotification">Setting up a special activity PendingIntent</a></li> 35 </ol> 36 </li> 37 <li><a href="#Progress">Displaying Progress in a Notification</a> 38 <ol> 39 <li><a href="#FixedProgress">Displaying a fixed-duration progress indicator</a></li> 40 <li><a href="#ActivityIndicator">Displaying a continuing activity indicator</a></li> 41 </ol> 42 </li> 43 <li><a href="#CustomNotification">Custom Notification Layouts</a></li> 44</ol> 45 46 <h2>Key classes</h2> 47 <ol> 48 <li>{@link android.app.NotificationManager}</li> 49 <li>{@link android.support.v4.app.NotificationCompat}</li> 50 </ol> 51 <h2>Videos</h2> 52 <ol> 53 <li> 54 <a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s"> 55 Notifications in 4.1</a> 56 </li> 57 </ol> 58<h2>See also</h2> 59<ol> 60 <li> 61 <a href="{@docRoot}design/patterns/notifications.html">Android Design: Notifications</a> 62 </li> 63</ol> 64</div> 65</div> 66<p> 67 A notification is a message you can display to the user outside of your application's 68 normal UI. When you tell the system to issue a notification, it first appears as an icon in the 69 <strong>notification area</strong>. To see the details of the notification, the user opens the 70 <strong>notification drawer</strong>. Both the notification area and the notification drawer 71 are system-controlled areas that the user can view at any time. 72</p> 73<img 74 id="figure1" 75 src="{@docRoot}images/ui/notifications/iconic_notification.png" 76 height="120" alt="" /> 77<p class="img-caption"> 78 <strong>Figure 1.</strong> Notifications in the notification area. 79</p> 80<img id="figure2" src="{@docRoot}images/ui/notifications/normal_notification.png" 81 height="293" alt="" /> 82<p class="img-caption"> 83 <strong>Figure 2.</strong> Notifications in the notification drawer. 84</p> 85<div class="note design"> 86 <p> 87 <strong>Notification Design</strong> 88 </p> 89 <p> 90 Notifications, as an important part of the Android UI, have their own design guidelines. To 91 learn how to design notifications and their interactions, read the Android Design Guide 92 <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> topic. 93 </p> 94</div> 95<p class="note"> 96 <strong>Note:</strong> Except where noted, this guide refers to the 97 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class 98 in the version 4 <a href="{@docRoot}tools/support-library/index.html">Support Library</a>. 99 The class {@link android.app.Notification.Builder Notification.Builder} was added in Android 100 3.0. 101</p> 102<!-- ------------------------------------------------------------------------------------------ --> 103<!-- ------------------------------------------------------------------------------------------ --> 104<h2 id="NotificationUI">Notification Display Elements</h2> 105<p> 106 Notifications in the notification drawer can appear in one of two visual styles, depending on 107 the version and the state of the drawer: 108</p> 109<dl> 110 <dt> 111 Normal view 112 </dt> 113 <dd> 114 The standard view of the notifications in the notification drawer. 115 </dd> 116 <dt> 117 Big view 118 </dt> 119 <dd> 120 A large view that's visible when the notification is expanded. Big view is part of the 121 expanded notification feature available as of Android 4.1. 122 </dd> 123</dl> 124<p> 125 These styles are described in the following sections. 126</p> 127<!-- ------------------------------------------------------------------------------------------ --> 128<h3 id="NormalNotify">Normal view</h3> 129<p> 130 A notification in normal view appears in an area that's up to 64 dp tall. Even if you create a 131 notification with a big view style, it will appear in normal view until it's expanded. This 132 is an example of a normal view: 133</p> 134<img 135 src="{@docRoot}images/ui/notifications/normal_notification_callouts.png" 136 alt="" 137 height="153" 138 id="figure3" /> 139<p class="img-caption"> 140 <strong>Figure 3.</strong> Notification in normal view. 141</p> 142<p> 143 The callouts in the illustration refer to the following: 144</p> 145<ol> 146 <li>Content title</li> 147 <li>Large icon</li> 148 <li>Content text</li> 149 <li>Content info</li> 150 <li>Small icon</li> 151 <li> 152 Time that the notification was issued. You can set an explicit value with 153 {@link android.support.v4.app.NotificationCompat.Builder#setWhen setWhen()}; if you don't 154 it defaults to the time that the system received the notification. 155 </li> 156</ol> 157<!-- ------------------------------------------------------------------------------------------ --> 158<h3 id="BigNotify">Big view</h3> 159<p> 160 A notification's big view appears only when the notification is expanded, which happens when the 161 notification is at the top of the notification drawer, or when the user expands the 162 notification with a gesture. Expanded notifications are available starting with Android 4.1. 163</p> 164<p> 165 The following screenshot shows an inbox-style notification: 166</p> 167<img src="{@docRoot}images/ui/notifications/bigpicture_notification_callouts.png" 168 alt="" 169 height="240" 170 id="figure4" /> 171<p class="img-caption"> 172 <strong>Figure 4.</strong> Big view notification. 173</p> 174<p> 175 Notice that the big view shares most of its visual elements with the normal view. The 176 only difference is callout number 7, the details area. Each big view style sets this area in 177 a different way. The available styles are: 178</p> 179<dl> 180 <dt> 181 Big picture style 182 </dt> 183 <dd> 184 The details area contains a bitmap up to 256 dp tall in its detail section. 185 </dd> 186 <dt> 187 Big text style 188 </dt> 189 <dd> 190 Displays a large text block in the details section. 191 </dd> 192 <dt> 193 Inbox style 194 </dt> 195 <dd> 196 Displays lines of text in the details section. 197 </dd> 198</dl> 199<p> 200 All of the big view styles also have the following content options that aren't 201 available in normal view: 202</p> 203<dl> 204 <dt> 205 Big content title 206 </dt> 207 <dd> 208 Allows you to override the normal view's content title with a title that appears only in 209 the expanded view. 210 </dd> 211 <dt> 212 Summary text 213 </dt> 214 <dd> 215 Allows you to add a line of text below the details area. 216 </dd> 217</dl> 218<p> 219 Applying a big view style to a notification is described in the section 220 <a href="#ApplyStyle">Applying a big view style to a notification</a>. 221</p> 222<!-- ------------------------------------------------------------------------------------------ --> 223<!-- ------------------------------------------------------------------------------------------ --> 224<h2 id="CreateNotification">Creating a Notification</h2> 225<p> 226 You specify the UI information and actions for a notification in a 227 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object. 228 To create the notification itself, you call 229 {@link android.support.v4.app.NotificationCompat.Builder#build 230 NotificationCompat.Builder.build()}, which returns a {@link android.app.Notification} object 231 containing your specifications. 232 To issue the notification, you pass the {@link android.app.Notification} object to the system 233 by calling {@link android.app.NotificationManager#notify NotificationManager.notify()}. 234</p> 235<!-- ------------------------------------------------------------------------------------------ --> 236<h3 id="Required">Required notification contents</h3> 237<p> 238 A {@link android.app.Notification} object <em>must</em> contain the following: 239</p> 240<ul> 241 <li> 242 A small icon, set by 243 {@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()} 244 </li> 245 <li> 246 A title, set by 247 {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()} 248 </li> 249 <li> 250 Detail text, set by 251 {@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()} 252 </li> 253</ul> 254<h3 id="Optional">Optional notification contents and settings</h3> 255<p> 256 All other notification settings and contents are optional. To learn more about them, 257 see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}. 258</p> 259<!-- ------------------------------------------------------------------------------------------ --> 260<h3 id="Actions">Notification actions</h3> 261<p> 262 Although they're optional, you should add at least one action to your notification. 263 An action allows users to go directly from the notification to an 264 {@link android.app.Activity} in your application, where they can look at one or more events 265 or do further work. 266</p> 267<p> 268 A notification can provide multiple actions. You should always define the action that's 269 triggered when the user clicks the notification; usually this action opens an 270 {@link android.app.Activity} in your application. You can also add buttons to the notification 271 that perform additional actions such as snoozing an alarm or responding immediately to a text 272 message; this feature is available as of Android 4.1. If you use additional action buttons, you 273 must also make their functionality available in an {@link android.app.Activity} in your app; see 274 the section <a href="#Compatibility">Handling compatibility</a> for more details. 275</p> 276<p> 277 Inside a {@link android.app.Notification}, the action itself is defined by a 278 {@link android.app.PendingIntent} containing an {@link android.content.Intent} that starts 279 an {@link android.app.Activity} in your application. To associate the 280 {@link android.app.PendingIntent} with a gesture, call the appropriate method of 281 {@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start 282 {@link android.app.Activity} when the user clicks the notification text in 283 the notification drawer, you add the {@link android.app.PendingIntent} by calling 284 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}. 285</p> 286<p> 287 Starting an {@link android.app.Activity} when the user clicks the notification is the most 288 common action scenario. You can also start an {@link android.app.Activity} when the user 289 dismisses a notification. In Android 4.1 and later, you can start an 290 {@link android.app.Activity} from an action button. To learn more, read the reference guide for 291 {@link android.support.v4.app.NotificationCompat.Builder}. 292</p> 293<!-- ------------------------------------------------------------------------------------------ --> 294<h3 id="Priority">Notification priority</h3> 295<p> 296 If you wish, you can set the priority of a notification. The priority acts 297 as a hint to the device UI about how the notification should be displayed. 298 To set a notification's priority, call {@link 299 android.support.v4.app.NotificationCompat.Builder#setPriority(int) 300 NotificationCompat.Builder.setPriority()} and pass in one of the {@link 301 android.support.v4.app.NotificationCompat} priority constants. There are 302 five priority levels, ranging from {@link 303 android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) to {@link 304 android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); if not set, the 305 priority defaults to {@link 306 android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0). 307</p> 308<p> For information about setting an appropriate priority level, see "Correctly 309 set and manage notification priority" in the <a 310 href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design 311 guide. 312</p> 313<!-- ------------------------------------------------------------------------------------------ --> 314<h3 id="SimpleNotification">Creating a simple notification</h3> 315<p> 316 The following snippet illustrates a simple notification that specifies an activity to open when 317 the user clicks the notification. Notice that the code creates a 318 {@link android.support.v4.app.TaskStackBuilder} object and uses it to create the 319 {@link android.app.PendingIntent} for the action. This pattern is explained in more detail 320 in the section <a href="#NotificationResponse"> 321 Preserving Navigation when Starting an Activity</a>: 322</p> 323<pre> 324NotificationCompat.Builder mBuilder = 325 new NotificationCompat.Builder(this) 326 .setSmallIcon(R.drawable.notification_icon) 327 .setContentTitle("My notification") 328 .setContentText("Hello World!"); 329// Creates an explicit intent for an Activity in your app 330Intent resultIntent = new Intent(this, ResultActivity.class); 331 332// The stack builder object will contain an artificial back stack for the 333// started Activity. 334// This ensures that navigating backward from the Activity leads out of 335// your application to the Home screen. 336TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 337// Adds the back stack for the Intent (but not the Intent itself) 338stackBuilder.addParentStack(ResultActivity.class); 339// Adds the Intent that starts the Activity to the top of the stack 340stackBuilder.addNextIntent(resultIntent); 341PendingIntent resultPendingIntent = 342 stackBuilder.getPendingIntent( 343 0, 344 PendingIntent.FLAG_UPDATE_CURRENT 345 ); 346mBuilder.setContentIntent(resultPendingIntent); 347NotificationManager mNotificationManager = 348 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 349// mId allows you to update the notification later on. 350mNotificationManager.notify(mId, mBuilder.build()); 351</pre> 352<p>That's it. Your user has now been notified.</p> 353<!-- ------------------------------------------------------------------------------------------ --> 354<h3 id="ApplyStyle">Applying a big view style to a notification</h3> 355<p> 356 To have a notification appear in a big view when it's expanded, first create a 357 {@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options 358 you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle 359 Builder.setStyle()} with a big view style object as its argument. 360</p> 361<p> 362 Remember that expanded notifications are not available on platforms prior to Android 4.1. To 363 learn how to handle notifications for Android 4.1 and for earlier platforms, read the 364 section <a href="#Compatibility">Handling compatibility</a>. 365</p> 366<p> 367 For example, the following code snippet demonstrates how to alter the notification created 368 in the previous snippet to use the Inbox big view style: 369</p> 370<pre> 371NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) 372 .setSmallIcon(R.drawable.notification_icon) 373 .setContentTitle("Event tracker") 374 .setContentText("Events received") 375NotificationCompat.InboxStyle inboxStyle = 376 new NotificationCompat.InboxStyle(); 377String[] events = new String[6]; 378// Sets a title for the Inbox style big view 379inboxStyle.setBigContentTitle("Event tracker details:"); 380... 381// Moves events into the big view 382for (int i=0; i < events.length; i++) { 383 384 inboxStyle.addLine(events[i]); 385} 386// Moves the big view style object into the notification object. 387mBuilder.setStyle(inBoxStyle); 388... 389// Issue the notification here. 390</pre> 391<h3 id="Compatibility">Handling compatibility</h3> 392<p> 393 Not all notification features are available for a particular version, even though 394 the methods to set them are in the support library class 395 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}. 396 For example, action buttons, which depend on expanded notifications, only appear on Android 397 4.1 and higher, because expanded notifications themselves are only available on 398 Android 4.1 and higher. 399</p> 400<p> 401 To ensure the best compatibility, create notifications with 402 {@link android.support.v4.app.NotificationCompat NotificationCompat} and its subclasses, 403 particularly {@link android.support.v4.app.NotificationCompat.Builder 404 NotificationCompat.Builder}. In addition, follow this process when you implement a notification: 405</p> 406<ol> 407 <li> 408 Provide all of the notification's functionality to all users, regardless of the version 409 they're using. To do this, verify that all of the functionality is available from an 410 {@link android.app.Activity} in your app. You may want to add a new 411 {@link android.app.Activity} to do this. 412 <p> 413 For example, if you want to use 414 {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} to 415 provide a control that stops and starts media playback, first implement this 416 control in an {@link android.app.Activity} in your app. 417 </p> 418 </li> 419 <li> 420 Ensure that all users can get to the functionality in the {@link android.app.Activity}, 421 by having it start when users click the notification. To do this, 422 create a {@link android.app.PendingIntent} for the {@link android.app.Activity}. Call 423 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent 424 setContentIntent()} to add the {@link android.app.PendingIntent} to the notification. 425 </li> 426 <li> 427 Now add the expanded notification features you want to use to the notification. Remember 428 that any functionality you add also has to be available in the {@link android.app.Activity} 429 that starts when users click the notification. 430 </li> 431</ol> 432<!-- ------------------------------------------------------------------------------------------ --> 433<!-- ------------------------------------------------------------------------------------------ --> 434<h2 id="Managing">Managing Notifications</h2> 435<p> 436 When you need to issue a notification multiple times for the same type of event, you 437 should avoid making a completely new notification. Instead, you should consider updating a 438 previous notification, either by changing some of its values or by adding to it, or both. 439</p> 440<p> 441 For example, Gmail notifies the user that new emails have arrived by increasing its count of 442 unread messages and by adding a summary of each email to the notification. This is called 443 "stacking" the notification; it's described in more detail in the 444 <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design guide. 445</p> 446<p class="note"> 447 <strong>Note:</strong> This Gmail feature requires the "inbox" big view style, which is 448 part of the expanded notification feature available starting in Android 4.1. 449</p> 450<p> 451 The following section describes how to update notifications and also how to remove them. 452</p> 453<h3 id="Updating">Updating notifications</h3> 454<p> 455 To set up a notification so it can be updated, issue it with a notification ID by 456 calling {@link android.app.NotificationManager#notify(int, Notification) 457 NotificationManager.notify(ID, notification)}. To update this notification once you've issued 458 it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object, 459 build a {@link android.app.Notification} object from it, and issue the 460 {@link android.app.Notification} with the same ID you used previously. If 461 the previous notification is still visible, the system updates it from the contents of 462 the {@link android.app.Notification} object. If the previous notification has been dismissed, a 463 new notification is created instead. 464</p> 465<p> 466 The following snippet demonstrates a notification that is updated to reflect the 467 number of events that have occurred. It stacks the notification, showing a summary: 468</p> 469<pre> 470mNotificationManager = 471 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 472// Sets an ID for the notification, so it can be updated 473int notifyID = 1; 474mNotifyBuilder = new NotificationCompat.Builder(this) 475 .setContentTitle("New Message") 476 .setContentText("You've received new messages.") 477 .setSmallIcon(R.drawable.ic_notify_status) 478numMessages = 0; 479// Start of a loop that processes data and then notifies the user 480... 481 mNotifyBuilder.setContentText(currentText) 482 .setNumber(++numMessages); 483 // Because the ID remains unchanged, the existing notification is 484 // updated. 485 mNotificationManager.notify( 486 notifyID, 487 mNotifyBuilder.build()); 488... 489</pre> 490<p> 491 This produces a notification that looks like this: 492</p> 493<img 494 id="figure5" 495 src="{@docRoot}images/ui/notifications/updated_notification.png" 496 alt="" 497 height="118"/> 498<p class="img-caption"> 499 <strong>Figure 5.</strong> Updated notification displayed in the notification drawer. 500</p> 501<!-- ------------------------------------------------------------------------------------------ --> 502<h3 id="Removing">Removing notifications</h3> 503<p> 504 Notifications remain visible until one of the following happens: 505</p> 506<ul> 507 <li> 508 The user dismisses the notification either individually or by using "Clear All" (if 509 the notification can be cleared). 510 </li> 511 <li> 512 The user clicks the notification, and you called 513 {@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when 514 you created the notification. 515 </li> 516 <li> 517 You call {@link android.app.NotificationManager#cancel(int) cancel()} for a specific 518 notification ID. This method also deletes ongoing notifications. 519 </li> 520 <li> 521 You call {@link android.app.NotificationManager#cancelAll() cancelAll()}, which removes 522 all of the notifications you previously issued. 523 </li> 524</ul> 525<!-- ------------------------------------------------------------------------------------------ --> 526<!-- ------------------------------------------------------------------------------------------ --> 527<h2 id="NotificationResponse">Preserving Navigation when Starting an Activity</h2> 528<p> 529 When you start an {@link android.app.Activity} from a notification, you must preserve the 530 user's expected navigation experience. Clicking <i>Back</i> should take the user back through 531 the application's normal work flow to the Home screen, and clicking <i>Recents</i> should show 532 the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you 533 should start the {@link android.app.Activity} in a fresh task. How you set up the 534 {@link android.app.PendingIntent} to give you a fresh task depends on the nature of the 535 {@link android.app.Activity} you're starting. There are two general situations: 536</p> 537<dl> 538 <dt> 539 Regular activity 540 </dt> 541 <dd> 542 You're starting an {@link android.app.Activity} that's part of the application's normal 543 workflow. In this situation, set up the {@link android.app.PendingIntent} to 544 start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack 545 that reproduces the application's normal <i>Back</i> behavior. 546 <p> 547 Notifications from the Gmail app demonstrate this. When you click a notification for 548 a single email message, you see the message itself. Touching <b>Back</b> takes you 549 backwards through Gmail to the Home screen, just as if you had entered Gmail from the 550 Home screen rather than entering it from a notification. 551 </p> 552 <p> 553 This happens regardless of the application you were in when you touched the 554 notification. For example, if you're in Gmail composing a message, and you click a 555 notification for a single email, you go immediately to that email. Touching <i>Back</i> 556 takes you to the inbox and then the Home screen, rather than taking you to the 557 message you were composing. 558 </p> 559 </dd> 560 <dt> 561 Special activity 562 </dt> 563 <dd> 564 The user only sees this {@link android.app.Activity} if it's started from a notification. 565 In a sense, the {@link android.app.Activity} extends the notification by providing 566 information that would be hard to display in the notification itself. For this situation, 567 set up the {@link android.app.PendingIntent} to start in a fresh task. There's no need to 568 create a back stack, though, because the started {@link android.app.Activity} isn't part of 569 the application's activity flow. Clicking <i>Back</i> will still take the user to the 570 Home screen. 571 </dd> 572</dl> 573<!-- ------------------------------------------------------------------------------------------ --> 574<h3 id="DirectEntry">Setting up a regular activity PendingIntent</h3> 575<p> 576 To set up a {@link android.app.PendingIntent} that starts a direct entry 577 {@link android.app.Activity}, follow these steps: 578</p> 579<ol> 580 <li> 581 Define your application's {@link android.app.Activity} hierarchy in the manifest. 582 <ol style="list-style-type: lower-alpha;"> 583 <li> 584 Add support for Android 4.0.3 and earlier. To do this, specify the parent of the 585 {@link android.app.Activity} you're starting by adding a 586<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data></a></code> 587 element as the child of the 588<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>. 589 <p> 590 For this element, set 591<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>. 592 Set 593<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="<parent_activity_name>"</code> 594 where <code><parent_activity_name></code> is the value of 595<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code> 596 for the parent 597<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> 598 element. See the following XML for an example. 599 </p> 600 </li> 601 <li> 602 Also add support for Android 4.1 and later. To do this, add the 603<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code> 604 attribute to the 605<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> 606 element of the {@link android.app.Activity} you're starting. 607 </li> 608 </ol> 609 <p> 610 The final XML should look like this: 611 </p> 612<pre> 613<activity 614 android:name=".MainActivity" 615 android:label="@string/app_name" > 616 <intent-filter> 617 <action android:name="android.intent.action.MAIN" /> 618 <category android:name="android.intent.category.LAUNCHER" /> 619 </intent-filter> 620</activity> 621<activity 622 android:name=".ResultActivity" 623 android:parentActivityName=".MainActivity"> 624 <meta-data 625 android:name="android.support.PARENT_ACTIVITY" 626 android:value=".MainActivity"/> 627</activity> 628</pre> 629 </li> 630 <li> 631 Create a back stack based on the {@link android.content.Intent} that starts the 632 {@link android.app.Activity}: 633 <ol style="list-style-type: lower-alpha;"> 634 <li> 635 Create the {@link android.content.Intent} to start the {@link android.app.Activity}. 636 </li> 637 <li> 638 Create a stack builder by calling {@link android.app.TaskStackBuilder#create 639 TaskStackBuilder.create()}. 640 </li> 641 <li> 642 Add the back stack to the stack builder by calling 643 {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}. 644 For each {@link android.app.Activity} in the hierarchy you've defined in the 645 manifest, the back stack contains an {@link android.content.Intent} object that 646 starts the {@link android.app.Activity}. This method also adds flags that start the 647 stack in a fresh task. 648 <p class="note"> 649 <strong>Note:</strong> Although the argument to 650 {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} 651 is a reference to the started {@link android.app.Activity}, the method call 652 doesn't add the {@link android.content.Intent} that starts the 653 {@link android.app.Activity}. Instead, that's taken care of in the next step. 654 </p> 655 </li> 656 <li> 657 Add the {@link android.content.Intent} that starts the {@link android.app.Activity} 658 from the notification, by calling 659 {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}. 660 Pass the {@link android.content.Intent} you created in the first step as the 661 argument to 662 {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}. 663 </li> 664 <li> 665 If you need to, add arguments to {@link android.content.Intent} objects on the 666 stack by calling {@link android.support.v4.app.TaskStackBuilder#editIntentAt 667 TaskStackBuilder.editIntentAt()}. This is sometimes necessary to ensure that the 668 target {@link android.app.Activity} displays meaningful data when the user navigates 669 to it using <i>Back</i>. 670 </li> 671 <li> 672 Get a {@link android.app.PendingIntent} for this back stack by calling 673 {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}. 674 You can then use this {@link android.app.PendingIntent} as the argument to 675 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent 676 setContentIntent()}. 677 </li> 678 </ol> 679 </li> 680</ol> 681<p> 682 The following code snippet demonstrates the process: 683</p> 684<pre> 685... 686Intent resultIntent = new Intent(this, ResultActivity.class); 687TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 688// Adds the back stack 689stackBuilder.addParentStack(ResultActivity.class); 690// Adds the Intent to the top of the stack 691stackBuilder.addNextIntent(resultIntent); 692// Gets a PendingIntent containing the entire back stack 693PendingIntent resultPendingIntent = 694 stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 695... 696NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 697builder.setContentIntent(resultPendingIntent); 698NotificationManager mNotificationManager = 699 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 700mNotificationManager.notify(id, builder.build()); 701</pre> 702<!-- ------------------------------------------------------------------------------------------ --> 703<h3 id="ExtendedNotification">Setting up a special activity PendingIntent</h3> 704<p> 705 The following section describes how to set up a special activity 706 {@link android.app.PendingIntent}. 707</p> 708<p> 709 A special {@link android.app.Activity} doesn't need a back stack, so you don't have to 710 define its {@link android.app.Activity} hierarchy in the manifest, and you don't have 711 to call 712 {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a 713 back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options, 714 and create the {@link android.app.PendingIntent} by calling 715 {@link android.app.PendingIntent#getActivity getActivity()}: 716</p> 717<ol> 718 <li> 719 In your manifest, add the following attributes to the 720<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> 721 element for the {@link android.app.Activity} 722 <dl> 723 <dt> 724<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code> 725 </dt> 726 <dd> 727 The activity's fully-qualified class name. 728 </dd> 729 <dt> 730<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code> 731 </dt> 732 <dd> 733 Combined with the 734 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag 735 that you set in code, this ensures that this {@link android.app.Activity} doesn't 736 go into the application's default task. Any existing tasks that have the 737 application's default affinity are not affected. 738 </dd> 739 <dt> 740<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code> 741 </dt> 742 <dd> 743 Excludes the new task from <i>Recents</i>, so that the user can't accidentally 744 navigate back to it. 745 </dd> 746 </dl> 747 <p> 748 This snippet shows the element: 749 </p> 750<pre> 751<activity 752 android:name=".ResultActivity" 753... 754 android:launchMode="singleTask" 755 android:taskAffinity="" 756 android:excludeFromRecents="true"> 757</activity> 758... 759</pre> 760 </li> 761 <li> 762 Build and issue the notification: 763 <ol style="list-style-type: lower-alpha;"> 764 <li> 765 Create an {@link android.content.Intent} that starts the 766 {@link android.app.Activity}. 767 </li> 768 <li> 769 Set the {@link android.app.Activity} to start in a new, empty task by calling 770 {@link android.content.Intent#setFlags setFlags()} with the flags 771 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} 772 and 773 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}. 774 </li> 775 <li> 776 Set any other options you need for the {@link android.content.Intent}. 777 </li> 778 <li> 779 Create a {@link android.app.PendingIntent} from the {@link android.content.Intent} 780 by calling {@link android.app.PendingIntent#getActivity getActivity()}. 781 You can then use this {@link android.app.PendingIntent} as the argument to 782 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent 783 setContentIntent()}. 784 </li> 785 </ol> 786 <p> 787 The following code snippet demonstrates the process: 788 </p> 789<pre> 790// Instantiate a Builder object. 791NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 792// Creates an Intent for the Activity 793Intent notifyIntent = 794 new Intent(new ComponentName(this, ResultActivity.class)); 795// Sets the Activity to start in a new, empty task 796notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); 797// Creates the PendingIntent 798PendingIntent notifyIntent = 799 PendingIntent.getActivity( 800 this, 801 0, 802 notifyIntent 803 PendingIntent.FLAG_UPDATE_CURRENT 804); 805 806// Puts the PendingIntent into the notification builder 807builder.setContentIntent(notifyIntent); 808// Notifications are issued by sending them to the 809// NotificationManager system service. 810NotificationManager mNotificationManager = 811 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 812// Builds an anonymous Notification object from the builder, and 813// passes it to the NotificationManager 814mNotificationManager.notify(id, builder.build()); 815</pre> 816 </li> 817</ol> 818<!-- ------------------------------------------------------------------------------------------ --> 819<!-- ------------------------------------------------------------------------------------------ --> 820<h2 id="Progress">Displaying Progress in a Notification</h2> 821<p> 822 Notifications can include an animated progress indicator that shows users the status 823 of an ongoing operation. If you can estimate how long the operation takes and how much of it 824 is complete at any time, use the "determinate" form of the indicator 825 (a progress bar). If you can't estimate the length of the operation, use the 826 "indeterminate" form of the indicator (an activity indicator). 827</p> 828<p> 829 Progress indicators are displayed with the platform's implementation of the 830 {@link android.widget.ProgressBar} class. 831</p> 832<p> 833 To use a progress indicator on platforms starting with Android 4.0, call 834 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. For 835 previous versions, you must create your own custom notification layout that 836 includes a {@link android.widget.ProgressBar} view. 837</p> 838<p> 839 The following sections describe how to display progress in a notification using 840 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. 841</p> 842<!-- ------------------------------------------------------------------------------------------ --> 843<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3> 844<p> 845 To display a determinate progress bar, add the bar to your notification by calling 846 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress() 847 setProgress(max, progress, false)} and then issue the notification. As your operation proceeds, 848 increment <code>progress</code>, and update the notification. At the end of the operation, 849 <code>progress</code> should equal <code>max</code>. A common way to call 850 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()} 851 is to set <code>max</code> to 100 and then increment <code>progress</code> as a 852 "percent complete" value for the operation. 853</p> 854<p> 855 You can either leave the progress bar showing when the operation is done, or remove it. In 856 either case, remember to update the notification text to show that the operation is complete. 857 To remove the progress bar, call 858 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress() 859 setProgress(0, 0, false)}. For example: 860</p> 861<pre> 862... 863mNotifyManager = 864 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 865mBuilder = new NotificationCompat.Builder(this); 866mBuilder.setContentTitle("Picture Download") 867 .setContentText("Download in progress") 868 .setSmallIcon(R.drawable.ic_notification); 869// Start a lengthy operation in a background thread 870new Thread( 871 new Runnable() { 872 @Override 873 public void run() { 874 int incr; 875 // Do the "lengthy" operation 20 times 876 for (incr = 0; incr <= 100; incr+=5) { 877 // Sets the progress indicator to a max value, the 878 // current completion percentage, and "determinate" 879 // state 880 mBuilder.setProgress(100, incr, false); 881 // Displays the progress bar for the first time. 882 mNotifyManager.notify(0, mBuilder.build()); 883 // Sleeps the thread, simulating an operation 884 // that takes time 885 try { 886 // Sleep for 5 seconds 887 Thread.sleep(5*1000); 888 } catch (InterruptedException e) { 889 Log.d(TAG, "sleep failure"); 890 } 891 } 892 // When the loop is finished, updates the notification 893 mBuilder.setContentText("Download complete") 894 // Removes the progress bar 895 .setProgress(0,0,false); 896 mNotifyManager.notify(ID, mBuilder.build()); 897 } 898 } 899// Starts the thread by calling the run() method in its Runnable 900).start(); 901</pre> 902<p> 903 The resulting notifications are shown in figure 6. On the left side is a snapshot of the 904 notification during the operation; on the right side is a snapshot of it after the operation 905 has finished. 906</p> 907<img 908 id="figure6" 909 src="{@docRoot}images/ui/notifications/progress_bar_summary.png" 910 height="84" 911 alt="" /> 912<p class="img-caption"> 913<strong>Figure 6.</strong> The progress bar during and after the operation.</p> 914<!-- ------------------------------------------------------------------------------------------ --> 915<h3 id="ActivityIndicator">Displaying a continuing activity indicator</h3> 916<p> 917 To display an indeterminate activity indicator, add it to your notification with 918 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)} 919 (the first two arguments are ignored), and issue the notification. The result is an indicator 920 that has the same style as a progress bar, except that its animation is ongoing. 921</p> 922<p> 923 Issue the notification at the beginning of the operation. The animation will run until you 924 modify your notification. When the operation is done, call 925 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress() 926 setProgress(0, 0, false)} and then update the notification to remove the activity indicator. 927 Always do this; otherwise, the animation will run even when the operation is complete. Also 928 remember to change the notification text to indicate that the operation is complete. 929</p> 930<p> 931 To see how activity indicators work, refer to the preceding snippet. Locate the following lines: 932</p> 933<pre> 934// Sets the progress indicator to a max value, the current completion 935// percentage, and "determinate" state 936mBuilder.setProgress(100, incr, false); 937// Issues the notification 938mNotifyManager.notify(0, mBuilder.build()); 939</pre> 940<p> 941 Replace the lines you've found with the following lines: 942</p> 943<pre> 944 // Sets an activity indicator for an operation of indeterminate length 945mBuilder.setProgress(0, 0, true); 946// Issues the notification 947mNotifyManager.notify(0, mBuilder.build()); 948</pre> 949<p> 950 The resulting indicator is shown in figure 7: 951</p> 952<img 953 id="figure7" 954 src="{@docRoot}images/ui/notifications/activity_indicator.png" 955 height="99" 956 alt="" /> 957<p class="img-caption"><strong>Figure 7.</strong> An ongoing activity indicator.</p> 958 959<!-- ------------------------------------------------------------------------------------------ --> 960<!-- ------------------------------------------------------------------------------------------ --> 961<!-- ------------------------------------------------------------------------------------------ --> 962 963<!-- ------------------------------------------------------------------------------------------ --> 964<h2 id="CustomNotification">Custom Notification Layouts</h2> 965<p> 966 The notifications framework allows you to define a custom notification layout, which 967 defines the notification's appearance in a {@link android.widget.RemoteViews} object. 968 Custom layout notifications are similar to normal notifications, but they're based on a 969 {@link android.widget.RemoteViews} defined in a XML layout file. 970</p> 971<p> 972 The height available for a custom notification layout depends on the notification view. Normal 973 view layouts are limited to 64 dp, and expanded view layouts are limited to 256 dp. 974</p> 975<p> 976 To define a custom notification layout, start by instantiating a 977 {@link android.widget.RemoteViews} object that inflates an XML layout file. Then, 978 instead of calling methods such as 979 {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}, 980 call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set 981 content details in the custom notification, use the methods in 982 {@link android.widget.RemoteViews} to set the values of the view's children: 983</p> 984<ol> 985 <li> 986 Create an XML layout for the notification in a separate file. You can use any file name 987 you wish, but you must use the extension <code>.xml</code> 988 </li> 989 <li> 990 In your app, use {@link android.widget.RemoteViews} methods to define your notification's 991 icons and text. Put this {@link android.widget.RemoteViews} object into your 992 {@link android.support.v4.app.NotificationCompat.Builder} by calling 993 {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Avoid 994 setting a background {@link android.graphics.drawable.Drawable} on your 995 {@link android.widget.RemoteViews} object, because your text color may become unreadable. 996 </li> 997</ol> 998<p> 999 The {@link android.widget.RemoteViews} class also includes methods that you can use to easily 1000 add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar} 1001 to your notification's layout. For more information about creating custom layouts for your 1002 notification, refer to the {@link android.widget.RemoteViews} reference documentation. 1003</p> 1004<p class="caution"> 1005 <strong>Caution:</strong> When you use a custom notification layout, take special care to 1006 ensure that your custom layout works with different device orientations and resolutions. While 1007 this advice applies to all View layouts, it's especially important for notifications because 1008 the space in the notification drawer is very restricted. Don't make your custom layout too 1009 complex, and be sure to test it in various configurations. 1010</p> 1011<!-- ------------------------------------------------------------------------------------------ --> 1012<h4>Using style resources for custom notification text</h4> 1013<p> 1014 Always use style resources for the text of a custom notification. The background color of the 1015 notification can vary across different devices and versions, and using style resources 1016 helps you account for this. Starting in Android 2.3, the system defined a style for the 1017 standard notification layout text. If you use the same style in applications that target Android 1018 2.3 or higher, you'll ensure that your text is visible against the display background. 1019</p> 1020