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