1 page.title=Notifications 2 page.image=images/android-7.0/notifications-card.png 3 page.tags="notifications", "alerts" 4 @jd:body 5 6 <div id="qv-wrapper"> 7 <div id="qv"> 8 <h2>In this document</h2> 9 <ol> 10 <li><a href="#Design">Design Considerations</a></li> 11 <li><a href="#CreateNotification">Creating a Notification</a> 12 <ol> 13 <li><a href="#Required">Required notification contents</a></li> 14 <li><a href="#Optional">Optional notification contents and settings</a></li> 15 <li><a href="#Actions">Notification actions</a></li> 16 <li><a href="#Priority">Notification priority</a></li> 17 <li><a href="#SimpleNotification">Creating a simple notification</a></li> 18 <li><a href="#ApplyStyle">Applying an expanded layout to a notification</a></li> 19 <li><a href="#Compatibility">Handling compatibility</a></li> 20 </ol> 21 </li> 22 <li><a href="#Managing">Managing Notifications</a> 23 <ol> 24 <li><a href="#Updating">Updating notifications</a></li> 25 <li><a href="#Removing">Removing notifications</a></li> 26 <li><a href="#direct">Replying to notifications</a></li> 27 <li><a href="#bundle">Bundling notifications</a></li> 28 </ol> 29 </li> 30 <li><a href="#NotificationResponse">Preserving Navigation when Starting an Activity</a> 31 <ol> 32 <li><a href="#DirectEntry">Setting up a regular activity PendingIntent</a></li> 33 <li><a href="#ExtendedNotification">Setting up a special activity PendingIntent</a></li> 34 </ol> 35 </li> 36 <li><a href="#Progress">Displaying Progress in a Notification</a> 37 <ol> 38 <li><a href="#FixedProgress">Displaying a fixed-duration progress indicator</a></li> 39 <li><a href="#ActivityIndicator">Displaying a continuing activity indicator</a></li> 40 </ol> 41 </li> 42 <li><a href="#metadata">Notification Metadata</a></li> 43 <li><a href="#Heads-up">Heads-up Notifications</a></li> 44 <li><a href="#lockscreenNotification">Lock Screen Notifications</a> 45 <ol> 46 <li><a href="#visibility">Setting Visibility</a></li> 47 <li><a href="#controllingMedia">Controlling Media Playback on the Lock Screen</a></li> 48 </ol> 49 </li> 50 <li><a href="#CustomNotification">Customizing Notifications</a> 51 <ol> 52 <li><a href="#custom">Custom Views</a></li> 53 <li><a href="#style">Messaging Style</a></li> 54 </ol> 55 </li> 56 </ol> 57 58 <h2>Key classes</h2> 59 <ol> 60 <li>{@link android.app.NotificationManager}</li> 61 <li>{@link android.support.v4.app.NotificationCompat}</li> 62 </ol> 63 <h2>Videos</h2> 64 <ol> 65 <li> 66 <a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s"> 67 Notifications in 4.1</a> 68 </li> 69 </ol> 70 <h2>See also</h2> 71 <ol> 72 <li> 73 <a href="https://material.google.com/patterns/notifications.html">Material Design: Notifications</a> 74 </li> 75 </ol> 76 </div> 77 </div> 78 <p> 79 A notification is a message you can display to the user outside of your application's 80 normal UI. When you tell the system to issue a notification, it first appears as an icon in the 81 <strong>notification area</strong>. To see the details of the notification, the user opens the 82 <strong>notification drawer</strong>. Both the notification area and the notification drawer 83 are system-controlled areas that the user can view at any time. 84 </p> 85 <img 86 id="figure1" 87 src="{@docRoot}images/ui/notifications/notification_area.png" 88 height="" alt="" /> 89 <p class="img-caption"> 90 <strong>Figure 1.</strong> Notifications in the notification area. 91 </p> 92 <img id="figure2" src="{@docRoot}images/ui/notifications/notification_drawer.png" 93 width="280px" alt="" /> 94 <p class="img-caption"> 95 <strong>Figure 2.</strong> Notifications in the notification drawer. 96 </p> 97 98 <p class="note"><strong>Note:</strong> Except where noted, this guide refers to the 99 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class 100 in the version 4 <a href="{@docRoot}tools/support-library/index.html">Support Library</a>. 101 The class {@link android.app.Notification.Builder Notification.Builder} was added in Android 102 3.0 (API level 11).</p> 103 104 <h2 id="Design">Design Considerations</h2> 105 106 <p>Notifications, as an important part of the Android user interface, have their own design guidelines. 107 The material design changes introduced in Android 5.0 (API level 21) are of particular 108 importance, and you should review the <a href="{@docRoot}training/material/index.html">Material 109 Design</a> training for more information. To learn how to design notifications and their interactions, 110 read the <a href="https://material.google.com/patterns/notifications.html">Notifications</a> design guide.</p> 111 112 <h2 id="CreateNotification">Creating a Notification</h2> 113 114 <p>You specify the UI information and actions for a notification in a 115 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object. 116 To create the notification itself, you call 117 {@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()}, 118 which returns a {@link android.app.Notification} object containing your specifications. To issue the 119 notification, you pass the {@link android.app.Notification} object to the system by calling 120 {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.</p> 121 122 <h3 id="Required">Required notification contents</h3> 123 <p> 124 A {@link android.app.Notification} object <em>must</em> contain the following: 125 </p> 126 <ul> 127 <li> 128 A small icon, set by 129 {@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()} 130 </li> 131 <li> 132 A title, set by 133 {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()} 134 </li> 135 <li> 136 Detail text, set by 137 {@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()} 138 </li> 139 </ul> 140 <h3 id="Optional">Optional notification contents and settings</h3> 141 <p> 142 All other notification settings and contents are optional. To learn more about them, 143 see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}. 144 </p> 145 <!-- ------------------------------------------------------------------------------------------ --> 146 <h3 id="Actions">Notification actions</h3> 147 <p> 148 Although they're optional, you should add at least one action to your notification. 149 An action allows users to go directly from the notification to an 150 {@link android.app.Activity} in your application, where they can look at one or more events 151 or do further work. 152 </p> 153 <p> 154 A notification can provide multiple actions. You should always define the action that's 155 triggered when the user clicks the notification; usually this action opens an 156 {@link android.app.Activity} in your application. You can also add buttons to the notification 157 that perform additional actions such as snoozing an alarm or responding immediately to a text 158 message; this feature is available as of Android 4.1. If you use additional action buttons, you 159 must also make their functionality available in an {@link android.app.Activity} in your app; see 160 the section <a href="#Compatibility">Handling compatibility</a> for more details. 161 </p> 162 <p> 163 Inside a {@link android.app.Notification}, the action itself is defined by a 164 {@link android.app.PendingIntent} containing an 165 {@link android.content.Intent} that starts 166 an {@link android.app.Activity} in your application. To associate the 167 {@link android.app.PendingIntent} with a gesture, call the appropriate method of 168 {@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start 169 {@link android.app.Activity} when the user clicks the notification text in 170 the notification drawer, you add the {@link android.app.PendingIntent} by calling 171 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}. 172 </p> 173 <p> 174 Starting an {@link android.app.Activity} when the user clicks the notification is the most 175 common action scenario. You can also start an {@link android.app.Activity} when the user 176 dismisses a notification. In Android 4.1 and later, you can start an 177 {@link android.app.Activity} from an action button. To learn more, read the reference guide for 178 {@link android.support.v4.app.NotificationCompat.Builder}. 179 </p> 180 <!-- ------------------------------------------------------------------------------------------ --> 181 <h3 id="Priority">Notification priority</h3> 182 <p> 183 If you wish, you can set the priority of a notification. The priority acts 184 as a hint to the device UI about how the notification should be displayed. 185 To set a notification's priority, call {@link 186 android.support.v4.app.NotificationCompat.Builder#setPriority(int) 187 NotificationCompat.Builder.setPriority()} and pass in one of the {@link 188 android.support.v4.app.NotificationCompat} priority constants. There are 189 five priority levels, ranging from {@link 190 android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) to {@link 191 android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); if not set, the 192 priority defaults to {@link 193 android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0). 194 </p> 195 <p> For information about setting an appropriate priority level, see "Correctly 196 set and manage notification priority" in the <a 197 href="https://material.google.com/patterns/notifications.html">Notifications</a> Design 198 guide. 199 </p> 200 <!-- ------------------------------------------------------------------------------------------ --> 201 <h3 id="SimpleNotification">Creating a simple notification</h3> 202 <p> 203 The following snippet illustrates a simple notification that specifies an activity to open when 204 the user clicks the notification. Notice that the code creates a 205 {@link android.support.v4.app.TaskStackBuilder} object and uses it to create the 206 {@link android.app.PendingIntent} for the action. This pattern is explained in more detail 207 in the section <a href="#NotificationResponse"> 208 Preserving Navigation when Starting an Activity</a>: 209 </p> 210 <pre> 211 NotificationCompat.Builder mBuilder = 212 new NotificationCompat.Builder(this) 213 .setSmallIcon(R.drawable.notification_icon) 214 .setContentTitle("My notification") 215 .setContentText("Hello World!"); 216 // Creates an explicit intent for an Activity in your app 217 Intent resultIntent = new Intent(this, ResultActivity.class); 218 219 // The stack builder object will contain an artificial back stack for the 220 // started Activity. 221 // This ensures that navigating backward from the Activity leads out of 222 // your application to the Home screen. 223 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 224 // Adds the back stack for the Intent (but not the Intent itself) 225 stackBuilder.addParentStack(ResultActivity.class); 226 // Adds the Intent that starts the Activity to the top of the stack 227 stackBuilder.addNextIntent(resultIntent); 228 PendingIntent resultPendingIntent = 229 stackBuilder.getPendingIntent( 230 0, 231 PendingIntent.FLAG_UPDATE_CURRENT 232 ); 233 mBuilder.setContentIntent(resultPendingIntent); 234 NotificationManager mNotificationManager = 235 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 236 // mId allows you to update the notification later on. 237 mNotificationManager.notify(mId, mBuilder.build()); 238 </pre> 239 <p>That's it. Your user has now been notified.</p> 240 <!-- ------------------------------------------------------------------------------------------ --> 241 <h3 id="ApplyStyle">Applying an expanded layout to a notification</h3> 242 <p> 243 To have a notification appear in an expanded view, first create a 244 {@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options 245 you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle 246 Builder.setStyle()} with an expanded layout object as its argument. 247 </p> 248 <p> 249 Remember that expanded notifications are not available on platforms prior to Android 4.1. To 250 learn how to handle notifications for Android 4.1 and for earlier platforms, read the 251 section <a href="#Compatibility">Handling compatibility</a>. 252 </p> 253 <p> 254 For example, the following code snippet demonstrates how to alter the notification created 255 in the previous snippet to use the expanded layout: 256 </p> 257 <pre> 258 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) 259 .setSmallIcon(R.drawable.notification_icon) 260 .setContentTitle("Event tracker") 261 .setContentText("Events received") 262 NotificationCompat.InboxStyle inboxStyle = 263 new NotificationCompat.InboxStyle(); 264 String[] events = new String[6]; 265 // Sets a title for the Inbox in expanded layout 266 inboxStyle.setBigContentTitle("Event tracker details:"); 267 ... 268 // Moves events into the expanded layout 269 for (int i=0; i < events.length; i++) { 270 271 inboxStyle.addLine(events[i]); 272 } 273 // Moves the expanded layout object into the notification object. 274 mBuilder.setStyle(inBoxStyle); 275 ... 276 // Issue the notification here. 277 </pre> 278 279 <h3 id="Compatibility">Handling compatibility</h3> 280 281 <p> 282 Not all notification features are available for a particular version, even though 283 the methods to set them are in the support library class 284 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}. 285 For example, action buttons, which depend on expanded notifications, only appear on Android 286 4.1 and higher, because expanded notifications themselves are only available on 287 Android 4.1 and higher. 288 </p> 289 <p> 290 To ensure the best compatibility, create notifications with 291 {@link android.support.v4.app.NotificationCompat NotificationCompat} and its subclasses, 292 particularly {@link android.support.v4.app.NotificationCompat.Builder 293 NotificationCompat.Builder}. In addition, follow this process when you implement a notification: 294 </p> 295 <ol> 296 <li> 297 Provide all of the notification's functionality to all users, regardless of the version 298 they're using. To do this, verify that all of the functionality is available from an 299 {@link android.app.Activity} in your app. You may want to add a new 300 {@link android.app.Activity} to do this. 301 <p> 302 For example, if you want to use 303 {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} to 304 provide a control that stops and starts media playback, first implement this 305 control in an {@link android.app.Activity} in your app. 306 </p> 307 </li> 308 <li> 309 Ensure that all users can get to the functionality in the {@link android.app.Activity}, 310 by having it start when users click the notification. To do this, 311 create a {@link android.app.PendingIntent} 312 for the {@link android.app.Activity}. Call 313 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent 314 setContentIntent()} to add the {@link android.app.PendingIntent} to the notification. 315 </li> 316 <li> 317 Now add the expanded notification features you want to use to the notification. Remember 318 that any functionality you add also has to be available in the {@link android.app.Activity} 319 that starts when users click the notification. 320 </li> 321 </ol> 322 323 324 <!-- ------------------------------------------------------------------------------------------ --> 325 <!-- ------------------------------------------------------------------------------------------ --> 326 <h2 id="Managing">Managing Notifications</h2> 327 <p> 328 When you need to issue a notification multiple times for the same type of event, you 329 should avoid making a completely new notification. Instead, you should consider updating a 330 previous notification, either by changing some of its values or by adding to it, or both. 331 </p> 332 <p> 333 For example, Gmail notifies the user that new emails have arrived by increasing its count of 334 unread messages and by adding a summary of each email to the notification. This is called 335 "stacking" the notification; it's described in more detail in the 336 <a href="https://material.google.com/patterns/notifications.html">Notifications</a> Design guide. 337 </p> 338 <p class="note"> 339 <strong>Note:</strong> This Gmail feature requires the "inbox" expanded layout, which is part 340 of the expanded notification feature. 341 </p> 342 <p> 343 The following section describes how to update notifications and also how to remove them. 344 </p> 345 <h3 id="Updating">Updating notifications</h3> 346 <p> 347 To set up a notification so it can be updated, issue it with a notification ID by 348 calling {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}. 349 To update this notification once you've issued 350 it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object, 351 build a {@link android.app.Notification} object from it, and issue the 352 {@link android.app.Notification} with the same ID you used previously. If 353 the previous notification is still visible, the system updates it from the contents of 354 the {@link android.app.Notification} object. If the previous notification has been dismissed, a 355 new notification is created instead. 356 </p> 357 <p> 358 The following snippet demonstrates a notification that is updated to reflect the 359 number of events that have occurred. It stacks the notification, showing a summary: 360 </p> 361 <pre> 362 mNotificationManager = 363 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 364 // Sets an ID for the notification, so it can be updated 365 int notifyID = 1; 366 mNotifyBuilder = new NotificationCompat.Builder(this) 367 .setContentTitle("New Message") 368 .setContentText("You've received new messages.") 369 .setSmallIcon(R.drawable.ic_notify_status) 370 numMessages = 0; 371 // Start of a loop that processes data and then notifies the user 372 ... 373 mNotifyBuilder.setContentText(currentText) 374 .setNumber(++numMessages); 375 // Because the ID remains unchanged, the existing notification is 376 // updated. 377 mNotificationManager.notify( 378 notifyID, 379 mNotifyBuilder.build()); 380 ... 381 </pre> 382 383 <!-- ------------------------------------------------------------------------------------------ --> 384 <h3 id="Removing">Removing notifications</h3> 385 <p> 386 Notifications remain visible until one of the following happens: 387 </p> 388 <ul> 389 <li> 390 The user dismisses the notification either individually or by using "Clear All" (if 391 the notification can be cleared). 392 </li> 393 <li> 394 The user clicks the notification, and you called 395 {@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when 396 you created the notification. 397 </li> 398 <li> 399 You call {@link android.app.NotificationManager#cancel(int) cancel()} for a specific 400 notification ID. This method also deletes ongoing notifications. 401 </li> 402 <li> 403 You call {@link android.app.NotificationManager#cancelAll() cancelAll()}, which removes 404 all of the notifications you previously issued. 405 </li> 406 </ul> 407 408 <!--------------------------------------------------------------- --> 409 <h2 id="direct">Replying to notifications</h2> 410 411 <p> 412 Starting in Android 7.0 (API level 24), 413 users can respond directly to text messages or update task lists 414 from within the notification 415 dialog. On a handheld, the inline reply action appears as an additional 416 button 417 displayed in the notification. When a user replies via keyboard, the system 418 attaches the text response to the intent 419 you had specified for the notification action and sends the intent to your 420 handheld app. 421 </p> 422 423 <img id="fig-reply-button" src="{@docRoot}images/android-7.0/inline-reply.png" 424 srcset="{@docRoot}images/android-7.0/inline-reply.png 1x, 425 {@docRoot}images/android-7.0/inline-reply_2x.png 2x" 426 width="400"> 427 <p class="img-caption"> 428 <strong>Figure 1.</strong> The <strong>Reply</strong> action button. 429 </p> 430 431 <h3>Adding inline reply actions</h3> 432 433 <p>To create a notification action that supports direct reply: 434 </p> 435 436 <ol> 437 <li>Create an instance of {@link android.support.v4.app.RemoteInput.Builder} 438 that you can add to your notification 439 action. This class's constructor accepts a string that the system uses as the key 440 for the text input. Later, your handheld app uses that key to retrieve the text 441 of the input. 442 443 <pre> 444 // Key for the string that's delivered in the action's intent. 445 private static final String KEY_TEXT_REPLY = "key_text_reply"; 446 String replyLabel = getResources().getString(R.string.reply_label); 447 RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY) 448 .setLabel(replyLabel) 449 .build(); 450 </pre> 451 </li> 452 <li>Attach the {@link android.support.v4.app.RemoteInput} 453 object to an action using <code>addRemoteInput()</code>. 454 455 <pre> 456 // Create the reply action and add the remote input. 457 Notification.Action action = 458 new Notification.Action.Builder(R.drawable.ic_reply_icon, 459 getString(R.string.label), replyPendingIntent) 460 .addRemoteInput(remoteInput) 461 .build(); 462 </pre> 463 </li> 464 465 <li>Apply the action to a notification and issue the notification. 466 467 <pre> 468 // Build the notification and add the action. 469 Notification newMessageNotification = 470 new Notification.Builder(mContext) 471 .setSmallIcon(R.drawable.ic_message) 472 .setContentTitle(getString(R.string.title)) 473 .setContentText(getString(R.string.content)) 474 .addAction(action)) 475 .build(); 476 477 // Issue the notification. 478 NotificationManager notificationManager = 479 NotificationManager.from(mContext); 480 notificationManager.notify(notificationId, newMessageNotification); 481 482 </pre> 483 </li> 484 485 </ol> 486 487 488 <p> The system prompts the user to input a response when they trigger the 489 notification action. </p> 490 491 <img id="fig-user-input" src="{@docRoot}images/android-7.0/inline-type-reply.png" 492 srcset="{@docRoot}images/android-7.0/inline-type-reply.png 1x, 493 {@docRoot}images/android-7.0/inline-type-reply_2x.png 2x" 494 width="300"> 495 <p class="img-caption"> 496 <strong>Figure 2.</strong> The user inputs text from the notification shade. 497 </p> 498 499 <h3> 500 Retrieving user input from the inline reply 501 </h3> 502 503 <p> 504 To receive user input from the notification interface to the activity you 505 declared in the reply action's intent: 506 </p> 507 508 <ol> 509 <li>Call {@link android.support.v4.app.RemoteInput#getResultsFromIntent 510 getResultsFromIntent()} by passing the notification actions intent as the 511 input parameter. This method returns a {@link android.os.Bundle} that 512 contains the text response. 513 514 <pre> 515 Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); 516 </pre> 517 </li> 518 519 <li>Query the bundle using the result key (provided to the {@link 520 android.support.v4.app.RemoteInput.Builder} constructor). You can complete 521 this process and retrieve the input text by creating a method, as in the 522 following code snippet: 523 524 <pre> 525 // Obtain the intent that started this activity by calling 526 // Activity.getIntent() and pass it into this method to 527 // get the associated string. 528 529 private CharSequence getMessageText(Intent intent) { 530 Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); 531 if (remoteInput != null) { 532 return remoteInput.getCharSequence(KEY_TEXT_REPLY); 533 } 534 return null; 535 } 536 </pre> 537 </li> 538 539 <li>Build and issue another notification, using the same notification ID that 540 you provided for the previous notification. The progress indicator 541 disappears from the notification interface to inform users of a successful 542 reply. When working with this new notification, use the context that gets 543 passed to the receiver's {@code onReceive()} method. 544 545 <pre> 546 // Build a new notification, which informs the user that the system 547 // handled their interaction with the previous notification. 548 Notification repliedNotification = 549 new Notification.Builder(context) 550 .setSmallIcon(R.drawable.ic_message) 551 .setContentText(getString(R.string.replied)) 552 .build(); 553 554 // Issue the new notification. 555 NotificationManager notificationManager = 556 NotificationManager.from(context); 557 notificationManager.notify(notificationId, repliedNotification); 558 </pre> 559 </li> 560 </ol> 561 562 <p> 563 For interactive apps, such as chats, you can include additional 564 context when handling retrieved text. For example, these apps could show 565 multiple lines of chat history. When the user responds via {@link 566 android.support.v4.app.RemoteInput}, you can update the reply history 567 using the {@code setRemoteInputHistory()} method. 568 </p> 569 570 <p> 571 The notification must be either updated or cancelled after the app has 572 received remote input. When the user replies to a remote update 573 using Direct Reply, 574 do not cancel the notification. Instead, update the notification 575 to display the user's reply. 576 For notifications using {@code MessagingStyle}, you should add 577 the reply as the latest message. When using other templates, you can 578 append the user's reply to the remote-input history. 579 </p> 580 581 <!-------------------------------------------------------------------------- --> 582 583 <h2 id="bundle">Bundling notifications</h2> 584 585 <p> 586 Starting in Android 7.0 (API level 24), 587 Android provides developers with a new way to represent 588 a queue of notifications: <i>bundled notifications</i>. This is similar to the 589 <a href="{@docRoot}training/wearables/notifications/stacks.html">Notification 590 Stacks</a> feature in Android Wear. For example, if your app 591 creates notifications 592 for received messages, when more than one message is received, bundle the 593 notifications together as a single group. You can 594 use the {@link android.support.v4.app.NotificationCompat.Builder#setGroup 595 Builder.setGroup()} method to bundle similar notifications.</p> 596 597 <p> 598 A notification group imposes a hierarchy on the notifications comprising it. 599 At the top of that hierarchy is a parent notification that displays summary 600 information for the group. The user can progressively 601 expand the notification group, and the system shows more information as the 602 user drills deeper. When the user expands the bundle, the system reveals more 603 information for all its child notifications; when the user 604 expands one of those notifications, the system reveals its entire content. 605 </p> 606 607 <img id="fig-bundles" src="{@docRoot}images/android-7.0/bundles.png" 608 srcset="{@docRoot}images/android-7.0/bundles.png 1x, 609 {@docRoot}images/android-7.0/bundles_2x.png 2x" 610 width="300"> 611 <p class="img-caption"> 612 <strong>Figure 3.</strong> The user can progressively expand the notification 613 group. 614 </p> 615 616 <p class="note"> 617 <strong>Note:</strong> If the same app sends four or more notifications 618 and does not specify a grouping, the 619 system automatically groups them together. 620 </p> 621 622 <p>To learn how to add notifications to a group, see 623 <a href="{@docRoot}training/wearables/notifications/stacks.html#AddGroup">Add 624 Each Notification to a Group</a>.</p> 625 626 627 <h3 id="best-practices">Best practices for bundled notifications</h3> 628 <p>This section provides guidelines about when to use notification groups instead 629 of the {@link android.app.Notification.InboxStyle InboxStyle} 630 notifications available in Android 6.0 and previous versions.</p> 631 632 <h3>When to use bundled notifications</h3> 633 634 <p>You should use notification groups only if all of the following conditions are 635 true for your use case:</p> 636 637 <ul> 638 <li>The child notifications are complete notifications and can be displayed 639 individually without the need for a group summary.</li> 640 <li>There is a benefit to surfacing the child notifications individually. For 641 example: 642 </li> 643 <ul> 644 <li>They are actionable, with actions specific to each child.</li> 645 <li>There is more information to the child that the user wants to read.</li> 646 </ul> 647 </ul> 648 649 <p>Examples of good use cases for notification groups include: a messaging app 650 displaying a list of incoming messages, or an email app displaying a list of 651 received emails.</p> 652 653 <p> 654 Examples of cases where a single notification is preferable 655 include individual messages from a single person, or a list representation of 656 single-line text items. You can use 657 ({@link android.app.Notification.InboxStyle InboxStyle} or 658 {@link android.app.Notification.BigTextStyle BigTextStyle}) to accomplish 659 this. 660 </p> 661 662 <h3 id ="post">Displaying bundled notifications</h3> 663 664 <p> 665 The app should always post a group summary, even if the group contains just a 666 single child. The system will suppress the summary and directly display the 667 child notification if it only contains a single notification. This ensures 668 that the system can provide a consistent experience when the user swipes away 669 children of a group. 670 </p> 671 672 <h3>Peeking notifications</h3> 673 674 <p>While the system usually displays child notifications as a group, you can set 675 them to temporarily appear as 676 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#Heads-up"> 677 heads-up notifications</a>. This feature is especially useful because it allows 678 immediate access to the most recent child and the actions associated with it. 679 </p> 680 681 682 <h3>Backwards compatibility</h3> 683 684 <p> 685 Both notification groups and remote input have been a part of the {@link 686 android.app.Notification} API since Android 5.0 (API level 21) to support 687 Android Wear devices. If you've already built notifications with these APIs, 688 the only action you must take is to verify that the app behavior corresponds 689 to the guidelines described above, and to consider implementing {@code 690 setRemoteInputHistory()}. 691 </p> 692 693 <p> 694 In order to support backward compatibility, the same APIs are available with 695 the support library's {@link android.support.v4.app.NotificationCompat} 696 class, allowing you to build notifications that works on versions of Android 697 less than 5.0 (API level 21). 698 On handhelds and tablets, users only see the summary notification, 699 so an app should still have an inbox style or an equivalent notification 700 representative for the whole information content of the group. As Android 701 Wear devices allow users to see all child notifications even on older 702 platform levels, you should build child notifications regardless of API 703 level. 704 </p> 705 706 <!-- ------------------------------------------------------------------------------------------ --> 707 <!-- ------------------------------------------------------------------------------------------ --> 708 <h2 id="NotificationResponse">Preserving Navigation when Starting an Activity</h2> 709 <p> 710 When you start an {@link android.app.Activity} from a notification, you must preserve the 711 user's expected navigation experience. Clicking <i>Back</i> should take the user back through 712 the application's normal work flow to the Home screen, and clicking <i>Recents</i> should show 713 the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you 714 should start the {@link android.app.Activity} in a fresh task. How you set up the 715 {@link android.app.PendingIntent} to give you a fresh task depends on the nature of the 716 {@link android.app.Activity} you're starting. There are two general situations: 717 </p> 718 <dl> 719 <dt> 720 Regular activity 721 </dt> 722 <dd> 723 You're starting an {@link android.app.Activity} that's part of the application's normal 724 workflow. In this situation, set up the {@link android.app.PendingIntent} to 725 start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack 726 that reproduces the application's normal <i>Back</i> behavior. 727 <p> 728 Notifications from the Gmail app demonstrate this. When you click a notification for 729 a single email message, you see the message itself. Touching <b>Back</b> takes you 730 backwards through Gmail to the Home screen, just as if you had entered Gmail from the 731 Home screen rather than entering it from a notification. 732 </p> 733 <p> 734 This happens regardless of the application you were in when you touched the 735 notification. For example, if you're in Gmail composing a message, and you click a 736 notification for a single email, you go immediately to that email. Touching <i>Back</i> 737 takes you to the inbox and then the Home screen, rather than taking you to the 738 message you were composing. 739 </p> 740 </dd> 741 <dt> 742 Special activity 743 </dt> 744 <dd> 745 The user only sees this {@link android.app.Activity} if it's started from a notification. 746 In a sense, the {@link android.app.Activity} extends the notification by providing 747 information that would be hard to display in the notification itself. For this situation, 748 set up the {@link android.app.PendingIntent} to start in a fresh task. There's no need to 749 create a back stack, though, because the started {@link android.app.Activity} isn't part of 750 the application's activity flow. Clicking <i>Back</i> will still take the user to the 751 Home screen. 752 </dd> 753 </dl> 754 <!-- ------------------------------------------------------------------------------------------ --> 755 <h3 id="DirectEntry">Setting up a regular activity PendingIntent</h3> 756 <p> 757 To set up a {@link android.app.PendingIntent} that starts a direct entry 758 {@link android.app.Activity}, follow these steps: 759 </p> 760 <ol> 761 <li> 762 Define your application's {@link android.app.Activity} hierarchy in the manifest. 763 <ol style="list-style-type: lower-alpha;"> 764 <li> 765 Add support for Android 4.0.3 and earlier. To do this, specify the parent of the 766 {@link android.app.Activity} you're starting by adding a 767 <code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data></a></code> 768 element as the child of the 769 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>. 770 <p> 771 For this element, set 772 <code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>. 773 Set 774 <code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="<parent_activity_name>"</code> 775 where <code><parent_activity_name></code> is the value of 776 <code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code> 777 for the parent 778 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> 779 element. See the following XML for an example. 780 </p> 781 </li> 782 <li> 783 Also add support for Android 4.1 and later. To do this, add the 784 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code> 785 attribute to the 786 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> 787 element of the {@link android.app.Activity} you're starting. 788 </li> 789 </ol> 790 <p> 791 The final XML should look like this: 792 </p> 793 <pre> 794 <activity 795 android:name=".MainActivity" 796 android:label="@string/app_name" > 797 <intent-filter> 798 <action android:name="android.intent.action.MAIN" /> 799 <category android:name="android.intent.category.LAUNCHER" /> 800 </intent-filter> 801 </activity> 802 <activity 803 android:name=".ResultActivity" 804 android:parentActivityName=".MainActivity"> 805 <meta-data 806 android:name="android.support.PARENT_ACTIVITY" 807 android:value=".MainActivity"/> 808 </activity> 809 </pre> 810 </li> 811 <li> 812 Create a back stack based on the {@link android.content.Intent} that starts the 813 {@link android.app.Activity}: 814 <ol style="list-style-type: lower-alpha;"> 815 <li> 816 Create the {@link android.content.Intent} to start the {@link android.app.Activity}. 817 </li> 818 <li> 819 Create a stack builder by calling {@link android.app.TaskStackBuilder#create 820 TaskStackBuilder.create()}. 821 </li> 822 <li> 823 Add the back stack to the stack builder by calling 824 {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}. 825 For each {@link android.app.Activity} in the hierarchy you've defined in the 826 manifest, the back stack contains an {@link android.content.Intent} object that 827 starts the {@link android.app.Activity}. This method also adds flags that start the 828 stack in a fresh task. 829 <p class="note"> 830 <strong>Note:</strong> Although the argument to 831 {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} 832 is a reference to the started {@link android.app.Activity}, the method call 833 doesn't add the {@link android.content.Intent} that starts the 834 {@link android.app.Activity}. Instead, that's taken care of in the next step. 835 </p> 836 </li> 837 <li> 838 Add the {@link android.content.Intent} that starts the {@link android.app.Activity} 839 from the notification, by calling 840 {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}. 841 Pass the {@link android.content.Intent} you created in the first step as the 842 argument to 843 {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}. 844 </li> 845 <li> 846 If you need to, add arguments to {@link android.content.Intent} objects on the 847 stack by calling {@link android.support.v4.app.TaskStackBuilder#editIntentAt 848 TaskStackBuilder.editIntentAt()}. This is sometimes necessary to ensure that the 849 target {@link android.app.Activity} displays meaningful data when the user navigates 850 to it using <i>Back</i>. 851 </li> 852 <li> 853 Get a {@link android.app.PendingIntent} for this back stack by calling 854 {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}. 855 You can then use this {@link android.app.PendingIntent} as the argument to 856 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent 857 setContentIntent()}. 858 </li> 859 </ol> 860 </li> 861 </ol> 862 <p> 863 The following code snippet demonstrates the process: 864 </p> 865 <pre> 866 ... 867 Intent resultIntent = new Intent(this, ResultActivity.class); 868 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 869 // Adds the back stack 870 stackBuilder.addParentStack(ResultActivity.class); 871 // Adds the Intent to the top of the stack 872 stackBuilder.addNextIntent(resultIntent); 873 // Gets a PendingIntent containing the entire back stack 874 PendingIntent resultPendingIntent = 875 stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 876 ... 877 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 878 builder.setContentIntent(resultPendingIntent); 879 NotificationManager mNotificationManager = 880 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 881 mNotificationManager.notify(id, builder.build()); 882 </pre> 883 <!-- ------------------------------------------------------------------------------------------ --> 884 <h3 id="ExtendedNotification">Setting up a special activity PendingIntent</h3> 885 <p> 886 The following section describes how to set up a special activity 887 {@link android.app.PendingIntent}. 888 </p> 889 <p> 890 A special {@link android.app.Activity} doesn't need a back stack, so you don't have to 891 define its {@link android.app.Activity} hierarchy in the manifest, and you don't have 892 to call 893 {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a 894 back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options, 895 and create the {@link android.app.PendingIntent} by calling 896 {@link android.app.PendingIntent#getActivity getActivity()}: 897 </p> 898 <ol> 899 <li> 900 In your manifest, add the following attributes to the 901 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> 902 element for the {@link android.app.Activity} 903 <dl> 904 <dt> 905 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code> 906 </dt> 907 <dd> 908 The activity's fully-qualified class name. 909 </dd> 910 <dt> 911 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code> 912 </dt> 913 <dd> 914 Combined with the 915 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag 916 that you set in code, this ensures that this {@link android.app.Activity} doesn't 917 go into the application's default task. Any existing tasks that have the 918 application's default affinity are not affected. 919 </dd> 920 <dt> 921 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code> 922 </dt> 923 <dd> 924 Excludes the new task from <i>Recents</i>, so that the user can't accidentally 925 navigate back to it. 926 </dd> 927 </dl> 928 <p> 929 This snippet shows the element: 930 </p> 931 <pre> 932 <activity 933 android:name=".ResultActivity" 934 ... 935 android:launchMode="singleTask" 936 android:taskAffinity="" 937 android:excludeFromRecents="true"> 938 </activity> 939 ... 940 </pre> 941 </li> 942 <li> 943 Build and issue the notification: 944 <ol style="list-style-type: lower-alpha;"> 945 <li> 946 Create an {@link android.content.Intent} that starts the 947 {@link android.app.Activity}. 948 </li> 949 <li> 950 Set the {@link android.app.Activity} to start in a new, empty task by calling 951 {@link android.content.Intent#setFlags setFlags()} with the flags 952 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} 953 and 954 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}. 955 </li> 956 <li> 957 Set any other options you need for the {@link android.content.Intent}. 958 </li> 959 <li> 960 Create a {@link android.app.PendingIntent} from the {@link android.content.Intent} 961 by calling {@link android.app.PendingIntent#getActivity getActivity()}. 962 You can then use this {@link android.app.PendingIntent} as the argument to 963 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent 964 setContentIntent()}. 965 </li> 966 </ol> 967 <p> 968 The following code snippet demonstrates the process: 969 </p> 970 <pre> 971 // Instantiate a Builder object. 972 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 973 // Creates an Intent for the Activity 974 Intent notifyIntent = 975 new Intent(this, ResultActivity.class); 976 // Sets the Activity to start in a new, empty task 977 notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 978 | Intent.FLAG_ACTIVITY_CLEAR_TASK); 979 // Creates the PendingIntent 980 PendingIntent notifyPendingIntent = 981 PendingIntent.getActivity( 982 this, 983 0, 984 notifyIntent, 985 PendingIntent.FLAG_UPDATE_CURRENT 986 ); 987 988 // Puts the PendingIntent into the notification builder 989 builder.setContentIntent(notifyPendingIntent); 990 // Notifications are issued by sending them to the 991 // NotificationManager system service. 992 NotificationManager mNotificationManager = 993 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 994 // Builds an anonymous Notification object from the builder, and 995 // passes it to the NotificationManager 996 mNotificationManager.notify(id, builder.build()); 997 </pre> 998 </li> 999 </ol> 1000 <!-- ------------------------------------------------------------------------------------------ --> 1001 <!-- ------------------------------------------------------------------------------------------ --> 1002 <h2 id="Progress">Displaying Progress in a Notification</h2> 1003 <p> 1004 Notifications can include an animated progress indicator that shows users the status 1005 of an ongoing operation. If you can estimate how long the operation takes and how much of it 1006 is complete at any time, use the "determinate" form of the indicator 1007 (a progress bar). If you can't estimate the length of the operation, use the 1008 "indeterminate" form of the indicator (an activity indicator). 1009 </p> 1010 <p> 1011 Progress indicators are displayed with the platform's implementation of the 1012 {@link android.widget.ProgressBar} class. 1013 </p> 1014 <p> 1015 To use a progress indicator on platforms starting with Android 4.0, call 1016 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. For 1017 previous versions, you must create your own custom notification layout that 1018 includes a {@link android.widget.ProgressBar} view. 1019 </p> 1020 <p> 1021 The following sections describe how to display progress in a notification using 1022 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. 1023 </p> 1024 <!-- ------------------------------------------------------------------------------------------ --> 1025 <h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3> 1026 <p> 1027 To display a determinate progress bar, add the bar to your notification by calling 1028 {@link android.support.v4.app.NotificationCompat.Builder#setProgress 1029 setProgress(max, progress, false)} and then issue the notification. As your operation proceeds, 1030 increment <code>progress</code>, and update the notification. At the end of the operation, 1031 <code>progress</code> should equal <code>max</code>. A common way to call 1032 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()} 1033 is to set <code>max</code> to 100 and then increment <code>progress</code> as a 1034 "percent complete" value for the operation. 1035 </p> 1036 <p> 1037 You can either leave the progress bar showing when the operation is done, or remove it. In 1038 either case, remember to update the notification text to show that the operation is complete. 1039 To remove the progress bar, call 1040 {@link android.support.v4.app.NotificationCompat.Builder#setProgress 1041 setProgress(0, 0, false)}. For example: 1042 </p> 1043 <pre> 1044 ... 1045 mNotifyManager = 1046 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 1047 mBuilder = new NotificationCompat.Builder(this); 1048 mBuilder.setContentTitle("Picture Download") 1049 .setContentText("Download in progress") 1050 .setSmallIcon(R.drawable.ic_notification); 1051 // Start a lengthy operation in a background thread 1052 new Thread( 1053 new Runnable() { 1054 @Override 1055 public void run() { 1056 int incr; 1057 // Do the "lengthy" operation 20 times 1058 for (incr = 0; incr <= 100; incr+=5) { 1059 // Sets the progress indicator to a max value, the 1060 // current completion percentage, and "determinate" 1061 // state 1062 mBuilder.setProgress(100, incr, false); 1063 // Displays the progress bar for the first time. 1064 mNotifyManager.notify(0, mBuilder.build()); 1065 // Sleeps the thread, simulating an operation 1066 // that takes time 1067 try { 1068 // Sleep for 5 seconds 1069 Thread.sleep(5*1000); 1070 } catch (InterruptedException e) { 1071 Log.d(TAG, "sleep failure"); 1072 } 1073 } 1074 // When the loop is finished, updates the notification 1075 mBuilder.setContentText("Download complete") 1076 // Removes the progress bar 1077 .setProgress(0,0,false); 1078 mNotifyManager.notify(ID, mBuilder.build()); 1079 } 1080 } 1081 // Starts the thread by calling the run() method in its Runnable 1082 ).start(); 1083 </pre> 1084 1085 <!-- ------------------------------------------------------------------------------------------ --> 1086 <h3 id="ActivityIndicator">Displaying a continuing activity indicator</h3> 1087 <p> 1088 To display an indeterminate activity indicator, add it to your notification with 1089 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)} 1090 (the first two arguments are ignored), and issue the notification. The result is an indicator 1091 that has the same style as a progress bar, except that its animation is ongoing. 1092 </p> 1093 <p> 1094 Issue the notification at the beginning of the operation. The animation will run until you 1095 modify your notification. When the operation is done, call 1096 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)} 1097 and then update the notification to remove the activity indicator. 1098 Always do this; otherwise, the animation will run even when the operation is complete. Also 1099 remember to change the notification text to indicate that the operation is complete. 1100 </p> 1101 <p> 1102 To see how activity indicators work, refer to the preceding snippet. Locate the following lines: 1103 </p> 1104 <pre> 1105 // Sets the progress indicator to a max value, the current completion 1106 // percentage, and "determinate" state 1107 mBuilder.setProgress(100, incr, false); 1108 // Issues the notification 1109 mNotifyManager.notify(0, mBuilder.build()); 1110 </pre> 1111 <p> 1112 Replace the lines you've found with the following lines: 1113 </p> 1114 <pre> 1115 // Sets an activity indicator for an operation of indeterminate length 1116 mBuilder.setProgress(0, 0, true); 1117 // Issues the notification 1118 mNotifyManager.notify(0, mBuilder.build()); 1119 </pre> 1120 1121 <h2 id="metadata">Notification Metadata</h2> 1122 1123 <p>Notifications may be sorted according to metadata that you assign with the 1124 following {@link android.support.v4.app.NotificationCompat.Builder} methods:</p> 1125 1126 <ul> 1127 <li>{@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()} 1128 tells the system how to handle your app notifications when the device is in Priority mode 1129 (for example, if your notification represents an incoming call, instant message, or alarm).</li> 1130 <li>{@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()} causes 1131 notifications with the priority field set to {@code PRIORITY_MAX} or {@code PRIORITY_HIGH} to 1132 appear in a small floating window if the notification also has sound or vibration.</li> 1133 <li>{@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()} 1134 allows you to add a list of people to a notification. Your app can use this to signal to the 1135 system that it should group together notifications from the specified people, or rank notifications 1136 from these people as being more important.</li> 1137 </ul> 1138 1139 <div class="figure" style="width:230px"> 1140 <img src="{@docRoot}images/ui/notifications/heads-up.png" 1141 alt="" width="" height="" id="figure3" /> 1142 <p class="img-caption"> 1143 <strong>Figure 3.</strong> Fullscreen activity showing a heads-up notification 1144 </p> 1145 </div> 1146 1147 <h2 id="Heads-up">Heads-up Notifications</h2> 1148 1149 <p>With Android 5.0 (API level 21), notifications can appear in a small floating window 1150 (also called a <em>heads-up notification</em>) when the device is active 1151 (that is, the device is unlocked and its screen is on). These notifications 1152 appear similar to the compact form of your notification, except that the 1153 heads-up notification also shows action buttons. Users can act on, or dismiss, 1154 a heads-up notification without leaving the current app.</p> 1155 1156 <p>Examples of conditions that may trigger heads-up notifications include:</p> 1157 1158 <ul> 1159 <li>The user's activity is in fullscreen mode (the app uses 1160 {@link android.app.Notification#fullScreenIntent}), or</li> 1161 <li>The notification has high priority and uses ringtones or 1162 vibrations</li> 1163 </ul> 1164 1165 <h2 id="lockscreenNotification">Lock Screen Notifications</h2> 1166 1167 <p>With the release of Android 5.0 (API level 21), notifications may now appear on the lock 1168 screen. Your app can use this functionality to provide media playback controls and other common 1169 actions. Users can choose via Settings whether to display notifications on the lock screen, and 1170 you can designate whether a notification from your app is visible on the lock screen.</p> 1171 1172 <h3 id="visibility">Setting Visibility</h3> 1173 1174 <p>Your app can control the level of detail visible in notifications displayed on a secure 1175 lock screen. You call {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()} 1176 and specify one of the following values:</p> 1177 1178 <ul> 1179 <li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC} shows the notification's 1180 full content.</li> 1181 <li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET} doesn't show any part of 1182 this notification on the lock screen.</li> 1183 <li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} shows basic information, 1184 such as the notification's icon and the content title, but hides the notification's full content.</li> 1185 </ul> 1186 1187 <p>When {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} is set, you can also 1188 provide an alternate version of the notification content which hides certain details. For example, 1189 an SMS app might display a notification that shows <em>You have 3 new text messages</em>, but hides the 1190 message contents and senders. To provide this alternative notification, first create the replacement 1191 notification using {@link android.support.v4.app.NotificationCompat.Builder}. When you create the 1192 private notification object, attach the replacement notification to it through the 1193 {@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()} 1194 method.</p> 1195 1196 <h3 id="controllingMedia">Controlling Media Playback on the Lock Screen</h3> 1197 1198 <p> 1199 In Android 5.0 (API level 21) the lock screen no longer displays media 1200 controls based on the {@link android.media.RemoteControlClient}, which is 1201 now deprecated. Instead, use the {@link 1202 android.support.v7.app.NotificationCompat.MediaStyle} template with the 1203 {@link 1204 android.support.v4.app.NotificationCompat.Builder#addAction(android.support.v4.app.NotificationCompat.Action) 1205 addAction()} method, which converts actions into clickable icons. 1206 </p> 1207 1208 <p> 1209 To display media playback controls on the lock screen in Android 5.0, set 1210 the visibility to {@link 1211 android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, as described 1212 above. Then add the actions and set the {@link 1213 android.support.v7.app.NotificationCompat.MediaStyle} template, as described 1214 in the following sample code: 1215 </p> 1216 1217 <pre> 1218 Notification notification = new NotificationCompat.Builder(context) 1219 // Show controls on lock screen even when user hides sensitive content. 1220 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) 1221 .setSmallIcon(R.drawable.ic_stat_player) 1222 // Add media control buttons that invoke intents in your media service 1223 .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0 1224 .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1 1225 .addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2 1226 // Apply the media style template 1227 .setStyle(new NotificationCompat.MediaStyle() 1228 .setShowActionsInCompactView(1 /* #1: pause button */) 1229 .setMediaSession(mMediaSession.getSessionToken())) 1230 .setContentTitle("Wonderful music") 1231 .setContentText("My Awesome Band") 1232 .setLargeIcon(albumArtBitmap) 1233 .build(); 1234 </pre> 1235 1236 <p class="note"><strong>Note:</strong> The deprecation of {@link android.media.RemoteControlClient} 1237 has further implications for controlling media. See 1238 <a href="{@docRoot}about/versions/android-5.0.html#MediaPlaybackControl">Media Playback Control</a> 1239 for more information about the new APIs for managing the media session and controlling playback.</p> 1240 1241 1242 <!-- ------------------------------------------------------------------------------------------ --> 1243 <h2 id="CustomNotification">Custom Notification Layouts</h2> 1244 <p> 1245 The notifications framework allows you to define a custom notification layout, which 1246 defines the notification's appearance in a {@link android.widget.RemoteViews} object. 1247 Custom layout notifications are similar to normal notifications, but they're based on a 1248 {@link android.widget.RemoteViews} defined in a XML layout file. 1249 </p> 1250 <p> 1251 The height available for a custom notification layout depends on the notification view. Normal 1252 view layouts are limited to 64 dp, and expanded view layouts are limited to 256 dp. 1253 </p> 1254 <p> 1255 To define a custom notification layout, start by instantiating a 1256 {@link android.widget.RemoteViews} object that inflates an XML layout file. Then, 1257 instead of calling methods such as 1258 {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}, 1259 call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set 1260 content details in the custom notification, use the methods in 1261 {@link android.widget.RemoteViews} to set the values of the view's children: 1262 </p> 1263 <ol> 1264 <li> 1265 Create an XML layout for the notification in a separate file. You can use any file name 1266 you wish, but you must use the extension <code>.xml</code> 1267 </li> 1268 <li> 1269 In your app, use {@link android.widget.RemoteViews} methods to define your notification's 1270 icons and text. Put this {@link android.widget.RemoteViews} object into your 1271 {@link android.support.v4.app.NotificationCompat.Builder} by calling 1272 {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Avoid 1273 setting a background {@link android.graphics.drawable.Drawable} on your 1274 {@link android.widget.RemoteViews} object, because your text color may become unreadable. 1275 </li> 1276 </ol> 1277 <p> 1278 The {@link android.widget.RemoteViews} class also includes methods that you can use to easily 1279 add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar} 1280 to your notification's layout. For more information about creating custom layouts for your 1281 notification, refer to the {@link android.widget.RemoteViews} reference documentation. 1282 </p> 1283 <p class="caution"> 1284 <strong>Caution:</strong> When you use a custom notification layout, take special care to 1285 ensure that your custom layout works with different device orientations and resolutions. While 1286 this advice applies to all View layouts, it's especially important for notifications because 1287 the space in the notification drawer is very restricted. Don't make your custom layout too 1288 complex, and be sure to test it in various configurations. 1289 </p> 1290 <!-- ------------------------------------------------------------------------------------------ --> 1291 <h4>Using style resources for custom notification text</h4> 1292 <p> 1293 Always use style resources for the text of a custom notification. The background color of the 1294 notification can vary across different devices and versions, and using style resources 1295 helps you account for this. Starting in Android 2.3, the system defined a style for the 1296 standard notification layout text. If you use the same style in applications that target Android 1297 2.3 or higher, you'll ensure that your text is visible against the display background. 1298 </p> 1299 1300 <!-- ------------------------------------------------------------------------ --> 1301 <h3 id="custom"> Custom Views</h3> 1302 <p> 1303 Starting from Android 7.0 (API level 24), 1304 you can customize notification views and 1305 still obtain system decorations like notification headers, actions, and 1306 expandable layouts. 1307 </p> 1308 1309 <p>To enable this capability, Android provides the following APIs to style your 1310 custom view:</p> 1311 1312 <dl> 1313 <dt> 1314 {@code DecoratedCustomViewStyle()}</dt> 1315 <dd> Styles notifications other than media 1316 notifications.</dd> 1317 <dt> 1318 {@code DecoratedMediaCustomViewStyle()}</dt> 1319 <dd> Styles media notifications.</dd> 1320 </dl> 1321 1322 <p>To use this API, call the {@code setStyle()} method, passing to it 1323 the desired custom view style.</p> 1324 1325 <p>This snippet shows how to construct a custom notification object with the 1326 {@code DecoratedCustomViewStyle()} method.</p> 1327 1328 <pre> 1329 Notification notification = new Notification.Builder() 1330 .setSmallIcon(R.drawable.ic_stat_player) 1331 .setLargeIcon(albumArtBitmap)) 1332 .setCustomContentView(contentView); 1333 .setStyle(new Notification.DecoratedCustomViewStyle()) 1334 .build(); 1335 1336 </pre> 1337 1338 <!-- ----------------------------------------------------------------------- --> 1339 1340 <h3 id="style">Messaging Style</h3> 1341 <p> 1342 Starting in Android 7.0 (API level 24), 1343 Android provides an API for customizing the style of a notification. 1344 Using the <code>MessagingStyle</code> class, you can change several of the 1345 labels displayed on the notification, including the conversation title, 1346 additional messages, and the content view for the notification. 1347 </p> 1348 1349 <p> 1350 The following code snippet demonstrates how to customize a notification's 1351 style using the <code>MessagingStyle</code> class. 1352 </p> 1353 1354 <pre> 1355 Notification notification = new Notification.Builder() 1356 .setStyle(new Notification.MessagingStyle("Me") 1357 .setConversationTitle("Team lunch") 1358 .addMessage("Hi", timestamp1, null) // Pass in null for user. 1359 .addMessage("What's up?", timestamp2, "Coworker") 1360 .addMessage("Not much", timestamp3, null) 1361 .addMessage("How about lunch?", timestamp4, "Coworker")) 1362 .build(); 1363 </pre> 1364 1365