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