NotificationCompat.java revision cd05a19c0775e69e93e4c93b0a48ab044b531d7a
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.app; 18 19import android.app.Notification; 20import android.app.PendingIntent; 21import android.content.Context; 22import android.graphics.Bitmap; 23import android.graphics.Color; 24import android.media.AudioManager; 25import android.net.Uri; 26import android.os.Build; 27import android.os.Bundle; 28import android.widget.RemoteViews; 29 30import java.util.ArrayList; 31 32/** 33 * Helper for accessing features in {@link android.app.Notification} 34 * introduced after API level 4 in a backwards compatible fashion. 35 */ 36public class NotificationCompat { 37 38 /** 39 * Use all default values (where applicable). 40 */ 41 public static final int DEFAULT_ALL = ~0; 42 43 /** 44 * Use the default notification sound. This will ignore any sound set using 45 * {@link Builder#setSound} 46 * 47 * @see Builder#setDefaults 48 */ 49 public static final int DEFAULT_SOUND = 1; 50 51 /** 52 * Use the default notification vibrate. This will ignore any vibrate set using 53 * {@link Builder#setVibrate}. Using phone vibration requires the 54 * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. 55 * 56 * @see Builder#setDefaults 57 */ 58 public static final int DEFAULT_VIBRATE = 2; 59 60 /** 61 * Use the default notification lights. This will ignore the 62 * {@link #FLAG_SHOW_LIGHTS} bit, and values set with {@link Builder#setLights}. 63 * 64 * @see Builder#setDefaults 65 */ 66 public static final int DEFAULT_LIGHTS = 4; 67 68 /** 69 * Use this constant as the value for audioStreamType to request that 70 * the default stream type for notifications be used. Currently the 71 * default stream type is {@link AudioManager#STREAM_NOTIFICATION}. 72 */ 73 public static final int STREAM_DEFAULT = -1; 74 75 /** 76 * Bit set in the Notification flags field when LEDs should be turned on 77 * for this notification. 78 */ 79 public static final int FLAG_SHOW_LIGHTS = 0x00000001; 80 81 /** 82 * Bit set in the Notification flags field if this notification is in 83 * reference to something that is ongoing, like a phone call. It should 84 * not be set if this notification is in reference to something that 85 * happened at a particular point in time, like a missed phone call. 86 */ 87 public static final int FLAG_ONGOING_EVENT = 0x00000002; 88 89 /** 90 * Bit set in the Notification flags field if 91 * the audio will be repeated until the notification is 92 * cancelled or the notification window is opened. 93 */ 94 public static final int FLAG_INSISTENT = 0x00000004; 95 96 /** 97 * Bit set in the Notification flags field if the notification's sound, 98 * vibrate and ticker should only be played if the notification is not already showing. 99 */ 100 public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008; 101 102 /** 103 * Bit set in the Notification flags field if the notification should be canceled when 104 * it is clicked by the user. 105 */ 106 public static final int FLAG_AUTO_CANCEL = 0x00000010; 107 108 /** 109 * Bit set in the Notification flags field if the notification should not be canceled 110 * when the user clicks the Clear all button. 111 */ 112 public static final int FLAG_NO_CLEAR = 0x00000020; 113 114 /** 115 * Bit set in the Notification flags field if this notification represents a currently 116 * running service. This will normally be set for you by 117 * {@link android.app.Service#startForeground}. 118 */ 119 public static final int FLAG_FOREGROUND_SERVICE = 0x00000040; 120 121 /** 122 * Obsolete flag indicating high-priority notifications; use the priority field instead. 123 * 124 * @deprecated Use {@link NotificationCompat.Builder#setPriority(int)} with a positive value. 125 */ 126 public static final int FLAG_HIGH_PRIORITY = 0x00000080; 127 128 /** 129 * Bit set in the Notification flags field if this notification is relevant to the current 130 * device only and it is not recommended that it bridge to other devices. 131 */ 132 public static final int FLAG_LOCAL_ONLY = 0x00000100; 133 134 /** 135 * Bit set in the Notification flags field if this notification is the group summary for a 136 * group of notifications. Grouped notifications may display in a cluster or stack on devices 137 * which support such rendering. Requires a group key also be set using 138 * {@link Builder#setGroup}. 139 */ 140 public static final int FLAG_GROUP_SUMMARY = 0x00000200; 141 142 /** 143 * Default notification priority for {@link NotificationCompat.Builder#setPriority(int)}. 144 * If your application does not prioritize its own notifications, 145 * use this value for all notifications. 146 */ 147 public static final int PRIORITY_DEFAULT = 0; 148 149 /** 150 * Lower notification priority for {@link NotificationCompat.Builder#setPriority(int)}, 151 * for items that are less important. The UI may choose to show 152 * these items smaller, or at a different position in the list, 153 * compared with your app's {@link #PRIORITY_DEFAULT} items. 154 */ 155 public static final int PRIORITY_LOW = -1; 156 157 /** 158 * Lowest notification priority for {@link NotificationCompat.Builder#setPriority(int)}; 159 * these items might not be shown to the user except under 160 * special circumstances, such as detailed notification logs. 161 */ 162 public static final int PRIORITY_MIN = -2; 163 164 /** 165 * Higher notification priority for {@link NotificationCompat.Builder#setPriority(int)}, 166 * for more important notifications or alerts. The UI may choose 167 * to show these items larger, or at a different position in 168 * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items. 169 */ 170 public static final int PRIORITY_HIGH = 1; 171 172 /** 173 * Highest notification priority for {@link NotificationCompat.Builder#setPriority(int)}, 174 * for your application's most important items that require the user's 175 * prompt attention or input. 176 */ 177 public static final int PRIORITY_MAX = 2; 178 179 /** 180 * Notification extras key: this is the title of the notification, 181 * as supplied to {@link Builder#setContentTitle(CharSequence)}. 182 */ 183 public static final String EXTRA_TITLE = "android.title"; 184 185 /** 186 * Notification extras key: this is the title of the notification when shown in expanded form, 187 * e.g. as supplied to {@link BigTextStyle#setBigContentTitle(CharSequence)}. 188 */ 189 public static final String EXTRA_TITLE_BIG = EXTRA_TITLE + ".big"; 190 191 /** 192 * Notification extras key: this is the main text payload, as supplied to 193 * {@link Builder#setContentText(CharSequence)}. 194 */ 195 public static final String EXTRA_TEXT = "android.text"; 196 197 /** 198 * Notification extras key: this is a third line of text, as supplied to 199 * {@link Builder#setSubText(CharSequence)}. 200 */ 201 public static final String EXTRA_SUB_TEXT = "android.subText"; 202 203 /** 204 * Notification extras key: this is a small piece of additional text as supplied to 205 * {@link Builder#setContentInfo(CharSequence)}. 206 */ 207 public static final String EXTRA_INFO_TEXT = "android.infoText"; 208 209 /** 210 * Notification extras key: this is a line of summary information intended to be shown 211 * alongside expanded notifications, as supplied to (e.g.) 212 * {@link BigTextStyle#setSummaryText(CharSequence)}. 213 */ 214 public static final String EXTRA_SUMMARY_TEXT = "android.summaryText"; 215 216 /** 217 * Notification extras key: this is the resource ID of the notification's main small icon, as 218 * supplied to {@link Builder#setSmallIcon(int)}. 219 */ 220 public static final String EXTRA_SMALL_ICON = "android.icon"; 221 222 /** 223 * Notification extras key: this is a bitmap to be used instead of the small icon when showing the 224 * notification payload, as 225 * supplied to {@link Builder#setLargeIcon(android.graphics.Bitmap)}. 226 */ 227 public static final String EXTRA_LARGE_ICON = "android.largeIcon"; 228 229 /** 230 * Notification extras key: this is a bitmap to be used instead of the one from 231 * {@link Builder#setLargeIcon(android.graphics.Bitmap)} when the notification is 232 * shown in its expanded form, as supplied to 233 * {@link BigPictureStyle#bigLargeIcon(android.graphics.Bitmap)}. 234 */ 235 public static final String EXTRA_LARGE_ICON_BIG = EXTRA_LARGE_ICON + ".big"; 236 237 /** 238 * Notification extras key: this is the progress value supplied to 239 * {@link Builder#setProgress(int, int, boolean)}. 240 */ 241 public static final String EXTRA_PROGRESS = "android.progress"; 242 243 /** 244 * Notification extras key: this is the maximum value supplied to 245 * {@link Builder#setProgress(int, int, boolean)}. 246 */ 247 public static final String EXTRA_PROGRESS_MAX = "android.progressMax"; 248 249 /** 250 * Notification extras key: whether the progress bar is indeterminate, supplied to 251 * {@link Builder#setProgress(int, int, boolean)}. 252 */ 253 public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate"; 254 255 /** 256 * Notification extras key: whether the when field set using {@link Builder#setWhen} should 257 * be shown as a count-up timer (specifically a {@link android.widget.Chronometer}) instead 258 * of a timestamp, as supplied to {@link Builder#setUsesChronometer(boolean)}. 259 */ 260 public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer"; 261 262 /** 263 * Notification extras key: this is a bitmap to be shown in {@link BigPictureStyle} expanded 264 * notifications, supplied to {@link BigPictureStyle#bigPicture(android.graphics.Bitmap)}. 265 */ 266 public static final String EXTRA_PICTURE = "android.picture"; 267 268 /** 269 * Notification extras key: An array of CharSequences to show in {@link InboxStyle} expanded 270 * notifications, each of which was supplied to {@link InboxStyle#addLine(CharSequence)}. 271 */ 272 public static final String EXTRA_TEXT_LINES = "android.textLines"; 273 274 /** 275 * Notification extras key: An array of people that this notification relates to, specified 276 * by contacts provider contact URI. 277 */ 278 public static final String EXTRA_PEOPLE = "android.people"; 279 280 /** 281 * Value of {@link Notification#color} equal to 0 (also known as 282 * {@link android.graphics.Color#TRANSPARENT Color.TRANSPARENT}), 283 * telling the system not to decorate this notification with any special color but instead use 284 * default colors when presenting this notification. 285 */ 286 public static final int COLOR_DEFAULT = Color.TRANSPARENT; 287 288 /** 289 * Notification visibility: Show this notification in its entirety on all lockscreens. 290 * 291 * {@see android.app.Notification#visibility} 292 */ 293 public static final int VISIBILITY_PUBLIC = 1; 294 295 /** 296 * Notification visibility: Show this notification on all lockscreens, but conceal sensitive or 297 * private information on secure lockscreens. 298 * 299 * {@see android.app.Notification#visibility} 300 */ 301 public static final int VISIBILITY_PRIVATE = 0; 302 303 /** 304 * Notification visibility: Do not reveal any part of this notification on a secure lockscreen. 305 * 306 * {@see android.app.Notification#visibility} 307 */ 308 public static final int VISIBILITY_SECRET = -1; 309 310 private static final NotificationCompatImpl IMPL; 311 312 interface NotificationCompatImpl { 313 public Notification build(Builder b); 314 public Bundle getExtras(Notification n); 315 public int getActionCount(Notification n); 316 public Action getAction(Notification n, int actionIndex); 317 public boolean getLocalOnly(Notification n); 318 public String getGroup(Notification n); 319 public boolean isGroupSummary(Notification n); 320 public String getSortKey(Notification n); 321 } 322 323 static class NotificationCompatImplBase implements NotificationCompatImpl { 324 @Override 325 public Notification build(Builder b) { 326 Notification result = b.mNotification; 327 result.setLatestEventInfo(b.mContext, b.mContentTitle, 328 b.mContentText, b.mContentIntent); 329 // translate high priority requests into legacy flag 330 if (b.mPriority > PRIORITY_DEFAULT) { 331 result.flags |= FLAG_HIGH_PRIORITY; 332 } 333 return result; 334 } 335 336 @Override 337 public Bundle getExtras(Notification n) { 338 return null; 339 } 340 341 @Override 342 public int getActionCount(Notification n) { 343 return 0; 344 } 345 346 @Override 347 public Action getAction(Notification n, int actionIndex) { 348 return null; 349 } 350 351 @Override 352 public boolean getLocalOnly(Notification n) { 353 return false; 354 } 355 356 @Override 357 public String getGroup(Notification n) { 358 return null; 359 } 360 361 @Override 362 public boolean isGroupSummary(Notification n) { 363 return false; 364 } 365 366 @Override 367 public String getSortKey(Notification n) { 368 return null; 369 } 370 } 371 372 static class NotificationCompatImplGingerbread extends NotificationCompatImplBase { 373 @Override 374 public Notification build(Builder b) { 375 Notification result = b.mNotification; 376 result.setLatestEventInfo(b.mContext, b.mContentTitle, 377 b.mContentText, b.mContentIntent); 378 result = NotificationCompatGingerbread.add(result, b.mContext, 379 b.mContentTitle, b.mContentText, b.mContentIntent, b.mFullScreenIntent); 380 // translate high priority requests into legacy flag 381 if (b.mPriority > PRIORITY_DEFAULT) { 382 result.flags |= FLAG_HIGH_PRIORITY; 383 } 384 return result; 385 } 386 } 387 388 static class NotificationCompatImplHoneycomb extends NotificationCompatImplBase { 389 @Override 390 public Notification build(Builder b) { 391 return NotificationCompatHoneycomb.add(b.mContext, b.mNotification, 392 b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, 393 b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon); 394 } 395 } 396 397 static class NotificationCompatImplIceCreamSandwich extends NotificationCompatImplBase { 398 @Override 399 public Notification build(Builder b) { 400 return NotificationCompatIceCreamSandwich.add(b.mContext, b.mNotification, 401 b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, 402 b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 403 b.mProgressMax, b.mProgress, b.mProgressIndeterminate); 404 } 405 } 406 407 static class NotificationCompatImplJellybean extends NotificationCompatImplBase { 408 @Override 409 public Notification build(Builder b) { 410 NotificationCompatJellybean.Builder builder = new NotificationCompatJellybean.Builder( 411 b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, 412 b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 413 b.mProgressMax, b.mProgress, b.mProgressIndeterminate, 414 b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras, 415 b.mGroupKey, b.mGroupSummary, b.mSortKey); 416 addActionsToBuilder(builder, b.mActions); 417 addStyleToBuilderJellybean(builder, b.mStyle); 418 return builder.build(); 419 } 420 421 @Override 422 public Bundle getExtras(Notification n) { 423 return NotificationCompatJellybean.getExtras(n); 424 } 425 426 @Override 427 public int getActionCount(Notification n) { 428 return NotificationCompatJellybean.getActionCount(n); 429 } 430 431 @Override 432 public Action getAction(Notification n, int actionIndex) { 433 return (Action) NotificationCompatJellybean.getAction(n, actionIndex, Action.FACTORY, 434 RemoteInput.FACTORY); 435 } 436 437 @Override 438 public boolean getLocalOnly(Notification n) { 439 return NotificationCompatJellybean.getLocalOnly(n); 440 } 441 442 @Override 443 public String getGroup(Notification n) { 444 return NotificationCompatJellybean.getGroup(n); 445 } 446 447 @Override 448 public boolean isGroupSummary(Notification n) { 449 return NotificationCompatJellybean.isGroupSummary(n); 450 } 451 452 @Override 453 public String getSortKey(Notification n) { 454 return NotificationCompatJellybean.getSortKey(n); 455 } 456 } 457 458 static class NotificationCompatImplKitKat extends NotificationCompatImplJellybean { 459 @Override 460 public Notification build(Builder b) { 461 NotificationCompatKitKat.Builder builder = new NotificationCompatKitKat.Builder( 462 b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, 463 b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 464 b.mProgressMax, b.mProgress, b.mProgressIndeterminate, 465 b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mPeople, b.mExtras, 466 b.mGroupKey, b.mGroupSummary, b.mSortKey); 467 addActionsToBuilder(builder, b.mActions); 468 addStyleToBuilderJellybean(builder, b.mStyle); 469 return builder.build(); 470 } 471 472 @Override 473 public Bundle getExtras(Notification n) { 474 return NotificationCompatKitKat.getExtras(n); 475 } 476 477 @Override 478 public int getActionCount(Notification n) { 479 return NotificationCompatKitKat.getActionCount(n); 480 } 481 482 @Override 483 public Action getAction(Notification n, int actionIndex) { 484 return (Action) NotificationCompatKitKat.getAction(n, actionIndex, Action.FACTORY, 485 RemoteInput.FACTORY); 486 } 487 488 @Override 489 public boolean getLocalOnly(Notification n) { 490 return NotificationCompatKitKat.getLocalOnly(n); 491 } 492 493 @Override 494 public String getGroup(Notification n) { 495 return NotificationCompatKitKat.getGroup(n); 496 } 497 498 @Override 499 public boolean isGroupSummary(Notification n) { 500 return NotificationCompatKitKat.isGroupSummary(n); 501 } 502 503 @Override 504 public String getSortKey(Notification n) { 505 return NotificationCompatKitKat.getSortKey(n); 506 } 507 } 508 509 static class NotificationCompatImplApi20 extends NotificationCompatImplKitKat { 510 @Override 511 public Notification build(Builder b) { 512 NotificationCompatApi20.Builder builder = new NotificationCompatApi20.Builder( 513 b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, 514 b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 515 b.mProgressMax, b.mProgress, b.mProgressIndeterminate, 516 b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory, 517 b.mPeople, b.mExtras, b.mColor, b.mVisibility, b.mPublicVersion, 518 b.mGroupKey, b.mGroupSummary, b.mSortKey); 519 addActionsToBuilder(builder, b.mActions); 520 addStyleToBuilderJellybean(builder, b.mStyle); 521 return builder.build(); 522 } 523 524 @Override 525 public Action getAction(Notification n, int actionIndex) { 526 return (Action) NotificationCompatApi20.getAction(n, actionIndex, Action.FACTORY, 527 RemoteInput.FACTORY); 528 } 529 530 @Override 531 public boolean getLocalOnly(Notification n) { 532 return NotificationCompatApi20.getLocalOnly(n); 533 } 534 535 @Override 536 public String getGroup(Notification n) { 537 return NotificationCompatApi20.getGroup(n); 538 } 539 540 @Override 541 public boolean isGroupSummary(Notification n) { 542 return NotificationCompatApi20.isGroupSummary(n); 543 } 544 545 @Override 546 public String getSortKey(Notification n) { 547 return NotificationCompatApi20.getSortKey(n); 548 } 549 } 550 551 private static void addActionsToBuilder(NotificationBuilderWithActions builder, 552 ArrayList<Action> actions) { 553 for (Action action : actions) { 554 builder.addAction(action); 555 } 556 } 557 558 private static void addStyleToBuilderJellybean(NotificationBuilderWithBuilderAccessor builder, 559 Style style) { 560 if (style != null) { 561 if (style instanceof BigTextStyle) { 562 BigTextStyle bigTextStyle = (BigTextStyle) style; 563 NotificationCompatJellybean.addBigTextStyle(builder, 564 bigTextStyle.mBigContentTitle, 565 bigTextStyle.mSummaryTextSet, 566 bigTextStyle.mSummaryText, 567 bigTextStyle.mBigText); 568 } else if (style instanceof InboxStyle) { 569 InboxStyle inboxStyle = (InboxStyle) style; 570 NotificationCompatJellybean.addInboxStyle(builder, 571 inboxStyle.mBigContentTitle, 572 inboxStyle.mSummaryTextSet, 573 inboxStyle.mSummaryText, 574 inboxStyle.mTexts); 575 } else if (style instanceof BigPictureStyle) { 576 BigPictureStyle bigPictureStyle = (BigPictureStyle) style; 577 NotificationCompatJellybean.addBigPictureStyle(builder, 578 bigPictureStyle.mBigContentTitle, 579 bigPictureStyle.mSummaryTextSet, 580 bigPictureStyle.mSummaryText, 581 bigPictureStyle.mPicture, 582 bigPictureStyle.mBigLargeIcon, 583 bigPictureStyle.mBigLargeIconSet); 584 } 585 } 586 } 587 588 static { 589 // TODO: Replace this if clause when SDK_INT is incremented to 20. 590 if (Build.VERSION.RELEASE.equals("L")) { 591 IMPL = new NotificationCompatImplApi20(); 592 } else if (Build.VERSION.SDK_INT >= 19) { 593 IMPL = new NotificationCompatImplKitKat(); 594 } else if (Build.VERSION.SDK_INT >= 16) { 595 IMPL = new NotificationCompatImplJellybean(); 596 } else if (Build.VERSION.SDK_INT >= 14) { 597 IMPL = new NotificationCompatImplIceCreamSandwich(); 598 } else if (Build.VERSION.SDK_INT >= 11) { 599 IMPL = new NotificationCompatImplHoneycomb(); 600 } else if (Build.VERSION.SDK_INT >= 9) { 601 IMPL = new NotificationCompatImplGingerbread(); 602 } else { 603 IMPL = new NotificationCompatImplBase(); 604 } 605 } 606 607 /** 608 * Builder class for {@link NotificationCompat} objects. Allows easier control over 609 * all the flags, as well as help constructing the typical notification layouts. 610 * <p> 611 * On platform versions that don't offer expanded notifications, methods that depend on 612 * expanded notifications have no effect. 613 * </p> 614 * <p> 615 * For example, action buttons won't appear on platforms prior to Android 4.1. Action 616 * buttons depend on expanded notifications, which are only available in Android 4.1 617 * and later. 618 * <p> 619 * For this reason, you should always ensure that UI controls in a notification are also 620 * available in an {@link android.app.Activity} in your app, and you should always start that 621 * {@link android.app.Activity} when users click the notification. To do this, use the 622 * {@link NotificationCompat.Builder#setContentIntent setContentIntent()} 623 * method. 624 * </p> 625 * 626 */ 627 public static class Builder { 628 Context mContext; 629 630 CharSequence mContentTitle; 631 CharSequence mContentText; 632 PendingIntent mContentIntent; 633 PendingIntent mFullScreenIntent; 634 RemoteViews mTickerView; 635 Bitmap mLargeIcon; 636 CharSequence mContentInfo; 637 int mNumber; 638 int mPriority; 639 boolean mUseChronometer; 640 Style mStyle; 641 CharSequence mSubText; 642 int mProgressMax; 643 int mProgress; 644 boolean mProgressIndeterminate; 645 String mGroupKey; 646 boolean mGroupSummary; 647 String mSortKey; 648 ArrayList<Action> mActions = new ArrayList<Action>(); 649 boolean mLocalOnly = false; 650 String mCategory; 651 Bundle mExtras; 652 int mColor = COLOR_DEFAULT; 653 int mVisibility = VISIBILITY_PRIVATE; 654 Notification mPublicVersion; 655 656 Notification mNotification = new Notification(); 657 public ArrayList<String> mPeople; 658 659 /** 660 * Constructor. 661 * 662 * Automatically sets the when field to {@link System#currentTimeMillis() 663 * System.currentTimeMillis()} and the audio stream to the 664 * {@link Notification#STREAM_DEFAULT}. 665 * 666 * @param context A {@link Context} that will be used to construct the 667 * RemoteViews. The Context will not be held past the lifetime of this 668 * Builder object. 669 */ 670 public Builder(Context context) { 671 mContext = context; 672 673 // Set defaults to match the defaults of a Notification 674 mNotification.when = System.currentTimeMillis(); 675 mNotification.audioStreamType = Notification.STREAM_DEFAULT; 676 mPriority = PRIORITY_DEFAULT; 677 mPeople = new ArrayList<String>(); 678 } 679 680 /** 681 * Set the time that the event occurred. Notifications in the panel are 682 * sorted by this time. 683 */ 684 public Builder setWhen(long when) { 685 mNotification.when = when; 686 return this; 687 } 688 689 /** 690 * Show the {@link Notification#when} field as a stopwatch. 691 * 692 * Instead of presenting <code>when</code> as a timestamp, the notification will show an 693 * automatically updating display of the minutes and seconds since <code>when</code>. 694 * 695 * Useful when showing an elapsed time (like an ongoing phone call). 696 * 697 * @see android.widget.Chronometer 698 * @see Notification#when 699 */ 700 public Builder setUsesChronometer(boolean b) { 701 mUseChronometer = b; 702 return this; 703 } 704 705 /** 706 * Set the small icon to use in the notification layouts. Different classes of devices 707 * may return different sizes. See the UX guidelines for more information on how to 708 * design these icons. 709 * 710 * @param icon A resource ID in the application's package of the drawble to use. 711 */ 712 public Builder setSmallIcon(int icon) { 713 mNotification.icon = icon; 714 return this; 715 } 716 717 /** 718 * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional 719 * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable 720 * LevelListDrawable}. 721 * 722 * @param icon A resource ID in the application's package of the drawble to use. 723 * @param level The level to use for the icon. 724 * 725 * @see android.graphics.drawable.LevelListDrawable 726 */ 727 public Builder setSmallIcon(int icon, int level) { 728 mNotification.icon = icon; 729 mNotification.iconLevel = level; 730 return this; 731 } 732 733 /** 734 * Set the title (first row) of the notification, in a standard notification. 735 */ 736 public Builder setContentTitle(CharSequence title) { 737 mContentTitle = title; 738 return this; 739 } 740 741 /** 742 * Set the text (second row) of the notification, in a standard notification. 743 */ 744 public Builder setContentText(CharSequence text) { 745 mContentText = text; 746 return this; 747 } 748 749 /** 750 * Set the third line of text in the platform notification template. 751 * Don't use if you're also using {@link #setProgress(int, int, boolean)}; 752 * they occupy the same location in the standard template. 753 * <br> 754 * If the platform does not provide large-format notifications, this method has no effect. 755 * The third line of text only appears in expanded view. 756 * <br> 757 */ 758 public Builder setSubText(CharSequence text) { 759 mSubText = text; 760 return this; 761 } 762 763 /** 764 * Set the large number at the right-hand side of the notification. This is 765 * equivalent to setContentInfo, although it might show the number in a different 766 * font size for readability. 767 */ 768 public Builder setNumber(int number) { 769 mNumber = number; 770 return this; 771 } 772 773 /** 774 * Set the large text at the right-hand side of the notification. 775 */ 776 public Builder setContentInfo(CharSequence info) { 777 mContentInfo = info; 778 return this; 779 } 780 781 /** 782 * Set the progress this notification represents, which may be 783 * represented as a {@link android.widget.ProgressBar}. 784 */ 785 public Builder setProgress(int max, int progress, boolean indeterminate) { 786 mProgressMax = max; 787 mProgress = progress; 788 mProgressIndeterminate = indeterminate; 789 return this; 790 } 791 792 /** 793 * Supply a custom RemoteViews to use instead of the standard one. 794 */ 795 public Builder setContent(RemoteViews views) { 796 mNotification.contentView = views; 797 return this; 798 } 799 800 /** 801 * Supply a {@link PendingIntent} to send when the notification is clicked. 802 * If you do not supply an intent, you can now add PendingIntents to individual 803 * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent 804 * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to 805 * read {@link Notification#contentIntent Notification.contentIntent} for 806 * how to correctly use this. 807 */ 808 public Builder setContentIntent(PendingIntent intent) { 809 mContentIntent = intent; 810 return this; 811 } 812 813 /** 814 * Supply a {@link PendingIntent} to send when the notification is cleared by the user 815 * directly from the notification panel. For example, this intent is sent when the user 816 * clicks the "Clear all" button, or the individual "X" buttons on notifications. This 817 * intent is not sent when the application calls 818 * {@link android.app.NotificationManager#cancel NotificationManager.cancel(int)}. 819 */ 820 public Builder setDeleteIntent(PendingIntent intent) { 821 mNotification.deleteIntent = intent; 822 return this; 823 } 824 825 /** 826 * An intent to launch instead of posting the notification to the status bar. 827 * Only for use with extremely high-priority notifications demanding the user's 828 * <strong>immediate</strong> attention, such as an incoming phone call or 829 * alarm clock that the user has explicitly set to a particular time. 830 * If this facility is used for something else, please give the user an option 831 * to turn it off and use a normal notification, as this can be extremely 832 * disruptive. 833 * 834 * @param intent The pending intent to launch. 835 * @param highPriority Passing true will cause this notification to be sent 836 * even if other notifications are suppressed. 837 */ 838 public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { 839 mFullScreenIntent = intent; 840 setFlag(FLAG_HIGH_PRIORITY, highPriority); 841 return this; 842 } 843 844 /** 845 * Set the text that is displayed in the status bar when the notification first 846 * arrives. 847 */ 848 public Builder setTicker(CharSequence tickerText) { 849 mNotification.tickerText = tickerText; 850 return this; 851 } 852 853 /** 854 * Set the text that is displayed in the status bar when the notification first 855 * arrives, and also a RemoteViews object that may be displayed instead on some 856 * devices. 857 */ 858 public Builder setTicker(CharSequence tickerText, RemoteViews views) { 859 mNotification.tickerText = tickerText; 860 mTickerView = views; 861 return this; 862 } 863 864 /** 865 * Set the large icon that is shown in the ticker and notification. 866 */ 867 public Builder setLargeIcon(Bitmap icon) { 868 mLargeIcon = icon; 869 return this; 870 } 871 872 /** 873 * Set the sound to play. It will play on the default stream. 874 */ 875 public Builder setSound(Uri sound) { 876 mNotification.sound = sound; 877 mNotification.audioStreamType = Notification.STREAM_DEFAULT; 878 return this; 879 } 880 881 /** 882 * Set the sound to play. It will play on the stream you supply. 883 * 884 * @see Notification#STREAM_DEFAULT 885 * @see AudioManager for the <code>STREAM_</code> constants. 886 */ 887 public Builder setSound(Uri sound, int streamType) { 888 mNotification.sound = sound; 889 mNotification.audioStreamType = streamType; 890 return this; 891 } 892 893 /** 894 * Set the vibration pattern to use. 895 * 896 * @see android.os.Vibrator for a discussion of the <code>pattern</code> 897 * parameter. 898 */ 899 public Builder setVibrate(long[] pattern) { 900 mNotification.vibrate = pattern; 901 return this; 902 } 903 904 /** 905 * Set the argb value that you would like the LED on the device to blnk, as well as the 906 * rate. The rate is specified in terms of the number of milliseconds to be on 907 * and then the number of milliseconds to be off. 908 */ 909 public Builder setLights(int argb, int onMs, int offMs) { 910 mNotification.ledARGB = argb; 911 mNotification.ledOnMS = onMs; 912 mNotification.ledOffMS = offMs; 913 boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0; 914 mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) | 915 (showLights ? Notification.FLAG_SHOW_LIGHTS : 0); 916 return this; 917 } 918 919 /** 920 * Set whether this is an ongoing notification. 921 * 922 * <p>Ongoing notifications differ from regular notifications in the following ways: 923 * <ul> 924 * <li>Ongoing notifications are sorted above the regular notifications in the 925 * notification panel.</li> 926 * <li>Ongoing notifications do not have an 'X' close button, and are not affected 927 * by the "Clear all" button. 928 * </ul> 929 */ 930 public Builder setOngoing(boolean ongoing) { 931 setFlag(Notification.FLAG_ONGOING_EVENT, ongoing); 932 return this; 933 } 934 935 /** 936 * Set this flag if you would only like the sound, vibrate 937 * and ticker to be played if the notification is not already showing. 938 */ 939 public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { 940 setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); 941 return this; 942 } 943 944 /** 945 * Setting this flag will make it so the notification is automatically 946 * canceled when the user clicks it in the panel. The PendingIntent 947 * set with {@link #setDeleteIntent} will be broadcast when the notification 948 * is canceled. 949 */ 950 public Builder setAutoCancel(boolean autoCancel) { 951 setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel); 952 return this; 953 } 954 955 /** 956 * Set whether or not this notification is only relevant to the current device. 957 * 958 * <p>Some notifications can be bridged to other devices for remote display. 959 * This hint can be set to recommend this notification not be bridged. 960 */ 961 public Builder setLocalOnly(boolean b) { 962 mLocalOnly = b; 963 return this; 964 } 965 966 /** 967 * Set the notification category. 968 * 969 * <p>Must be one of the predefined notification categories (see the <code>CATEGORY_*</code> 970 * constants in {@link Notification}) that best describes this notification. 971 * May be used by the system for ranking and filtering. 972 */ 973 public Builder setCategory(String category) { 974 mCategory = category; 975 return this; 976 } 977 978 /** 979 * Set the default notification options that will be used. 980 * <p> 981 * The value should be one or more of the following fields combined with 982 * bitwise-or: 983 * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE}, 984 * {@link Notification#DEFAULT_LIGHTS}. 985 * <p> 986 * For all default values, use {@link Notification#DEFAULT_ALL}. 987 */ 988 public Builder setDefaults(int defaults) { 989 mNotification.defaults = defaults; 990 if ((defaults & Notification.DEFAULT_LIGHTS) != 0) { 991 mNotification.flags |= Notification.FLAG_SHOW_LIGHTS; 992 } 993 return this; 994 } 995 996 private void setFlag(int mask, boolean value) { 997 if (value) { 998 mNotification.flags |= mask; 999 } else { 1000 mNotification.flags &= ~mask; 1001 } 1002 } 1003 1004 /** 1005 * Set the relative priority for this notification. 1006 * 1007 * Priority is an indication of how much of the user's 1008 * valuable attention should be consumed by this 1009 * notification. Low-priority notifications may be hidden from 1010 * the user in certain situations, while the user might be 1011 * interrupted for a higher-priority notification. 1012 * The system sets a notification's priority based on various factors including the 1013 * setPriority value. The effect may differ slightly on different platforms. 1014 * 1015 * @param pri Relative priority for this notification. Must be one of 1016 * the priority constants defined by {@link NotificationCompat}. 1017 * Acceptable values range from {@link 1018 * NotificationCompat#PRIORITY_MIN} (-2) to {@link 1019 * NotificationCompat#PRIORITY_MAX} (2). 1020 */ 1021 public Builder setPriority(int pri) { 1022 mPriority = pri; 1023 return this; 1024 } 1025 1026 /** 1027 * Add a person that is relevant to this notification. 1028 * 1029 * @see Notification#EXTRA_PEOPLE 1030 */ 1031 public Builder addPerson(String handle) { 1032 mPeople.add(handle); 1033 return this; 1034 } 1035 1036 /** 1037 * Set this notification to be part of a group of notifications sharing the same key. 1038 * Grouped notifications may display in a cluster or stack on devices which 1039 * support such rendering. 1040 * 1041 * <p>To make this notification the summary for its group, also call 1042 * {@link #setGroupSummary}. A sort order can be specified for group members by using 1043 * {@link #setSortKey}. 1044 * @param groupKey The group key of the group. 1045 * @return this object for method chaining 1046 */ 1047 public Builder setGroup(String groupKey) { 1048 mGroupKey = groupKey; 1049 return this; 1050 } 1051 1052 /** 1053 * Set this notification to be the group summary for a group of notifications. 1054 * Grouped notifications may display in a cluster or stack on devices which 1055 * support such rendering. Requires a group key also be set using {@link #setGroup}. 1056 * @param isGroupSummary Whether this notification should be a group summary. 1057 * @return this object for method chaining 1058 */ 1059 public Builder setGroupSummary(boolean isGroupSummary) { 1060 mGroupSummary = isGroupSummary; 1061 return this; 1062 } 1063 1064 /** 1065 * Set a sort key that orders this notification among other notifications from the 1066 * same package. This can be useful if an external sort was already applied and an app 1067 * would like to preserve this. Notifications will be sorted lexicographically using this 1068 * value, although providing different priorities in addition to providing sort key may 1069 * cause this value to be ignored. 1070 * 1071 * <p>This sort key can also be used to order members of a notification group. See 1072 * {@link Builder#setGroup}. 1073 * 1074 * @see String#compareTo(String) 1075 */ 1076 public Builder setSortKey(String sortKey) { 1077 mSortKey = sortKey; 1078 return this; 1079 } 1080 1081 /** 1082 * Merge additional metadata into this notification. 1083 * 1084 * <p>Values within the Bundle will replace existing extras values in this Builder. 1085 * 1086 * @see Notification#extras 1087 */ 1088 public Builder addExtras(Bundle extras) { 1089 if (extras != null) { 1090 if (mExtras == null) { 1091 mExtras = new Bundle(extras); 1092 } else { 1093 mExtras.putAll(extras); 1094 } 1095 } 1096 return this; 1097 } 1098 1099 /** 1100 * Set metadata for this notification. 1101 * 1102 * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's 1103 * current contents are copied into the Notification each time {@link #build()} is 1104 * called. 1105 * 1106 * <p>Replaces any existing extras values with those from the provided Bundle. 1107 * Use {@link #addExtras} to merge in metadata instead. 1108 * 1109 * @see Notification#extras 1110 */ 1111 public Builder setExtras(Bundle extras) { 1112 mExtras = extras; 1113 return this; 1114 } 1115 1116 /** 1117 * Get the current metadata Bundle used by this notification Builder. 1118 * 1119 * <p>The returned Bundle is shared with this Builder. 1120 * 1121 * <p>The current contents of this Bundle are copied into the Notification each time 1122 * {@link #build()} is called. 1123 * 1124 * @see Notification#extras 1125 */ 1126 public Bundle getExtras() { 1127 if (mExtras == null) { 1128 mExtras = new Bundle(); 1129 } 1130 return mExtras; 1131 } 1132 1133 /** 1134 * Add an action to this notification. Actions are typically displayed by 1135 * the system as a button adjacent to the notification content. 1136 * <br> 1137 * Action buttons won't appear on platforms prior to Android 4.1. Action 1138 * buttons depend on expanded notifications, which are only available in Android 4.1 1139 * and later. To ensure that an action button's functionality is always available, first 1140 * implement the functionality in the {@link android.app.Activity} that starts when a user 1141 * clicks the notification (see {@link #setContentIntent setContentIntent()}), and then 1142 * enhance the notification by implementing the same functionality with 1143 * {@link #addAction addAction()}. 1144 * 1145 * @param icon Resource ID of a drawable that represents the action. 1146 * @param title Text describing the action. 1147 * @param intent {@link android.app.PendingIntent} to be fired when the action is invoked. 1148 */ 1149 public Builder addAction(int icon, CharSequence title, PendingIntent intent) { 1150 mActions.add(new Action(icon, title, intent)); 1151 return this; 1152 } 1153 1154 /** 1155 * Add an action to this notification. Actions are typically displayed by 1156 * the system as a button adjacent to the notification content. 1157 * <br> 1158 * Action buttons won't appear on platforms prior to Android 4.1. Action 1159 * buttons depend on expanded notifications, which are only available in Android 4.1 1160 * and later. To ensure that an action button's functionality is always available, first 1161 * implement the functionality in the {@link android.app.Activity} that starts when a user 1162 * clicks the notification (see {@link #setContentIntent setContentIntent()}), and then 1163 * enhance the notification by implementing the same functionality with 1164 * {@link #addAction addAction()}. 1165 * 1166 * @param action The action to add. 1167 */ 1168 public Builder addAction(Action action) { 1169 mActions.add(action); 1170 return this; 1171 } 1172 1173 /** 1174 * Add a rich notification style to be applied at build time. 1175 * <br> 1176 * If the platform does not provide rich notification styles, this method has no effect. The 1177 * user will always see the normal notification style. 1178 * 1179 * @param style Object responsible for modifying the notification style. 1180 */ 1181 public Builder setStyle(Style style) { 1182 if (mStyle != style) { 1183 mStyle = style; 1184 if (mStyle != null) { 1185 mStyle.setBuilder(this); 1186 } 1187 } 1188 return this; 1189 } 1190 1191 /** 1192 * Sets {@link Notification#color}. 1193 * 1194 * @param argb The accent color to use 1195 * 1196 * @return The same Builder. 1197 */ 1198 public Builder setColor(int argb) { 1199 mColor = argb; 1200 return this; 1201 } 1202 1203 /** 1204 * Sets {@link Notification#visibility}. 1205 * 1206 * @param visibility One of {@link Notification#VISIBILITY_PRIVATE} (the default), 1207 * {@link Notification#VISIBILITY_PUBLIC}, or 1208 * {@link Notification#VISIBILITY_SECRET}. 1209 */ 1210 public Builder setVisibility(int visibility) { 1211 mVisibility = visibility; 1212 return this; 1213 } 1214 1215 /** 1216 * Supply a replacement Notification whose contents should be shown in insecure contexts 1217 * (i.e. atop the secure lockscreen). See {@link Notification#visibility} and 1218 * {@link #VISIBILITY_PUBLIC}. 1219 * 1220 * @param n A replacement notification, presumably with some or all info redacted. 1221 * @return The same Builder. 1222 */ 1223 public Builder setPublicVersion(Notification n) { 1224 mPublicVersion = n; 1225 return this; 1226 } 1227 1228 /** 1229 * Apply an extender to this notification builder. Extenders may be used to add 1230 * metadata or change options on this builder. 1231 */ 1232 public Builder apply(Extender extender) { 1233 extender.applyTo(this); 1234 return this; 1235 } 1236 1237 /** 1238 * Extender interface for use with {@link #apply}. Extenders may be used to add 1239 * metadata or change options on this builder. 1240 */ 1241 public interface Extender { 1242 /** 1243 * Apply this extender to a notification builder. 1244 * @param builder the builder to be modified. 1245 * @return the build object for chaining. 1246 */ 1247 public Builder applyTo(Builder builder); 1248 } 1249 1250 /** 1251 * @deprecated Use {@link #build()} instead. 1252 */ 1253 @Deprecated 1254 public Notification getNotification() { 1255 return IMPL.build(this); 1256 } 1257 1258 /** 1259 * Combine all of the options that have been set and return a new {@link Notification} 1260 * object. 1261 */ 1262 public Notification build() { 1263 return IMPL.build(this); 1264 } 1265 } 1266 1267 /** 1268 * An object that can apply a rich notification style to a {@link Notification.Builder} 1269 * object. 1270 * <br> 1271 * If the platform does not provide rich notification styles, methods in this class have no 1272 * effect. 1273 */ 1274 public static abstract class Style { 1275 Builder mBuilder; 1276 CharSequence mBigContentTitle; 1277 CharSequence mSummaryText; 1278 boolean mSummaryTextSet = false; 1279 1280 public void setBuilder(Builder builder) { 1281 if (mBuilder != builder) { 1282 mBuilder = builder; 1283 if (mBuilder != null) { 1284 mBuilder.setStyle(this); 1285 } 1286 } 1287 } 1288 1289 public Notification build() { 1290 Notification notification = null; 1291 if (mBuilder != null) { 1292 notification = mBuilder.build(); 1293 } 1294 return notification; 1295 } 1296 } 1297 1298 /** 1299 * Helper class for generating large-format notifications that include a large image attachment. 1300 * <br> 1301 * If the platform does not provide large-format notifications, this method has no effect. The 1302 * user will always see the normal notification view. 1303 * <br> 1304 * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: 1305 * <pre class="prettyprint"> 1306 * Notification noti = new Notification.Builder() 1307 * .setContentTitle("New photo from " + sender.toString()) 1308 * .setContentText(subject) 1309 * .setSmallIcon(R.drawable.new_post) 1310 * .setLargeIcon(aBitmap) 1311 * .setStyle(new Notification.BigPictureStyle() 1312 * .bigPicture(aBigBitmap)) 1313 * .build(); 1314 * </pre> 1315 * 1316 * @see Notification#bigContentView 1317 */ 1318 public static class BigPictureStyle extends Style { 1319 Bitmap mPicture; 1320 Bitmap mBigLargeIcon; 1321 boolean mBigLargeIconSet; 1322 1323 public BigPictureStyle() { 1324 } 1325 1326 public BigPictureStyle(Builder builder) { 1327 setBuilder(builder); 1328 } 1329 1330 /** 1331 * Overrides ContentTitle in the big form of the template. 1332 * This defaults to the value passed to setContentTitle(). 1333 */ 1334 public BigPictureStyle setBigContentTitle(CharSequence title) { 1335 mBigContentTitle = title; 1336 return this; 1337 } 1338 1339 /** 1340 * Set the first line of text after the detail section in the big form of the template. 1341 */ 1342 public BigPictureStyle setSummaryText(CharSequence cs) { 1343 mSummaryText = cs; 1344 mSummaryTextSet = true; 1345 return this; 1346 } 1347 1348 /** 1349 * Provide the bitmap to be used as the payload for the BigPicture notification. 1350 */ 1351 public BigPictureStyle bigPicture(Bitmap b) { 1352 mPicture = b; 1353 return this; 1354 } 1355 1356 /** 1357 * Override the large icon when the big notification is shown. 1358 */ 1359 public BigPictureStyle bigLargeIcon(Bitmap b) { 1360 mBigLargeIcon = b; 1361 mBigLargeIconSet = true; 1362 return this; 1363 } 1364 } 1365 1366 /** 1367 * Helper class for generating large-format notifications that include a lot of text. 1368 * 1369 * <br> 1370 * If the platform does not provide large-format notifications, this method has no effect. The 1371 * user will always see the normal notification view. 1372 * <br> 1373 * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: 1374 * <pre class="prettyprint"> 1375 * Notification noti = new Notification.Builder() 1376 * .setContentTitle("New mail from " + sender.toString()) 1377 * .setContentText(subject) 1378 * .setSmallIcon(R.drawable.new_mail) 1379 * .setLargeIcon(aBitmap) 1380 * .setStyle(new Notification.BigTextStyle() 1381 * .bigText(aVeryLongString)) 1382 * .build(); 1383 * </pre> 1384 * 1385 * @see Notification#bigContentView 1386 */ 1387 public static class BigTextStyle extends Style { 1388 CharSequence mBigText; 1389 1390 public BigTextStyle() { 1391 } 1392 1393 public BigTextStyle(Builder builder) { 1394 setBuilder(builder); 1395 } 1396 1397 /** 1398 * Overrides ContentTitle in the big form of the template. 1399 * This defaults to the value passed to setContentTitle(). 1400 */ 1401 public BigTextStyle setBigContentTitle(CharSequence title) { 1402 mBigContentTitle = title; 1403 return this; 1404 } 1405 1406 /** 1407 * Set the first line of text after the detail section in the big form of the template. 1408 */ 1409 public BigTextStyle setSummaryText(CharSequence cs) { 1410 mSummaryText = cs; 1411 mSummaryTextSet = true; 1412 return this; 1413 } 1414 1415 /** 1416 * Provide the longer text to be displayed in the big form of the 1417 * template in place of the content text. 1418 */ 1419 public BigTextStyle bigText(CharSequence cs) { 1420 mBigText = cs; 1421 return this; 1422 } 1423 } 1424 1425 /** 1426 * Helper class for generating large-format notifications that include a list of (up to 5) strings. 1427 * 1428 * <br> 1429 * If the platform does not provide large-format notifications, this method has no effect. The 1430 * user will always see the normal notification view. 1431 * <br> 1432 * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: 1433 * <pre class="prettyprint"> 1434 * Notification noti = new Notification.Builder() 1435 * .setContentTitle("5 New mails from " + sender.toString()) 1436 * .setContentText(subject) 1437 * .setSmallIcon(R.drawable.new_mail) 1438 * .setLargeIcon(aBitmap) 1439 * .setStyle(new Notification.InboxStyle() 1440 * .addLine(str1) 1441 * .addLine(str2) 1442 * .setContentTitle("") 1443 * .setSummaryText("+3 more")) 1444 * .build(); 1445 * </pre> 1446 * 1447 * @see Notification#bigContentView 1448 */ 1449 public static class InboxStyle extends Style { 1450 ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>(); 1451 1452 public InboxStyle() { 1453 } 1454 1455 public InboxStyle(Builder builder) { 1456 setBuilder(builder); 1457 } 1458 1459 /** 1460 * Overrides ContentTitle in the big form of the template. 1461 * This defaults to the value passed to setContentTitle(). 1462 */ 1463 public InboxStyle setBigContentTitle(CharSequence title) { 1464 mBigContentTitle = title; 1465 return this; 1466 } 1467 1468 /** 1469 * Set the first line of text after the detail section in the big form of the template. 1470 */ 1471 public InboxStyle setSummaryText(CharSequence cs) { 1472 mSummaryText = cs; 1473 mSummaryTextSet = true; 1474 return this; 1475 } 1476 1477 /** 1478 * Append a line to the digest section of the Inbox notification. 1479 */ 1480 public InboxStyle addLine(CharSequence cs) { 1481 mTexts.add(cs); 1482 return this; 1483 } 1484 } 1485 1486 /** 1487 * Structure to encapsulate a named action that can be shown as part of this notification. 1488 * It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is 1489 * selected by the user. Action buttons won't appear on platforms prior to Android 4.1. 1490 * <p> 1491 * Apps should use {@link NotificationCompat.Builder#addAction(int, CharSequence, PendingIntent)} 1492 * or {@link NotificationCompat.Builder#addAction(NotificationCompat.Action)} 1493 * to attach actions. 1494 */ 1495 public static class Action extends NotificationCompatBase.Action { 1496 private final Bundle mExtras; 1497 private RemoteInput[] mRemoteInputs; 1498 1499 /** 1500 * Small icon representing the action. 1501 */ 1502 public int icon; 1503 /** 1504 * Title of the action. 1505 */ 1506 public CharSequence title; 1507 /** 1508 * Intent to send when the user invokes this action. May be null, in which case the action 1509 * may be rendered in a disabled presentation. 1510 */ 1511 public PendingIntent actionIntent; 1512 1513 public Action(int icon, CharSequence title, PendingIntent intent) { 1514 this(icon, title, intent, new Bundle(), null); 1515 } 1516 1517 private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras, 1518 RemoteInput[] remoteInputs) { 1519 this.icon = icon; 1520 this.title = title; 1521 this.actionIntent = intent; 1522 this.mExtras = extras != null ? extras : new Bundle(); 1523 this.mRemoteInputs = remoteInputs; 1524 } 1525 1526 @Override 1527 protected int getIcon() { 1528 return icon; 1529 } 1530 1531 @Override 1532 protected CharSequence getTitle() { 1533 return title; 1534 } 1535 1536 @Override 1537 protected PendingIntent getActionIntent() { 1538 return actionIntent; 1539 } 1540 1541 /** 1542 * Get additional metadata carried around with this Action. 1543 */ 1544 public Bundle getExtras() { 1545 return mExtras; 1546 } 1547 1548 /** 1549 * Get the list of inputs to be collected from the user when this action is sent. 1550 * May return null if no remote inputs were added. 1551 */ 1552 public RemoteInput[] getRemoteInputs() { 1553 return mRemoteInputs; 1554 } 1555 1556 /** 1557 * Builder class for {@link Action} objects. 1558 */ 1559 public static final class Builder { 1560 private final int mIcon; 1561 private final CharSequence mTitle; 1562 private final PendingIntent mIntent; 1563 private final Bundle mExtras; 1564 private ArrayList<RemoteInput> mRemoteInputs; 1565 1566 /** 1567 * Construct a new builder for {@link Action} object. 1568 * @param icon icon to show for this action 1569 * @param title the title of the action 1570 * @param intent the {@link PendingIntent} to fire when users trigger this action 1571 */ 1572 public Builder(int icon, CharSequence title, PendingIntent intent) { 1573 this(icon, title, intent, new Bundle()); 1574 } 1575 1576 /** 1577 * Construct a new builder for {@link Action} object using the fields from an 1578 * {@link Action}. 1579 * @param action the action to read fields from. 1580 */ 1581 public Builder(Action action) { 1582 this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras)); 1583 } 1584 1585 private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) { 1586 mIcon = icon; 1587 mTitle = title; 1588 mIntent = intent; 1589 mExtras = extras; 1590 } 1591 1592 /** 1593 * Merge additional metadata into this builder. 1594 * 1595 * <p>Values within the Bundle will replace existing extras values in this Builder. 1596 * 1597 * @see NotificationCompat.Action#getExtras 1598 */ 1599 public Builder addExtras(Bundle extras) { 1600 if (extras != null) { 1601 mExtras.putAll(extras); 1602 } 1603 return this; 1604 } 1605 1606 /** 1607 * Get the metadata Bundle used by this Builder. 1608 * 1609 * <p>The returned Bundle is shared with this Builder. 1610 */ 1611 public Bundle getExtras() { 1612 return mExtras; 1613 } 1614 1615 /** 1616 * Add an input to be collected from the user when this action is sent. 1617 * Response values can be retrieved from the fired intent by using the 1618 * {@link RemoteInput#getResultsFromIntent} function. 1619 * @param remoteInput a {@link RemoteInput} to add to the action 1620 * @return this object for method chaining 1621 */ 1622 public Builder addRemoteInput(RemoteInput remoteInput) { 1623 if (mRemoteInputs == null) { 1624 mRemoteInputs = new ArrayList<RemoteInput>(); 1625 } 1626 mRemoteInputs.add(remoteInput); 1627 return this; 1628 } 1629 1630 /** 1631 * Apply an extender to this action builder. Extenders may be used to add 1632 * metadata or change options on this builder. 1633 */ 1634 public Builder apply(Extender extender) { 1635 extender.applyTo(this); 1636 return this; 1637 } 1638 1639 /** 1640 * Extender interface for use with {@link #apply}. Extenders may be used to add 1641 * metadata or change options on this builder. 1642 */ 1643 public interface Extender { 1644 /** 1645 * Apply this extender to a notification action builder. 1646 * @param builder the builder to be modified. 1647 * @return the build object for chaining. 1648 */ 1649 public Builder applyTo(Builder builder); 1650 } 1651 1652 /** 1653 * Combine all of the options that have been set and return a new {@link Action} 1654 * object. 1655 * @return the built action 1656 */ 1657 public Action build() { 1658 RemoteInput[] remoteInputs = mRemoteInputs != null 1659 ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null; 1660 return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs); 1661 } 1662 } 1663 1664 /** @hide */ 1665 public static final Factory FACTORY = new Factory() { 1666 @Override 1667 public Action build(int icon, CharSequence title, 1668 PendingIntent actionIntent, Bundle extras, 1669 RemoteInputCompatBase.RemoteInput[] remoteInputs) { 1670 return new Action(icon, title, actionIntent, extras, 1671 (RemoteInput[]) remoteInputs); 1672 } 1673 1674 @Override 1675 public Action[] newArray(int length) { 1676 return new Action[length]; 1677 } 1678 }; 1679 } 1680 1681 /** 1682 * Gets the {@link Notification#extras} field from a notification in a backwards 1683 * compatible manner. Extras field was supported from JellyBean (Api level 16) 1684 * forwards. This function will return null on older api levels. 1685 */ 1686 public static Bundle getExtras(Notification notif) { 1687 return IMPL.getExtras(notif); 1688 } 1689 1690 /** 1691 * Get the number of actions in this notification in a backwards compatible 1692 * manner. Actions were supported from JellyBean (Api level 16) forwards. 1693 */ 1694 public static int getActionCount(Notification notif) { 1695 return IMPL.getActionCount(notif); 1696 } 1697 1698 /** 1699 * Get an action on this notification in a backwards compatible 1700 * manner. Actions were supported from JellyBean (Api level 16) forwards. 1701 * @param notif The notification to inspect. 1702 * @param actionIndex The index of the action to retrieve. 1703 */ 1704 public static Action getAction(Notification notif, int actionIndex) { 1705 return IMPL.getAction(notif, actionIndex); 1706 } 1707 1708 /** 1709 * Get whether or not this notification is only relevant to the current device. 1710 * 1711 * <p>Some notifications can be bridged to other devices for remote display. 1712 * If this hint is set, it is recommend that this notification not be bridged. 1713 */ 1714 public static boolean getLocalOnly(Notification notif) { 1715 return IMPL.getLocalOnly(notif); 1716 } 1717 1718 /** 1719 * Get the key used to group this notification into a cluster or stack 1720 * with other notifications on devices which support such rendering. 1721 */ 1722 public static String getGroup(Notification notif) { 1723 return IMPL.getGroup(notif); 1724 } 1725 1726 /** 1727 * Get whether this notification to be the group summary for a group of notifications. 1728 * Grouped notifications may display in a cluster or stack on devices which 1729 * support such rendering. Requires a group key also be set using {@link Builder#setGroup}. 1730 * @return Whether this notification is a group summary. 1731 */ 1732 public static boolean isGroupSummary(Notification notif) { 1733 return IMPL.isGroupSummary(notif); 1734 } 1735 1736 /** 1737 * Get a sort key that orders this notification among other notifications from the 1738 * same package. This can be useful if an external sort was already applied and an app 1739 * would like to preserve this. Notifications will be sorted lexicographically using this 1740 * value, although providing different priorities in addition to providing sort key may 1741 * cause this value to be ignored. 1742 * 1743 * <p>This sort key can also be used to order members of a notification group. See 1744 * {@link Builder#setGroup}. 1745 * 1746 * @see String#compareTo(String) 1747 */ 1748 public static String getSortKey(Notification notif) { 1749 return IMPL.getSortKey(notif); 1750 } 1751} 1752