NotificationCompat.java revision 2e275ce7680eafd02423e8aad7f044aa90ded89c
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.NotificationManager; 21import android.app.PendingIntent; 22import android.content.Context; 23import android.graphics.Bitmap; 24import android.media.AudioManager; 25import android.net.Uri; 26import android.os.Build; 27import android.os.Bundle; 28import android.widget.RemoteViews; 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 * Obsolete flag indicating high-priority notifications; use the priority field instead. 38 * 39 * @deprecated Use {@link NotificationCompat.Builder#setPriority(int)} with a positive value. 40 */ 41 public static final int FLAG_HIGH_PRIORITY = 0x00000080; 42 43 /** 44 * Default notification priority for {@link NotificationCompat.Builder#setPriority(int)}. 45 * If your application does not prioritize its own notifications, 46 * use this value for all notifications. 47 */ 48 public static final int PRIORITY_DEFAULT = 0; 49 50 /** 51 * Lower notification priority for {@link NotificationCompat.Builder#setPriority(int)}, 52 * for items that are less important. The UI may choose to show 53 * these items smaller, or at a different position in the list, 54 * compared with your app's {@link #PRIORITY_DEFAULT} items. 55 */ 56 public static final int PRIORITY_LOW = -1; 57 58 /** 59 * Lowest notification priority for {@link NotificationCompat.Builder#setPriority(int)}; 60 * these items might not be shown to the user except under 61 * special circumstances, such as detailed notification logs. 62 */ 63 public static final int PRIORITY_MIN = -2; 64 65 /** 66 * Higher notification priority for {@link NotificationCompat.Builder#setPriority(int)}, 67 * for more important notifications or alerts. The UI may choose 68 * to show these items larger, or at a different position in 69 * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items. 70 */ 71 public static final int PRIORITY_HIGH = 1; 72 73 /** 74 * Highest notification priority for {@link NotificationCompat.Builder#setPriority(int)}, 75 * for your application's most important items that require the user's 76 * prompt attention or input. 77 */ 78 public static final int PRIORITY_MAX = 2; 79 80 private static final NotificationCompatImpl IMPL; 81 82 interface NotificationCompatImpl { 83 public Notification build(Builder b); 84 public Bundle getExtras(Notification n); 85 public boolean getLocalOnly(Notification n); 86 } 87 88 static class NotificationCompatImplBase implements NotificationCompatImpl { 89 @Override 90 public Notification build(Builder b) { 91 Notification result = b.mNotification; 92 result.setLatestEventInfo(b.mContext, b.mContentTitle, 93 b.mContentText, b.mContentIntent); 94 // translate high priority requests into legacy flag 95 if (b.mPriority > PRIORITY_DEFAULT) { 96 result.flags |= FLAG_HIGH_PRIORITY; 97 } 98 return result; 99 } 100 101 @Override 102 public Bundle getExtras(Notification n) { 103 return null; 104 } 105 106 @Override 107 public boolean getLocalOnly(Notification n) { 108 return false; 109 } 110 } 111 112 static class NotificationCompatImplGingerbread extends NotificationCompatImplBase { 113 @Override 114 public Notification build(Builder b) { 115 Notification result = b.mNotification; 116 result.setLatestEventInfo(b.mContext, b.mContentTitle, 117 b.mContentText, b.mContentIntent); 118 result = NotificationCompatGingerbread.add(result, b.mContext, 119 b.mContentTitle, b.mContentText, b.mContentIntent, b.mFullScreenIntent); 120 // translate high priority requests into legacy flag 121 if (b.mPriority > PRIORITY_DEFAULT) { 122 result.flags |= FLAG_HIGH_PRIORITY; 123 } 124 return result; 125 } 126 } 127 128 static class NotificationCompatImplHoneycomb extends NotificationCompatImplBase { 129 @Override 130 public Notification build(Builder b) { 131 return NotificationCompatHoneycomb.add(b.mContext, b.mNotification, 132 b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, 133 b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon); 134 } 135 } 136 137 static class NotificationCompatImplIceCreamSandwich extends NotificationCompatImplBase { 138 @Override 139 public Notification build(Builder b) { 140 return NotificationCompatIceCreamSandwich.add(b.mContext, b.mNotification, 141 b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, 142 b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 143 b.mProgressMax, b.mProgress, b.mProgressIndeterminate); 144 } 145 } 146 147 static class NotificationCompatImplJellybean extends NotificationCompatImplBase { 148 @Override 149 public Notification build(Builder b) { 150 NotificationCompatJellybean.Builder builder = new NotificationCompatJellybean.Builder( 151 b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, 152 b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 153 b.mProgressMax, b.mProgress, b.mProgressIndeterminate, 154 b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras); 155 addActionsToBuilder(builder, b.mActions); 156 addStyleToBuilderJellybean(builder, b.mStyle); 157 return builder.build(); 158 } 159 160 @Override 161 public Bundle getExtras(Notification n) { 162 return NotificationCompatJellybean.getExtras(n); 163 } 164 165 @Override 166 public boolean getLocalOnly(Notification n) { 167 return NotificationCompatJellybean.getLocalOnly(n); 168 } 169 } 170 171 static class NotificationCompatImplKitKat extends NotificationCompatImplBase { 172 @Override 173 public Notification build(Builder b) { 174 NotificationCompatKitKat.Builder builder = new NotificationCompatKitKat.Builder( 175 b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, 176 b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 177 b.mProgressMax, b.mProgress, b.mProgressIndeterminate, 178 b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras); 179 addActionsToBuilder(builder, b.mActions); 180 addStyleToBuilderJellybean(builder, b.mStyle); 181 return builder.build(); 182 } 183 184 @Override 185 public Bundle getExtras(Notification n) { 186 return NotificationCompatKitKat.getExtras(n); 187 } 188 189 @Override 190 public boolean getLocalOnly(Notification n) { 191 return NotificationCompatKitKat.getLocalOnly(n); 192 } 193 } 194 195 static class NotificationCompatImplApi20 extends NotificationCompatImplBase { 196 @Override 197 public Notification build(Builder b) { 198 NotificationCompatApi20.Builder builder = new NotificationCompatApi20.Builder( 199 b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, 200 b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, 201 b.mProgressMax, b.mProgress, b.mProgressIndeterminate, 202 b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory, 203 b.mExtras); 204 addActionsToBuilder(builder, b.mActions); 205 addStyleToBuilderJellybean(builder, b.mStyle); 206 return builder.build(); 207 } 208 209 @Override 210 public Bundle getExtras(Notification n) { 211 return NotificationCompatKitKat.getExtras(n); 212 } 213 214 @Override 215 public boolean getLocalOnly(Notification n) { 216 return NotificationCompatApi20.getLocalOnly(n); 217 } 218 } 219 220 private static void addActionsToBuilder(NotificationBuilderWithActions builder, 221 ArrayList<Action> actions) { 222 for (Action action : actions) { 223 builder.addAction(action.icon, action.title, action.actionIntent); 224 } 225 } 226 227 private static void addStyleToBuilderJellybean(NotificationBuilderWithBuilderAccessor builder, 228 Style style) { 229 if (style != null) { 230 if (style instanceof BigTextStyle) { 231 BigTextStyle bigTextStyle = (BigTextStyle) style; 232 NotificationCompatJellybean.addBigTextStyle(builder, 233 bigTextStyle.mBigContentTitle, 234 bigTextStyle.mSummaryTextSet, 235 bigTextStyle.mSummaryText, 236 bigTextStyle.mBigText); 237 } else if (style instanceof InboxStyle) { 238 InboxStyle inboxStyle = (InboxStyle) style; 239 NotificationCompatJellybean.addInboxStyle(builder, 240 inboxStyle.mBigContentTitle, 241 inboxStyle.mSummaryTextSet, 242 inboxStyle.mSummaryText, 243 inboxStyle.mTexts); 244 } else if (style instanceof BigPictureStyle) { 245 BigPictureStyle bigPictureStyle = (BigPictureStyle) style; 246 NotificationCompatJellybean.addBigPictureStyle(builder, 247 bigPictureStyle.mBigContentTitle, 248 bigPictureStyle.mSummaryTextSet, 249 bigPictureStyle.mSummaryText, 250 bigPictureStyle.mPicture, 251 bigPictureStyle.mBigLargeIcon, 252 bigPictureStyle.mBigLargeIconSet); 253 } 254 } 255 } 256 257 static { 258 // TODO: Add NotificationCompatApi20 when SDK_INT is incremented. 259 if (Build.VERSION.SDK_INT >= 19) { 260 IMPL = new NotificationCompatImplKitKat(); 261 } else if (Build.VERSION.SDK_INT >= 16) { 262 IMPL = new NotificationCompatImplJellybean(); 263 } else if (Build.VERSION.SDK_INT >= 14) { 264 IMPL = new NotificationCompatImplIceCreamSandwich(); 265 } else if (Build.VERSION.SDK_INT >= 11) { 266 IMPL = new NotificationCompatImplHoneycomb(); 267 } else if (Build.VERSION.SDK_INT >= 9) { 268 IMPL = new NotificationCompatImplGingerbread(); 269 } else { 270 IMPL = new NotificationCompatImplBase(); 271 } 272 } 273 274 /** 275 * Builder class for {@link NotificationCompat} objects. Allows easier control over 276 * all the flags, as well as help constructing the typical notification layouts. 277 * <p> 278 * On platform versions that don't offer expanded notifications, methods that depend on 279 * expanded notifications have no effect. 280 * </p> 281 * <p> 282 * For example, action buttons won't appear on platforms prior to Android 4.1. Action 283 * buttons depend on expanded notifications, which are only available in Android 4.1 284 * and later. 285 * <p> 286 * For this reason, you should always ensure that UI controls in a notification are also 287 * available in an {@link android.app.Activity} in your app, and you should always start that 288 * {@link android.app.Activity} when users click the notification. To do this, use the 289 * {@link NotificationCompat.Builder#setContentIntent setContentIntent()} 290 * method. 291 * </p> 292 * 293 */ 294 public static class Builder { 295 Context mContext; 296 297 CharSequence mContentTitle; 298 CharSequence mContentText; 299 PendingIntent mContentIntent; 300 PendingIntent mFullScreenIntent; 301 RemoteViews mTickerView; 302 Bitmap mLargeIcon; 303 CharSequence mContentInfo; 304 int mNumber; 305 int mPriority; 306 boolean mUseChronometer; 307 Style mStyle; 308 CharSequence mSubText; 309 int mProgressMax; 310 int mProgress; 311 boolean mProgressIndeterminate; 312 ArrayList<Action> mActions = new ArrayList<Action>(); 313 boolean mLocalOnly = false; 314 String mCategory; 315 Bundle mExtras; 316 317 Notification mNotification = new Notification(); 318 319 /** 320 * Constructor. 321 * 322 * Automatically sets the when field to {@link System#currentTimeMillis() 323 * System.currentTimeMillis()} and the audio stream to the 324 * {@link Notification#STREAM_DEFAULT}. 325 * 326 * @param context A {@link Context} that will be used to construct the 327 * RemoteViews. The Context will not be held past the lifetime of this 328 * Builder object. 329 */ 330 public Builder(Context context) { 331 mContext = context; 332 333 // Set defaults to match the defaults of a Notification 334 mNotification.when = System.currentTimeMillis(); 335 mNotification.audioStreamType = Notification.STREAM_DEFAULT; 336 mPriority = PRIORITY_DEFAULT; 337 } 338 339 /** 340 * Set the time that the event occurred. Notifications in the panel are 341 * sorted by this time. 342 */ 343 public Builder setWhen(long when) { 344 mNotification.when = when; 345 return this; 346 } 347 348 /** 349 * Show the {@link Notification#when} field as a stopwatch. 350 * 351 * Instead of presenting <code>when</code> as a timestamp, the notification will show an 352 * automatically updating display of the minutes and seconds since <code>when</code>. 353 * 354 * Useful when showing an elapsed time (like an ongoing phone call). 355 * 356 * @see android.widget.Chronometer 357 * @see Notification#when 358 */ 359 public Builder setUsesChronometer(boolean b) { 360 mUseChronometer = b; 361 return this; 362 } 363 364 /** 365 * Set the small icon to use in the notification layouts. Different classes of devices 366 * may return different sizes. See the UX guidelines for more information on how to 367 * design these icons. 368 * 369 * @param icon A resource ID in the application's package of the drawble to use. 370 */ 371 public Builder setSmallIcon(int icon) { 372 mNotification.icon = icon; 373 return this; 374 } 375 376 /** 377 * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional 378 * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable 379 * LevelListDrawable}. 380 * 381 * @param icon A resource ID in the application's package of the drawble to use. 382 * @param level The level to use for the icon. 383 * 384 * @see android.graphics.drawable.LevelListDrawable 385 */ 386 public Builder setSmallIcon(int icon, int level) { 387 mNotification.icon = icon; 388 mNotification.iconLevel = level; 389 return this; 390 } 391 392 /** 393 * Set the title (first row) of the notification, in a standard notification. 394 */ 395 public Builder setContentTitle(CharSequence title) { 396 mContentTitle = title; 397 return this; 398 } 399 400 /** 401 * Set the text (second row) of the notification, in a standard notification. 402 */ 403 public Builder setContentText(CharSequence text) { 404 mContentText = text; 405 return this; 406 } 407 408 /** 409 * Set the third line of text in the platform notification template. 410 * Don't use if you're also using {@link #setProgress(int, int, boolean)}; 411 * they occupy the same location in the standard template. 412 * <br> 413 * If the platform does not provide large-format notifications, this method has no effect. 414 * The third line of text only appears in expanded view. 415 * <br> 416 */ 417 public Builder setSubText(CharSequence text) { 418 mSubText = text; 419 return this; 420 } 421 422 /** 423 * Set the large number at the right-hand side of the notification. This is 424 * equivalent to setContentInfo, although it might show the number in a different 425 * font size for readability. 426 */ 427 public Builder setNumber(int number) { 428 mNumber = number; 429 return this; 430 } 431 432 /** 433 * Set the large text at the right-hand side of the notification. 434 */ 435 public Builder setContentInfo(CharSequence info) { 436 mContentInfo = info; 437 return this; 438 } 439 440 /** 441 * Set the progress this notification represents, which may be 442 * represented as a {@link android.widget.ProgressBar}. 443 */ 444 public Builder setProgress(int max, int progress, boolean indeterminate) { 445 mProgressMax = max; 446 mProgress = progress; 447 mProgressIndeterminate = indeterminate; 448 return this; 449 } 450 451 /** 452 * Supply a custom RemoteViews to use instead of the standard one. 453 */ 454 public Builder setContent(RemoteViews views) { 455 mNotification.contentView = views; 456 return this; 457 } 458 459 /** 460 * Supply a {@link PendingIntent} to send when the notification is clicked. 461 * If you do not supply an intent, you can now add PendingIntents to individual 462 * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent 463 * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to 464 * read {@link Notification#contentIntent Notification.contentIntent} for 465 * how to correctly use this. 466 */ 467 public Builder setContentIntent(PendingIntent intent) { 468 mContentIntent = intent; 469 return this; 470 } 471 472 /** 473 * Supply a {@link PendingIntent} to send when the notification is cleared by the user 474 * directly from the notification panel. For example, this intent is sent when the user 475 * clicks the "Clear all" button, or the individual "X" buttons on notifications. This 476 * intent is not sent when the application calls {@link NotificationManager#cancel 477 * NotificationManager.cancel(int)}. 478 */ 479 public Builder setDeleteIntent(PendingIntent intent) { 480 mNotification.deleteIntent = intent; 481 return this; 482 } 483 484 /** 485 * An intent to launch instead of posting the notification to the status bar. 486 * Only for use with extremely high-priority notifications demanding the user's 487 * <strong>immediate</strong> attention, such as an incoming phone call or 488 * alarm clock that the user has explicitly set to a particular time. 489 * If this facility is used for something else, please give the user an option 490 * to turn it off and use a normal notification, as this can be extremely 491 * disruptive. 492 * 493 * @param intent The pending intent to launch. 494 * @param highPriority Passing true will cause this notification to be sent 495 * even if other notifications are suppressed. 496 */ 497 public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { 498 mFullScreenIntent = intent; 499 setFlag(FLAG_HIGH_PRIORITY, highPriority); 500 return this; 501 } 502 503 /** 504 * Set the text that is displayed in the status bar when the notification first 505 * arrives. 506 */ 507 public Builder setTicker(CharSequence tickerText) { 508 mNotification.tickerText = tickerText; 509 return this; 510 } 511 512 /** 513 * Set the text that is displayed in the status bar when the notification first 514 * arrives, and also a RemoteViews object that may be displayed instead on some 515 * devices. 516 */ 517 public Builder setTicker(CharSequence tickerText, RemoteViews views) { 518 mNotification.tickerText = tickerText; 519 mTickerView = views; 520 return this; 521 } 522 523 /** 524 * Set the large icon that is shown in the ticker and notification. 525 */ 526 public Builder setLargeIcon(Bitmap icon) { 527 mLargeIcon = icon; 528 return this; 529 } 530 531 /** 532 * Set the sound to play. It will play on the default stream. 533 */ 534 public Builder setSound(Uri sound) { 535 mNotification.sound = sound; 536 mNotification.audioStreamType = Notification.STREAM_DEFAULT; 537 return this; 538 } 539 540 /** 541 * Set the sound to play. It will play on the stream you supply. 542 * 543 * @see Notification#STREAM_DEFAULT 544 * @see AudioManager for the <code>STREAM_</code> constants. 545 */ 546 public Builder setSound(Uri sound, int streamType) { 547 mNotification.sound = sound; 548 mNotification.audioStreamType = streamType; 549 return this; 550 } 551 552 /** 553 * Set the vibration pattern to use. 554 * 555 * @see android.os.Vibrator for a discussion of the <code>pattern</code> 556 * parameter. 557 */ 558 public Builder setVibrate(long[] pattern) { 559 mNotification.vibrate = pattern; 560 return this; 561 } 562 563 /** 564 * Set the argb value that you would like the LED on the device to blnk, as well as the 565 * rate. The rate is specified in terms of the number of milliseconds to be on 566 * and then the number of milliseconds to be off. 567 */ 568 public Builder setLights(int argb, int onMs, int offMs) { 569 mNotification.ledARGB = argb; 570 mNotification.ledOnMS = onMs; 571 mNotification.ledOffMS = offMs; 572 boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0; 573 mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) | 574 (showLights ? Notification.FLAG_SHOW_LIGHTS : 0); 575 return this; 576 } 577 578 /** 579 * Set whether this is an ongoing notification. 580 * 581 * <p>Ongoing notifications differ from regular notifications in the following ways: 582 * <ul> 583 * <li>Ongoing notifications are sorted above the regular notifications in the 584 * notification panel.</li> 585 * <li>Ongoing notifications do not have an 'X' close button, and are not affected 586 * by the "Clear all" button. 587 * </ul> 588 */ 589 public Builder setOngoing(boolean ongoing) { 590 setFlag(Notification.FLAG_ONGOING_EVENT, ongoing); 591 return this; 592 } 593 594 /** 595 * Set this flag if you would only like the sound, vibrate 596 * and ticker to be played if the notification is not already showing. 597 */ 598 public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { 599 setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); 600 return this; 601 } 602 603 /** 604 * Setting this flag will make it so the notification is automatically 605 * canceled when the user clicks it in the panel. The PendingIntent 606 * set with {@link #setDeleteIntent} will be broadcast when the notification 607 * is canceled. 608 */ 609 public Builder setAutoCancel(boolean autoCancel) { 610 setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel); 611 return this; 612 } 613 614 /** 615 * Set whether or not this notification is only relevant to the current device. 616 * 617 * <p>Some notifications can be bridged to other devices for remote display. 618 * This hint can be set to recommend this notification not be bridged. 619 */ 620 public Builder setLocalOnly(boolean b) { 621 mLocalOnly = b; 622 return this; 623 } 624 625 /** 626 * Set the notification category. 627 * 628 * <p>Must be one of the predefined notification categories (see the <code>CATEGORY_*</code> 629 * constants in {@link Notification}) that best describes this notification. 630 * May be used by the system for ranking and filtering. 631 */ 632 public Builder setCategory(String category) { 633 mCategory = category; 634 return this; 635 } 636 637 /** 638 * Set the default notification options that will be used. 639 * <p> 640 * The value should be one or more of the following fields combined with 641 * bitwise-or: 642 * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE}, 643 * {@link Notification#DEFAULT_LIGHTS}. 644 * <p> 645 * For all default values, use {@link Notification#DEFAULT_ALL}. 646 */ 647 public Builder setDefaults(int defaults) { 648 mNotification.defaults = defaults; 649 if ((defaults & Notification.DEFAULT_LIGHTS) != 0) { 650 mNotification.flags |= Notification.FLAG_SHOW_LIGHTS; 651 } 652 return this; 653 } 654 655 private void setFlag(int mask, boolean value) { 656 if (value) { 657 mNotification.flags |= mask; 658 } else { 659 mNotification.flags &= ~mask; 660 } 661 } 662 663 /** 664 * Set the relative priority for this notification. 665 * 666 * Priority is an indication of how much of the user's 667 * valuable attention should be consumed by this 668 * notification. Low-priority notifications may be hidden from 669 * the user in certain situations, while the user might be 670 * interrupted for a higher-priority notification. 671 * The system sets a notification's priority based on various factors including the 672 * setPriority value. The effect may differ slightly on different platforms. 673 */ 674 public Builder setPriority(int pri) { 675 mPriority = pri; 676 return this; 677 } 678 679 /** 680 * Merge additional metadata into this notification. 681 * 682 * <p>Values within the Bundle will replace existing extras values in this Builder. 683 * 684 * @see Notification#extras 685 */ 686 public Builder addExtras(Bundle bag) { 687 if (mExtras == null) { 688 mExtras = new Bundle(bag); 689 } else { 690 mExtras.putAll(bag); 691 } 692 return this; 693 } 694 695 /** 696 * Set metadata for this notification. 697 * 698 * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's 699 * current contents are copied into the Notification each time {@link #build()} is 700 * called. 701 * 702 * <p>Replaces any existing extras values with those from the provided Bundle. 703 * Use {@link #addExtras} to merge in metadata instead. 704 * 705 * @see Notification#extras 706 */ 707 public Builder setExtras(Bundle bag) { 708 mExtras = bag; 709 return this; 710 } 711 712 /** 713 * Get the current metadata Bundle used by this notification Builder. 714 * 715 * <p>The returned Bundle is shared with this Builder. 716 * 717 * <p>The current contents of this Bundle are copied into the Notification each time 718 * {@link #build()} is called. 719 * 720 * @see Notification#extras 721 */ 722 public Bundle getExtras() { 723 if (mExtras == null) { 724 mExtras = new Bundle(); 725 } 726 return mExtras; 727 } 728 729 /** 730 * Add an action to this notification. Actions are typically displayed by 731 * the system as a button adjacent to the notification content. 732 * <br> 733 * Action buttons won't appear on platforms prior to Android 4.1. Action 734 * buttons depend on expanded notifications, which are only available in Android 4.1 735 * and later. To ensure that an action button's functionality is always available, first 736 * implement the functionality in the {@link android.app.Activity} that starts when a user 737 * clicks the notification (see {@link #setContentIntent setContentIntent()}), and then 738 * enhance the notification by implementing the same functionality with 739 * {@link #addAction addAction()}. 740 * 741 * @param icon Resource ID of a drawable that represents the action. 742 * @param title Text describing the action. 743 * @param intent {@link android.app.PendingIntent} to be fired when the action is invoked. 744 */ 745 public Builder addAction(int icon, CharSequence title, PendingIntent intent) { 746 mActions.add(new Action(icon, title, intent)); 747 return this; 748 } 749 750 /** 751 * Add a rich notification style to be applied at build time. 752 * <br> 753 * If the platform does not provide rich notification styles, this method has no effect. The 754 * user will always see the normal notification style. 755 * 756 * @param style Object responsible for modifying the notification style. 757 */ 758 public Builder setStyle(Style style) { 759 if (mStyle != style) { 760 mStyle = style; 761 if (mStyle != null) { 762 mStyle.setBuilder(this); 763 } 764 } 765 return this; 766 } 767 768 /** 769 * @deprecated Use {@link #build()} instead. 770 */ 771 @Deprecated 772 public Notification getNotification() { 773 return IMPL.build(this); 774 } 775 776 /** 777 * Combine all of the options that have been set and return a new {@link Notification} 778 * object. 779 */ 780 public Notification build() { 781 return IMPL.build(this); 782 } 783 } 784 785 /** 786 * An object that can apply a rich notification style to a {@link Notification.Builder} 787 * object. 788 * <br> 789 * If the platform does not provide rich notification styles, methods in this class have no 790 * effect. 791 */ 792 public static abstract class Style { 793 Builder mBuilder; 794 CharSequence mBigContentTitle; 795 CharSequence mSummaryText; 796 boolean mSummaryTextSet = false; 797 798 public void setBuilder(Builder builder) { 799 if (mBuilder != builder) { 800 mBuilder = builder; 801 if (mBuilder != null) { 802 mBuilder.setStyle(this); 803 } 804 } 805 } 806 807 public Notification build() { 808 Notification notification = null; 809 if (mBuilder != null) { 810 notification = mBuilder.build(); 811 } 812 return notification; 813 } 814 } 815 816 /** 817 * Helper class for generating large-format notifications that include a large image attachment. 818 * <br> 819 * If the platform does not provide large-format notifications, this method has no effect. The 820 * user will always see the normal notification view. 821 * <br> 822 * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: 823 * <pre class="prettyprint"> 824 * Notification noti = new Notification.Builder() 825 * .setContentTitle("New photo from " + sender.toString()) 826 * .setContentText(subject) 827 * .setSmallIcon(R.drawable.new_post) 828 * .setLargeIcon(aBitmap) 829 * .setStyle(new Notification.BigPictureStyle() 830 * .bigPicture(aBigBitmap)) 831 * .build(); 832 * </pre> 833 * 834 * @see Notification#bigContentView 835 */ 836 public static class BigPictureStyle extends Style { 837 Bitmap mPicture; 838 Bitmap mBigLargeIcon; 839 boolean mBigLargeIconSet; 840 841 public BigPictureStyle() { 842 } 843 844 public BigPictureStyle(Builder builder) { 845 setBuilder(builder); 846 } 847 848 /** 849 * Overrides ContentTitle in the big form of the template. 850 * This defaults to the value passed to setContentTitle(). 851 */ 852 public BigPictureStyle setBigContentTitle(CharSequence title) { 853 mBigContentTitle = title; 854 return this; 855 } 856 857 /** 858 * Set the first line of text after the detail section in the big form of the template. 859 */ 860 public BigPictureStyle setSummaryText(CharSequence cs) { 861 mSummaryText = cs; 862 mSummaryTextSet = true; 863 return this; 864 } 865 866 /** 867 * Provide the bitmap to be used as the payload for the BigPicture notification. 868 */ 869 public BigPictureStyle bigPicture(Bitmap b) { 870 mPicture = b; 871 return this; 872 } 873 874 /** 875 * Override the large icon when the big notification is shown. 876 */ 877 public BigPictureStyle bigLargeIcon(Bitmap b) { 878 mBigLargeIcon = b; 879 mBigLargeIconSet = true; 880 return this; 881 } 882 } 883 884 /** 885 * Helper class for generating large-format notifications that include a lot of text. 886 * 887 * <br> 888 * If the platform does not provide large-format notifications, this method has no effect. The 889 * user will always see the normal notification view. 890 * <br> 891 * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: 892 * <pre class="prettyprint"> 893 * Notification noti = new Notification.Builder() 894 * .setContentTitle("New mail from " + sender.toString()) 895 * .setContentText(subject) 896 * .setSmallIcon(R.drawable.new_mail) 897 * .setLargeIcon(aBitmap) 898 * .setStyle(new Notification.BigTextStyle() 899 * .bigText(aVeryLongString)) 900 * .build(); 901 * </pre> 902 * 903 * @see Notification#bigContentView 904 */ 905 public static class BigTextStyle extends Style { 906 CharSequence mBigText; 907 908 public BigTextStyle() { 909 } 910 911 public BigTextStyle(Builder builder) { 912 setBuilder(builder); 913 } 914 915 /** 916 * Overrides ContentTitle in the big form of the template. 917 * This defaults to the value passed to setContentTitle(). 918 */ 919 public BigTextStyle setBigContentTitle(CharSequence title) { 920 mBigContentTitle = title; 921 return this; 922 } 923 924 /** 925 * Set the first line of text after the detail section in the big form of the template. 926 */ 927 public BigTextStyle setSummaryText(CharSequence cs) { 928 mSummaryText = cs; 929 mSummaryTextSet = true; 930 return this; 931 } 932 933 /** 934 * Provide the longer text to be displayed in the big form of the 935 * template in place of the content text. 936 */ 937 public BigTextStyle bigText(CharSequence cs) { 938 mBigText = cs; 939 return this; 940 } 941 } 942 943 /** 944 * Helper class for generating large-format notifications that include a list of (up to 5) strings. 945 * 946 * <br> 947 * If the platform does not provide large-format notifications, this method has no effect. The 948 * user will always see the normal notification view. 949 * <br> 950 * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: 951 * <pre class="prettyprint"> 952 * Notification noti = new Notification.Builder() 953 * .setContentTitle("5 New mails from " + sender.toString()) 954 * .setContentText(subject) 955 * .setSmallIcon(R.drawable.new_mail) 956 * .setLargeIcon(aBitmap) 957 * .setStyle(new Notification.InboxStyle() 958 * .addLine(str1) 959 * .addLine(str2) 960 * .setContentTitle("") 961 * .setSummaryText("+3 more")) 962 * .build(); 963 * </pre> 964 * 965 * @see Notification#bigContentView 966 */ 967 public static class InboxStyle extends Style { 968 ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>(); 969 970 public InboxStyle() { 971 } 972 973 public InboxStyle(Builder builder) { 974 setBuilder(builder); 975 } 976 977 /** 978 * Overrides ContentTitle in the big form of the template. 979 * This defaults to the value passed to setContentTitle(). 980 */ 981 public InboxStyle setBigContentTitle(CharSequence title) { 982 mBigContentTitle = title; 983 return this; 984 } 985 986 /** 987 * Set the first line of text after the detail section in the big form of the template. 988 */ 989 public InboxStyle setSummaryText(CharSequence cs) { 990 mSummaryText = cs; 991 mSummaryTextSet = true; 992 return this; 993 } 994 995 /** 996 * Append a line to the digest section of the Inbox notification. 997 */ 998 public InboxStyle addLine(CharSequence cs) { 999 mTexts.add(cs); 1000 return this; 1001 } 1002 } 1003 1004 public static class Action { 1005 public int icon; 1006 public CharSequence title; 1007 public PendingIntent actionIntent; 1008 1009 public Action(int icon_, CharSequence title_, PendingIntent intent_) { 1010 this.icon = icon_; 1011 this.title = title_; 1012 this.actionIntent = intent_; 1013 } 1014 } 1015 1016 /** 1017 * Gets the {@link Notification#extras} field from a notification in a backwards 1018 * compatible manner. Extras field was supported from JellyBean (Api level 16) 1019 * forwards. This function will return null on older api levels. 1020 */ 1021 public static Bundle getExtras(Notification notif) { 1022 return IMPL.getExtras(notif); 1023 } 1024 1025 /** 1026 * Get whether or not this notification is only relevant to the current device. 1027 * 1028 * <p>Some notifications can be bridged to other devices for remote display. 1029 * If this hint is set, it is recommend that this notification not be bridged. 1030 */ 1031 public static boolean getLocalOnly(Notification notif) { 1032 return IMPL.getLocalOnly(notif); 1033 } 1034} 1035