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