Notification.java revision 6b31880838196806dff991551f197684b5809d8b
1/* 2 * Copyright (C) 2007 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.app; 18 19import com.android.internal.R; 20 21import android.content.Context; 22import android.content.Intent; 23import android.graphics.Bitmap; 24import android.net.Uri; 25import android.os.Bundle; 26import android.os.IBinder; 27import android.os.Parcel; 28import android.os.Parcelable; 29import android.os.SystemClock; 30import android.text.TextUtils; 31import android.util.IntProperty; 32import android.util.Log; 33import android.view.View; 34import android.widget.ProgressBar; 35import android.widget.RemoteViews; 36 37import java.text.NumberFormat; 38import java.util.ArrayList; 39 40/** 41 * A class that represents how a persistent notification is to be presented to 42 * the user using the {@link android.app.NotificationManager}. 43 * 44 * <p>The {@link Notification.Builder Notification.Builder} has been added to make it 45 * easier to construct Notifications.</p> 46 * 47 * <div class="special reference"> 48 * <h3>Developer Guides</h3> 49 * <p>For a guide to creating notifications, read the 50 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a> 51 * developer guide.</p> 52 * </div> 53 */ 54public class Notification implements Parcelable 55{ 56 /** 57 * Use all default values (where applicable). 58 */ 59 public static final int DEFAULT_ALL = ~0; 60 61 /** 62 * Use the default notification sound. This will ignore any given 63 * {@link #sound}. 64 * 65 66 * @see #defaults 67 */ 68 69 public static final int DEFAULT_SOUND = 1; 70 71 /** 72 * Use the default notification vibrate. This will ignore any given 73 * {@link #vibrate}. Using phone vibration requires the 74 * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. 75 * 76 * @see #defaults 77 */ 78 79 public static final int DEFAULT_VIBRATE = 2; 80 81 /** 82 * Use the default notification lights. This will ignore the 83 * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or 84 * {@link #ledOnMS}. 85 * 86 * @see #defaults 87 */ 88 89 public static final int DEFAULT_LIGHTS = 4; 90 91 /** 92 * A timestamp related to this notification, in milliseconds since the epoch. 93 * 94 * Default value: {@link System#currentTimeMillis() Now}. 95 * 96 * Choose a timestamp that will be most relevant to the user. For most finite events, this 97 * corresponds to the time the event happened (or will happen, in the case of events that have 98 * yet to occur but about which the user is being informed). Indefinite events should be 99 * timestamped according to when the activity began. 100 * 101 * Some examples: 102 * 103 * <ul> 104 * <li>Notification of a new chat message should be stamped when the message was received.</li> 105 * <li>Notification of an ongoing file download (with a progress bar, for example) should be stamped when the download started.</li> 106 * <li>Notification of a completed file download should be stamped when the download finished.</li> 107 * <li>Notification of an upcoming meeting should be stamped with the time the meeting will begin (that is, in the future).</li> 108 * <li>Notification of an ongoing stopwatch (increasing timer) should be stamped with the watch's start time. 109 * <li>Notification of an ongoing countdown timer should be stamped with the timer's end time. 110 * </ul> 111 * 112 */ 113 public long when; 114 115 /** 116 * The resource id of a drawable to use as the icon in the status bar. 117 * This is required; notifications with an invalid icon resource will not be shown. 118 */ 119 public int icon; 120 121 /** 122 * If the icon in the status bar is to have more than one level, you can set this. Otherwise, 123 * leave it at its default value of 0. 124 * 125 * @see android.widget.ImageView#setImageLevel 126 * @see android.graphics.drawable#setLevel 127 */ 128 public int iconLevel; 129 130 /** 131 * The number of events that this notification represents. For example, in a new mail 132 * notification, this could be the number of unread messages. 133 * 134 * The system may or may not use this field to modify the appearance of the notification. For 135 * example, before {@link android.os.Build.VERSION_CODES#HONEYCOMB}, this number was 136 * superimposed over the icon in the status bar. Starting with 137 * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, the template used by 138 * {@link Notification.Builder} has displayed the number in the expanded notification view. 139 * 140 * If the number is 0 or negative, it is never shown. 141 */ 142 public int number; 143 144 /** 145 * The intent to execute when the expanded status entry is clicked. If 146 * this is an activity, it must include the 147 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 148 * that you take care of task management as described in the 149 * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back 150 * Stack</a> document. In particular, make sure to read the notification section 151 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#HandlingNotifications">Handling 152 * Notifications</a> for the correct ways to launch an application from a 153 * notification. 154 */ 155 public PendingIntent contentIntent; 156 157 /** 158 * The intent to execute when the notification is explicitly dismissed by the user, either with 159 * the "Clear All" button or by swiping it away individually. 160 * 161 * This probably shouldn't be launching an activity since several of those will be sent 162 * at the same time. 163 */ 164 public PendingIntent deleteIntent; 165 166 /** 167 * An intent to launch instead of posting the notification to the status bar. 168 * 169 * @see Notification.Builder#setFullScreenIntent 170 */ 171 public PendingIntent fullScreenIntent; 172 173 /** 174 * Text to scroll across the screen when this item is added to 175 * the status bar on large and smaller devices. 176 * 177 * @see #tickerView 178 */ 179 public CharSequence tickerText; 180 181 /** 182 * The view to show as the ticker in the status bar when the notification 183 * is posted. 184 */ 185 public RemoteViews tickerView; 186 187 /** 188 * The view that will represent this notification in the expanded status bar. 189 */ 190 public RemoteViews contentView; 191 192 /** 193 * A large-format version of {@link #contentView}, giving the Notification an 194 * opportunity to show more detail. The system UI may choose to show this 195 * instead of the normal content view at its discretion. 196 */ 197 public RemoteViews bigContentView; 198 199 /** 200 * The bitmap that may escape the bounds of the panel and bar. 201 */ 202 public Bitmap largeIcon; 203 204 /** 205 * The sound to play. 206 * 207 * <p> 208 * To play the default notification sound, see {@link #defaults}. 209 * </p> 210 */ 211 public Uri sound; 212 213 /** 214 * Use this constant as the value for audioStreamType to request that 215 * the default stream type for notifications be used. Currently the 216 * default stream type is STREAM_RING. 217 */ 218 public static final int STREAM_DEFAULT = -1; 219 220 /** 221 * The audio stream type to use when playing the sound. 222 * Should be one of the STREAM_ constants from 223 * {@link android.media.AudioManager}. 224 */ 225 public int audioStreamType = STREAM_DEFAULT; 226 227 /** 228 * The pattern with which to vibrate. 229 * 230 * <p> 231 * To vibrate the default pattern, see {@link #defaults}. 232 * </p> 233 * 234 * @see android.os.Vibrator#vibrate(long[],int) 235 */ 236 public long[] vibrate; 237 238 /** 239 * The color of the led. The hardware will do its best approximation. 240 * 241 * @see #FLAG_SHOW_LIGHTS 242 * @see #flags 243 */ 244 public int ledARGB; 245 246 /** 247 * The number of milliseconds for the LED to be on while it's flashing. 248 * The hardware will do its best approximation. 249 * 250 * @see #FLAG_SHOW_LIGHTS 251 * @see #flags 252 */ 253 public int ledOnMS; 254 255 /** 256 * The number of milliseconds for the LED to be off while it's flashing. 257 * The hardware will do its best approximation. 258 * 259 * @see #FLAG_SHOW_LIGHTS 260 * @see #flags 261 */ 262 public int ledOffMS; 263 264 /** 265 * Specifies which values should be taken from the defaults. 266 * <p> 267 * To set, OR the desired from {@link #DEFAULT_SOUND}, 268 * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default 269 * values, use {@link #DEFAULT_ALL}. 270 * </p> 271 */ 272 public int defaults; 273 274 /** 275 * Bit to be bitwise-ored into the {@link #flags} field that should be 276 * set if you want the LED on for this notification. 277 * <ul> 278 * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB 279 * or 0 for both ledOnMS and ledOffMS.</li> 280 * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li> 281 * <li>To flash the LED, pass the number of milliseconds that it should 282 * be on and off to ledOnMS and ledOffMS.</li> 283 * </ul> 284 * <p> 285 * Since hardware varies, you are not guaranteed that any of the values 286 * you pass are honored exactly. Use the system defaults (TODO) if possible 287 * because they will be set to values that work on any given hardware. 288 * <p> 289 * The alpha channel must be set for forward compatibility. 290 * 291 */ 292 public static final int FLAG_SHOW_LIGHTS = 0x00000001; 293 294 /** 295 * Bit to be bitwise-ored into the {@link #flags} field that should be 296 * set if this notification is in reference to something that is ongoing, 297 * like a phone call. It should not be set if this notification is in 298 * reference to something that happened at a particular point in time, 299 * like a missed phone call. 300 */ 301 public static final int FLAG_ONGOING_EVENT = 0x00000002; 302 303 /** 304 * Bit to be bitwise-ored into the {@link #flags} field that if set, 305 * the audio will be repeated until the notification is 306 * cancelled or the notification window is opened. 307 */ 308 public static final int FLAG_INSISTENT = 0x00000004; 309 310 /** 311 * Bit to be bitwise-ored into the {@link #flags} field that should be 312 * set if you want the sound and/or vibration play each time the 313 * notification is sent, even if it has not been canceled before that. 314 */ 315 public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008; 316 317 /** 318 * Bit to be bitwise-ored into the {@link #flags} field that should be 319 * set if the notification should be canceled when it is clicked by the 320 * user. On tablets, the 321 322 */ 323 public static final int FLAG_AUTO_CANCEL = 0x00000010; 324 325 /** 326 * Bit to be bitwise-ored into the {@link #flags} field that should be 327 * set if the notification should not be canceled when the user clicks 328 * the Clear all button. 329 */ 330 public static final int FLAG_NO_CLEAR = 0x00000020; 331 332 /** 333 * Bit to be bitwise-ored into the {@link #flags} field that should be 334 * set if this notification represents a currently running service. This 335 * will normally be set for you by {@link Service#startForeground}. 336 */ 337 public static final int FLAG_FOREGROUND_SERVICE = 0x00000040; 338 339 /** 340 * Obsolete flag indicating high-priority notifications; use the priority field instead. 341 * 342 * @deprecated Use {@link #priority} with a positive value. 343 */ 344 public static final int FLAG_HIGH_PRIORITY = 0x00000080; 345 346 public int flags; 347 348 /** 349 * Default notification {@link #priority}. If your application does not prioritize its own 350 * notifications, use this value for all notifications. 351 */ 352 public static final int PRIORITY_DEFAULT = 0; 353 354 /** 355 * Lower {@link #priority}, for items that are less important. The UI may choose to show these 356 * items smaller, or at a different position in the list, compared with your app's 357 * {@link #PRIORITY_DEFAULT} items. 358 */ 359 public static final int PRIORITY_LOW = -1; 360 361 /** 362 * Lowest {@link #priority}; these items might not be shown to the user except under special 363 * circumstances, such as detailed notification logs. 364 */ 365 public static final int PRIORITY_MIN = -2; 366 367 /** 368 * Higher {@link #priority}, for more important notifications or alerts. The UI may choose to 369 * show these items larger, or at a different position in notification lists, compared with 370 * your app's {@link #PRIORITY_DEFAULT} items. 371 */ 372 public static final int PRIORITY_HIGH = 1; 373 374 /** 375 * Highest {@link #priority}, for your application's most important items that require the 376 * user's prompt attention or input. 377 */ 378 public static final int PRIORITY_MAX = 2; 379 380 /** 381 * Relative priority for this notification. 382 * 383 * Priority is an indication of how much of the user's valuable attention should be consumed by 384 * this notification. Low-priority notifications may be hidden from the user in certain 385 * situations, while the user might be interrupted for a higher-priority notification. The 386 * system will make a determination about how to interpret notification priority as described in 387 * MUMBLE MUMBLE. 388 */ 389 public int priority; 390 391 /** 392 * Notification type: incoming call (voice or video) or similar synchronous communication request. 393 */ 394 public static final String KIND_CALL = "android.call"; 395 396 /** 397 * Notification type: incoming direct message (SMS, instant message, etc.). 398 */ 399 public static final String KIND_MESSAGE = "android.message"; 400 401 /** 402 * Notification type: asynchronous bulk message (email). 403 */ 404 public static final String KIND_EMAIL = "android.email"; 405 406 /** 407 * Notification type: calendar event. 408 */ 409 public static final String KIND_EVENT = "android.event"; 410 411 /** 412 * Notification type: promotion or advertisement. 413 */ 414 public static final String KIND_PROMO = "android.promo"; 415 416 /** 417 * If this notification matches of one or more special types (see the <code>KIND_*</code> 418 * constants), add them here, best match first. 419 */ 420 public String[] kind; 421 422 /** 423 * Extra key for people values (type TBD). 424 * 425 * @hide 426 */ 427 public static final String EXTRA_PEOPLE = "android.people"; 428 429 private Bundle extras; 430 431 /** 432 * Structure to encapsulate an "action", including title and icon, that can be attached to a Notification. 433 * @hide 434 */ 435 private static class Action implements Parcelable { 436 public int icon; 437 public CharSequence title; 438 public PendingIntent actionIntent; 439 @SuppressWarnings("unused") 440 public Action() { } 441 private Action(Parcel in) { 442 icon = in.readInt(); 443 title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 444 if (in.readInt() == 1) { 445 actionIntent = PendingIntent.CREATOR.createFromParcel(in); 446 } 447 } 448 public Action(int icon_, CharSequence title_, PendingIntent intent_) { 449 this.icon = icon_; 450 this.title = title_; 451 this.actionIntent = intent_; 452 } 453 @Override 454 public Action clone() { 455 return new Action( 456 this.icon, 457 this.title.toString(), 458 this.actionIntent // safe to alias 459 ); 460 } 461 @Override 462 public int describeContents() { 463 return 0; 464 } 465 @Override 466 public void writeToParcel(Parcel out, int flags) { 467 out.writeInt(icon); 468 TextUtils.writeToParcel(title, out, flags); 469 if (actionIntent != null) { 470 out.writeInt(1); 471 actionIntent.writeToParcel(out, flags); 472 } else { 473 out.writeInt(0); 474 } 475 } 476 public static final Parcelable.Creator<Action> CREATOR 477 = new Parcelable.Creator<Action>() { 478 public Action createFromParcel(Parcel in) { 479 return new Action(in); 480 } 481 public Action[] newArray(int size) { 482 return new Action[size]; 483 } 484 }; 485 } 486 487 private Action[] actions; 488 489 /** 490 * Constructs a Notification object with default values. 491 * You might want to consider using {@link Builder} instead. 492 */ 493 public Notification() 494 { 495 this.when = System.currentTimeMillis(); 496 this.priority = PRIORITY_DEFAULT; 497 } 498 499 /** 500 * @hide 501 */ 502 public Notification(Context context, int icon, CharSequence tickerText, long when, 503 CharSequence contentTitle, CharSequence contentText, Intent contentIntent) 504 { 505 this.when = when; 506 this.icon = icon; 507 this.tickerText = tickerText; 508 setLatestEventInfo(context, contentTitle, contentText, 509 PendingIntent.getActivity(context, 0, contentIntent, 0)); 510 } 511 512 /** 513 * Constructs a Notification object with the information needed to 514 * have a status bar icon without the standard expanded view. 515 * 516 * @param icon The resource id of the icon to put in the status bar. 517 * @param tickerText The text that flows by in the status bar when the notification first 518 * activates. 519 * @param when The time to show in the time field. In the System.currentTimeMillis 520 * timebase. 521 * 522 * @deprecated Use {@link Builder} instead. 523 */ 524 @Deprecated 525 public Notification(int icon, CharSequence tickerText, long when) 526 { 527 this.icon = icon; 528 this.tickerText = tickerText; 529 this.when = when; 530 } 531 532 /** 533 * Unflatten the notification from a parcel. 534 */ 535 public Notification(Parcel parcel) 536 { 537 int version = parcel.readInt(); 538 539 when = parcel.readLong(); 540 icon = parcel.readInt(); 541 number = parcel.readInt(); 542 if (parcel.readInt() != 0) { 543 contentIntent = PendingIntent.CREATOR.createFromParcel(parcel); 544 } 545 if (parcel.readInt() != 0) { 546 deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel); 547 } 548 if (parcel.readInt() != 0) { 549 tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 550 } 551 if (parcel.readInt() != 0) { 552 tickerView = RemoteViews.CREATOR.createFromParcel(parcel); 553 } 554 if (parcel.readInt() != 0) { 555 contentView = RemoteViews.CREATOR.createFromParcel(parcel); 556 } 557 if (parcel.readInt() != 0) { 558 largeIcon = Bitmap.CREATOR.createFromParcel(parcel); 559 } 560 defaults = parcel.readInt(); 561 flags = parcel.readInt(); 562 if (parcel.readInt() != 0) { 563 sound = Uri.CREATOR.createFromParcel(parcel); 564 } 565 566 audioStreamType = parcel.readInt(); 567 vibrate = parcel.createLongArray(); 568 ledARGB = parcel.readInt(); 569 ledOnMS = parcel.readInt(); 570 ledOffMS = parcel.readInt(); 571 iconLevel = parcel.readInt(); 572 573 if (parcel.readInt() != 0) { 574 fullScreenIntent = PendingIntent.CREATOR.createFromParcel(parcel); 575 } 576 577 priority = parcel.readInt(); 578 579 kind = parcel.createStringArray(); // may set kind to null 580 581 if (parcel.readInt() != 0) { 582 extras = parcel.readBundle(); 583 } 584 585 actions = parcel.createTypedArray(Action.CREATOR); 586 if (parcel.readInt() != 0) { 587 bigContentView = RemoteViews.CREATOR.createFromParcel(parcel); 588 } 589 } 590 591 @Override 592 public Notification clone() { 593 Notification that = new Notification(); 594 595 that.when = this.when; 596 that.icon = this.icon; 597 that.number = this.number; 598 599 // PendingIntents are global, so there's no reason (or way) to clone them. 600 that.contentIntent = this.contentIntent; 601 that.deleteIntent = this.deleteIntent; 602 that.fullScreenIntent = this.fullScreenIntent; 603 604 if (this.tickerText != null) { 605 that.tickerText = this.tickerText.toString(); 606 } 607 if (this.tickerView != null) { 608 that.tickerView = this.tickerView.clone(); 609 } 610 if (this.contentView != null) { 611 that.contentView = this.contentView.clone(); 612 } 613 if (this.largeIcon != null) { 614 that.largeIcon = Bitmap.createBitmap(this.largeIcon); 615 } 616 that.iconLevel = this.iconLevel; 617 that.sound = this.sound; // android.net.Uri is immutable 618 that.audioStreamType = this.audioStreamType; 619 620 final long[] vibrate = this.vibrate; 621 if (vibrate != null) { 622 final int N = vibrate.length; 623 final long[] vib = that.vibrate = new long[N]; 624 System.arraycopy(vibrate, 0, vib, 0, N); 625 } 626 627 that.ledARGB = this.ledARGB; 628 that.ledOnMS = this.ledOnMS; 629 that.ledOffMS = this.ledOffMS; 630 that.defaults = this.defaults; 631 632 that.flags = this.flags; 633 634 that.priority = this.priority; 635 636 final String[] thiskind = this.kind; 637 if (thiskind != null) { 638 final int N = thiskind.length; 639 final String[] thatkind = that.kind = new String[N]; 640 System.arraycopy(thiskind, 0, thatkind, 0, N); 641 } 642 643 if (this.extras != null) { 644 that.extras = new Bundle(this.extras); 645 646 } 647 648 that.actions = new Action[this.actions.length]; 649 for(int i=0; i<this.actions.length; i++) { 650 that.actions[i] = this.actions[i].clone(); 651 } 652 if (this.bigContentView != null) { 653 that.bigContentView = this.bigContentView.clone(); 654 } 655 656 return that; 657 } 658 659 public int describeContents() { 660 return 0; 661 } 662 663 /** 664 * Flatten this notification from a parcel. 665 */ 666 public void writeToParcel(Parcel parcel, int flags) 667 { 668 parcel.writeInt(1); 669 670 parcel.writeLong(when); 671 parcel.writeInt(icon); 672 parcel.writeInt(number); 673 if (contentIntent != null) { 674 parcel.writeInt(1); 675 contentIntent.writeToParcel(parcel, 0); 676 } else { 677 parcel.writeInt(0); 678 } 679 if (deleteIntent != null) { 680 parcel.writeInt(1); 681 deleteIntent.writeToParcel(parcel, 0); 682 } else { 683 parcel.writeInt(0); 684 } 685 if (tickerText != null) { 686 parcel.writeInt(1); 687 TextUtils.writeToParcel(tickerText, parcel, flags); 688 } else { 689 parcel.writeInt(0); 690 } 691 if (tickerView != null) { 692 parcel.writeInt(1); 693 tickerView.writeToParcel(parcel, 0); 694 } else { 695 parcel.writeInt(0); 696 } 697 if (contentView != null) { 698 parcel.writeInt(1); 699 contentView.writeToParcel(parcel, 0); 700 } else { 701 parcel.writeInt(0); 702 } 703 if (largeIcon != null) { 704 parcel.writeInt(1); 705 largeIcon.writeToParcel(parcel, 0); 706 } else { 707 parcel.writeInt(0); 708 } 709 710 parcel.writeInt(defaults); 711 parcel.writeInt(this.flags); 712 713 if (sound != null) { 714 parcel.writeInt(1); 715 sound.writeToParcel(parcel, 0); 716 } else { 717 parcel.writeInt(0); 718 } 719 parcel.writeInt(audioStreamType); 720 parcel.writeLongArray(vibrate); 721 parcel.writeInt(ledARGB); 722 parcel.writeInt(ledOnMS); 723 parcel.writeInt(ledOffMS); 724 parcel.writeInt(iconLevel); 725 726 if (fullScreenIntent != null) { 727 parcel.writeInt(1); 728 fullScreenIntent.writeToParcel(parcel, 0); 729 } else { 730 parcel.writeInt(0); 731 } 732 733 parcel.writeInt(priority); 734 735 parcel.writeStringArray(kind); // ok for null 736 737 if (extras != null) { 738 parcel.writeInt(1); 739 extras.writeToParcel(parcel, 0); 740 } else { 741 parcel.writeInt(0); 742 } 743 744 parcel.writeTypedArray(actions, 0); 745 746 if (bigContentView != null) { 747 parcel.writeInt(1); 748 bigContentView.writeToParcel(parcel, 0); 749 } else { 750 parcel.writeInt(0); 751 } 752 } 753 754 /** 755 * Parcelable.Creator that instantiates Notification objects 756 */ 757 public static final Parcelable.Creator<Notification> CREATOR 758 = new Parcelable.Creator<Notification>() 759 { 760 public Notification createFromParcel(Parcel parcel) 761 { 762 return new Notification(parcel); 763 } 764 765 public Notification[] newArray(int size) 766 { 767 return new Notification[size]; 768 } 769 }; 770 771 /** 772 * Sets the {@link #contentView} field to be a view with the standard "Latest Event" 773 * layout. 774 * 775 * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields 776 * in the view.</p> 777 * @param context The context for your application / activity. 778 * @param contentTitle The title that goes in the expanded entry. 779 * @param contentText The text that goes in the expanded entry. 780 * @param contentIntent The intent to launch when the user clicks the expanded notification. 781 * If this is an activity, it must include the 782 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 783 * that you take care of task management as described in the 784 * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back 785 * Stack</a> document. 786 * 787 * @deprecated Use {@link Builder} instead. 788 */ 789 @Deprecated 790 public void setLatestEventInfo(Context context, 791 CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) { 792 // TODO: rewrite this to use Builder 793 RemoteViews contentView = new RemoteViews(context.getPackageName(), 794 R.layout.notification_template_base); 795 if (this.icon != 0) { 796 contentView.setImageViewResource(R.id.icon, this.icon); 797 } 798 if (contentTitle != null) { 799 contentView.setTextViewText(R.id.title, contentTitle); 800 } 801 if (contentText != null) { 802 contentView.setTextViewText(R.id.text, contentText); 803 } 804 if (this.when != 0) { 805 contentView.setViewVisibility(R.id.time, View.VISIBLE); 806 contentView.setLong(R.id.time, "setTime", when); 807 } 808 809 this.contentView = contentView; 810 this.contentIntent = contentIntent; 811 } 812 813 @Override 814 public String toString() { 815 StringBuilder sb = new StringBuilder(); 816 sb.append("Notification(pri="); 817 sb.append(priority); 818 sb.append(" contentView="); 819 if (contentView != null) { 820 sb.append(contentView.getPackage()); 821 sb.append("/0x"); 822 sb.append(Integer.toHexString(contentView.getLayoutId())); 823 } else { 824 sb.append("null"); 825 } 826 // TODO(dsandler): defaults take precedence over local values, so reorder the branches below 827 sb.append(" vibrate="); 828 if (this.vibrate != null) { 829 int N = this.vibrate.length-1; 830 sb.append("["); 831 for (int i=0; i<N; i++) { 832 sb.append(this.vibrate[i]); 833 sb.append(','); 834 } 835 if (N != -1) { 836 sb.append(this.vibrate[N]); 837 } 838 sb.append("]"); 839 } else if ((this.defaults & DEFAULT_VIBRATE) != 0) { 840 sb.append("default"); 841 } else { 842 sb.append("null"); 843 } 844 sb.append(" sound="); 845 if (this.sound != null) { 846 sb.append(this.sound.toString()); 847 } else if ((this.defaults & DEFAULT_SOUND) != 0) { 848 sb.append("default"); 849 } else { 850 sb.append("null"); 851 } 852 sb.append(" defaults=0x"); 853 sb.append(Integer.toHexString(this.defaults)); 854 sb.append(" flags=0x"); 855 sb.append(Integer.toHexString(this.flags)); 856 sb.append(" kind=["); 857 if (this.kind == null) { 858 sb.append("null"); 859 } else { 860 for (int i=0; i<this.kind.length; i++) { 861 if (i>0) sb.append(","); 862 sb.append(this.kind[i]); 863 } 864 } 865 sb.append("]"); 866 if (actions != null) { 867 sb.append(" "); 868 sb.append(actions.length); 869 sb.append(" action"); 870 if (actions.length > 1) sb.append("s"); 871 } 872 sb.append(")"); 873 return sb.toString(); 874 } 875 876 /** 877 * Builder class for {@link Notification} objects. 878 * 879 * Provides a convenient way to set the various fields of a {@link Notification} and generate 880 * content views using the platform's notification layout template. 881 * 882 * Example: 883 * 884 * <pre class="prettyprint"> 885 * Notification noti = new Notification.Builder() 886 * .setContentTitle("New mail from " + sender.toString()) 887 * .setContentText(subject) 888 * .setSmallIcon(R.drawable.new_mail) 889 * .setLargeIcon(aBitmap) 890 * .getNotification(); 891 * </pre> 892 */ 893 public static class Builder { 894 private Context mContext; 895 896 private long mWhen; 897 private int mSmallIcon; 898 private int mSmallIconLevel; 899 private int mNumber; 900 private CharSequence mContentTitle; 901 private CharSequence mContentText; 902 private CharSequence mContentInfo; 903 private CharSequence mSubText; 904 private PendingIntent mContentIntent; 905 private RemoteViews mContentView; 906 private PendingIntent mDeleteIntent; 907 private PendingIntent mFullScreenIntent; 908 private CharSequence mTickerText; 909 private RemoteViews mTickerView; 910 private Bitmap mLargeIcon; 911 private Uri mSound; 912 private int mAudioStreamType; 913 private long[] mVibrate; 914 private int mLedArgb; 915 private int mLedOnMs; 916 private int mLedOffMs; 917 private int mDefaults; 918 private int mFlags; 919 private int mProgressMax; 920 private int mProgress; 921 private boolean mProgressIndeterminate; 922 private ArrayList<String> mKindList = new ArrayList<String>(1); 923 private Bundle mExtras; 924 private int mPriority; 925 private ArrayList<Action> mActions = new ArrayList<Action>(3); 926 private boolean mUseChronometer; 927 928 /** 929 * Constructs a new Builder with the defaults: 930 * 931 932 * <table> 933 * <tr><th align=right>priority</th> 934 * <td>{@link #PRIORITY_DEFAULT}</td></tr> 935 * <tr><th align=right>when</th> 936 * <td>now ({@link System#currentTimeMillis()})</td></tr> 937 * <tr><th align=right>audio stream</th> 938 * <td>{@link #STREAM_DEFAULT}</td></tr> 939 * </table> 940 * 941 942 * @param context 943 * A {@link Context} that will be used by the Builder to construct the 944 * RemoteViews. The Context will not be held past the lifetime of this Builder 945 * object. 946 */ 947 public Builder(Context context) { 948 mContext = context; 949 950 // Set defaults to match the defaults of a Notification 951 mWhen = System.currentTimeMillis(); 952 mAudioStreamType = STREAM_DEFAULT; 953 mPriority = PRIORITY_DEFAULT; 954 } 955 956 /** 957 * Add a timestamp pertaining to the notification (usually the time the event occurred). 958 * 959 960 * @see Notification#when 961 */ 962 public Builder setWhen(long when) { 963 mWhen = when; 964 return this; 965 } 966 967 /** 968 * Show the {@link Notification#when} field as a countdown (or count-up) timer instead of a timestamp. 969 * 970 * @see Notification#when 971 */ 972 public Builder setUsesChronometer(boolean b) { 973 mUseChronometer = b; 974 return this; 975 } 976 977 /** 978 * Set the small icon resource, which will be used to represent the notification in the 979 * status bar. 980 * 981 982 * The platform template for the expanded view will draw this icon in the left, unless a 983 * {@link #setLargeIcon(Bitmap) large icon} has also been specified, in which case the small 984 * icon will be moved to the right-hand side. 985 * 986 987 * @param icon 988 * A resource ID in the application's package of the drawable to use. 989 * @see Notification#icon 990 */ 991 public Builder setSmallIcon(int icon) { 992 mSmallIcon = icon; 993 return this; 994 } 995 996 /** 997 * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional 998 * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable 999 * LevelListDrawable}. 1000 * 1001 * @param icon A resource ID in the application's package of the drawable to use. 1002 * @param level The level to use for the icon. 1003 * 1004 * @see Notification#icon 1005 * @see Notification#iconLevel 1006 */ 1007 public Builder setSmallIcon(int icon, int level) { 1008 mSmallIcon = icon; 1009 mSmallIconLevel = level; 1010 return this; 1011 } 1012 1013 /** 1014 * Set the first line of text in the platform notification template. 1015 */ 1016 public Builder setContentTitle(CharSequence title) { 1017 mContentTitle = title; 1018 return this; 1019 } 1020 1021 /** 1022 * Set the second line of text in the platform notification template. 1023 */ 1024 public Builder setContentText(CharSequence text) { 1025 mContentText = text; 1026 return this; 1027 } 1028 1029 /** 1030 * Set the third line of text in the platform notification template. 1031 * Don't use if you're also using {@link #setProgress(int, int, boolean)}; they occupy the same location in the standard template. 1032 */ 1033 public Builder setSubText(CharSequence text) { 1034 mSubText = text; 1035 return this; 1036 } 1037 1038 /** 1039 * Set the large number at the right-hand side of the notification. This is 1040 * equivalent to setContentInfo, although it might show the number in a different 1041 * font size for readability. 1042 */ 1043 public Builder setNumber(int number) { 1044 mNumber = number; 1045 return this; 1046 } 1047 1048 /** 1049 * A small piece of additional information pertaining to this notification. 1050 * 1051 * The platform template will draw this on the last line of the notification, at the far 1052 * right (to the right of a smallIcon if it has been placed there). 1053 */ 1054 public Builder setContentInfo(CharSequence info) { 1055 mContentInfo = info; 1056 return this; 1057 } 1058 1059 /** 1060 * Set the progress this notification represents. 1061 * 1062 * The platform template will represent this using a {@link ProgressBar}. 1063 */ 1064 public Builder setProgress(int max, int progress, boolean indeterminate) { 1065 mProgressMax = max; 1066 mProgress = progress; 1067 mProgressIndeterminate = indeterminate; 1068 return this; 1069 } 1070 1071 /** 1072 * Supply a custom RemoteViews to use instead of the platform template. 1073 * 1074 * @see Notification#contentView 1075 */ 1076 public Builder setContent(RemoteViews views) { 1077 mContentView = views; 1078 return this; 1079 } 1080 1081 /** 1082 * Supply a {@link PendingIntent} to be sent when the notification is clicked. 1083 * 1084 * As of {@link android.os.Build.VERSION_CODES#HONEYCOMB}, if this field is unset and you 1085 * have specified a custom RemoteViews with {@link #setContent(RemoteViews)}, you can use 1086 * {@link RemoteViews#setOnClickPendingIntent RemoteViews.setOnClickPendingIntent(int,PendingIntent)} 1087 * to assign PendingIntents to individual views in that custom layout (i.e., to create 1088 * clickable buttons inside the notification view). 1089 * 1090 * @see Notification#contentIntent Notification.contentIntent 1091 */ 1092 public Builder setContentIntent(PendingIntent intent) { 1093 mContentIntent = intent; 1094 return this; 1095 } 1096 1097 /** 1098 * Supply a {@link PendingIntent} to send when the notification is cleared explicitly by the user. 1099 * 1100 * @see Notification#deleteIntent 1101 */ 1102 public Builder setDeleteIntent(PendingIntent intent) { 1103 mDeleteIntent = intent; 1104 return this; 1105 } 1106 1107 /** 1108 * An intent to launch instead of posting the notification to the status bar. 1109 * Only for use with extremely high-priority notifications demanding the user's 1110 * <strong>immediate</strong> attention, such as an incoming phone call or 1111 * alarm clock that the user has explicitly set to a particular time. 1112 * If this facility is used for something else, please give the user an option 1113 * to turn it off and use a normal notification, as this can be extremely 1114 * disruptive. 1115 * 1116 * @param intent The pending intent to launch. 1117 * @param highPriority Passing true will cause this notification to be sent 1118 * even if other notifications are suppressed. 1119 * 1120 * @see Notification#fullScreenIntent 1121 */ 1122 public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { 1123 mFullScreenIntent = intent; 1124 setFlag(FLAG_HIGH_PRIORITY, highPriority); 1125 return this; 1126 } 1127 1128 /** 1129 * Set the "ticker" text which is displayed in the status bar when the notification first 1130 * arrives. 1131 * 1132 * @see Notification#tickerText 1133 */ 1134 public Builder setTicker(CharSequence tickerText) { 1135 mTickerText = tickerText; 1136 return this; 1137 } 1138 1139 /** 1140 * Set the text that is displayed in the status bar when the notification first 1141 * arrives, and also a RemoteViews object that may be displayed instead on some 1142 * devices. 1143 * 1144 * @see Notification#tickerText 1145 * @see Notification#tickerView 1146 */ 1147 public Builder setTicker(CharSequence tickerText, RemoteViews views) { 1148 mTickerText = tickerText; 1149 mTickerView = views; 1150 return this; 1151 } 1152 1153 /** 1154 * Add a large icon to the notification (and the ticker on some devices). 1155 * 1156 * In the platform template, this image will be shown on the left of the notification view 1157 * in place of the {@link #setSmallIcon(int) small icon} (which will move to the right side). 1158 * 1159 * @see Notification#largeIcon 1160 */ 1161 public Builder setLargeIcon(Bitmap icon) { 1162 mLargeIcon = icon; 1163 return this; 1164 } 1165 1166 /** 1167 * Set the sound to play. 1168 * 1169 * It will be played on the {@link #STREAM_DEFAULT default stream} for notifications. 1170 * 1171 * @see Notification#sound 1172 */ 1173 public Builder setSound(Uri sound) { 1174 mSound = sound; 1175 mAudioStreamType = STREAM_DEFAULT; 1176 return this; 1177 } 1178 1179 /** 1180 * Set the sound to play, along with a specific stream on which to play it. 1181 * 1182 * See {@link android.media.AudioManager} for the <code>STREAM_</code> constants. 1183 * 1184 * @see Notification#sound 1185 */ 1186 public Builder setSound(Uri sound, int streamType) { 1187 mSound = sound; 1188 mAudioStreamType = streamType; 1189 return this; 1190 } 1191 1192 /** 1193 * Set the vibration pattern to use. 1194 * 1195 1196 * See {@link android.os.Vibrator#vibrate(long[], int)} for a discussion of the 1197 * <code>pattern</code> parameter. 1198 * 1199 1200 * @see Notification#vibrate 1201 */ 1202 public Builder setVibrate(long[] pattern) { 1203 mVibrate = pattern; 1204 return this; 1205 } 1206 1207 /** 1208 * Set the desired color for the indicator LED on the device, as well as the 1209 * blink duty cycle (specified in milliseconds). 1210 * 1211 1212 * Not all devices will honor all (or even any) of these values. 1213 * 1214 1215 * @see Notification#ledARGB 1216 * @see Notification#ledOnMS 1217 * @see Notification#ledOffMS 1218 */ 1219 public Builder setLights(int argb, int onMs, int offMs) { 1220 mLedArgb = argb; 1221 mLedOnMs = onMs; 1222 mLedOffMs = offMs; 1223 return this; 1224 } 1225 1226 /** 1227 * Set whether this is an "ongoing" notification. 1228 * 1229 1230 * Ongoing notifications cannot be dismissed by the user, so your application or service 1231 * must take care of canceling them. 1232 * 1233 1234 * They are typically used to indicate a background task that the user is actively engaged 1235 * with (e.g., playing music) or is pending in some way and therefore occupying the device 1236 * (e.g., a file download, sync operation, active network connection). 1237 * 1238 1239 * @see Notification#FLAG_ONGOING_EVENT 1240 * @see Service#setForeground(boolean) 1241 */ 1242 public Builder setOngoing(boolean ongoing) { 1243 setFlag(FLAG_ONGOING_EVENT, ongoing); 1244 return this; 1245 } 1246 1247 /** 1248 * Set this flag if you would only like the sound, vibrate 1249 * and ticker to be played if the notification is not already showing. 1250 * 1251 * @see Notification#FLAG_ONLY_ALERT_ONCE 1252 */ 1253 public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { 1254 setFlag(FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); 1255 return this; 1256 } 1257 1258 /** 1259 * Make this notification automatically dismissed when the user touches it. The 1260 * PendingIntent set with {@link #setDeleteIntent} will be sent when this happens. 1261 * 1262 * @see Notification#FLAG_AUTO_CANCEL 1263 */ 1264 public Builder setAutoCancel(boolean autoCancel) { 1265 setFlag(FLAG_AUTO_CANCEL, autoCancel); 1266 return this; 1267 } 1268 1269 /** 1270 * Set which notification properties will be inherited from system defaults. 1271 * <p> 1272 * The value should be one or more of the following fields combined with 1273 * bitwise-or: 1274 * {@link #DEFAULT_SOUND}, {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. 1275 * <p> 1276 * For all default values, use {@link #DEFAULT_ALL}. 1277 */ 1278 public Builder setDefaults(int defaults) { 1279 mDefaults = defaults; 1280 return this; 1281 } 1282 1283 /** 1284 * Set the priority of this notification. 1285 * 1286 * @see Notification#priority 1287 */ 1288 public Builder setPriority(int pri) { 1289 mPriority = pri; 1290 return this; 1291 } 1292 1293 /** 1294 * Add a kind (category) to this notification. Optional. 1295 * 1296 * @see Notification#kind 1297 */ 1298 public Builder addKind(String k) { 1299 mKindList.add(k); 1300 return this; 1301 } 1302 1303 /** 1304 * Add metadata to this notification. 1305 * 1306 * A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's 1307 * current contents are copied into the Notification each time {@link #getNotification()} is 1308 * called. 1309 * 1310 * @see Notification#extras 1311 * @hide 1312 */ 1313 public Builder setExtras(Bundle bag) { 1314 mExtras = bag; 1315 return this; 1316 } 1317 1318 /** 1319 * Add an action to this notification. Actions are typically displayed by 1320 * the system as a button adjacent to the notification content. 1321 * 1322 * @param icon Resource ID of a drawable that represents the action. 1323 * @param title Text describing the action. 1324 * @param intent PendingIntent to be fired when the action is invoked. 1325 */ 1326 public Builder addAction(int icon, CharSequence title, PendingIntent intent) { 1327 mActions.add(new Action(icon, title, intent)); 1328 return this; 1329 } 1330 1331 private void setFlag(int mask, boolean value) { 1332 if (value) { 1333 mFlags |= mask; 1334 } else { 1335 mFlags &= ~mask; 1336 } 1337 } 1338 1339 private RemoteViews applyStandardTemplate(int resId) { 1340 RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); 1341 boolean hasLine3 = false; 1342 boolean hasLine2 = false; 1343 int smallIconImageViewId = R.id.icon; 1344 if (mLargeIcon != null) { 1345 contentView.setImageViewBitmap(R.id.icon, mLargeIcon); 1346 smallIconImageViewId = R.id.right_icon; 1347 } 1348 if (mSmallIcon != 0) { 1349 contentView.setImageViewResource(smallIconImageViewId, mSmallIcon); 1350 contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE); 1351 } else { 1352 contentView.setViewVisibility(smallIconImageViewId, View.GONE); 1353 } 1354 if (mContentTitle != null) { 1355 contentView.setTextViewText(R.id.title, mContentTitle); 1356 } 1357 if (mContentText != null) { 1358 contentView.setTextViewText( 1359 (mSubText != null) ? R.id.text2 : R.id.text, 1360 mContentText); 1361 hasLine3 = true; 1362 } 1363 if (mContentInfo != null) { 1364 contentView.setTextViewText(R.id.info, mContentInfo); 1365 contentView.setViewVisibility(R.id.info, View.VISIBLE); 1366 hasLine3 = true; 1367 } else if (mNumber > 0) { 1368 final int tooBig = mContext.getResources().getInteger( 1369 R.integer.status_bar_notification_info_maxnum); 1370 if (mNumber > tooBig) { 1371 contentView.setTextViewText(R.id.info, mContext.getResources().getString( 1372 R.string.status_bar_notification_info_overflow)); 1373 } else { 1374 NumberFormat f = NumberFormat.getIntegerInstance(); 1375 contentView.setTextViewText(R.id.info, f.format(mNumber)); 1376 } 1377 contentView.setViewVisibility(R.id.info, View.VISIBLE); 1378 hasLine3 = true; 1379 } else { 1380 contentView.setViewVisibility(R.id.info, View.GONE); 1381 } 1382 1383 if (mSubText != null) { 1384 contentView.setTextViewText(R.id.text, mSubText); 1385 contentView.setViewVisibility(R.id.text2, View.VISIBLE); 1386 } else { 1387 contentView.setViewVisibility(R.id.text2, View.GONE); 1388 if (mProgressMax != 0 || mProgressIndeterminate) { 1389 contentView.setProgressBar( 1390 R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); 1391 contentView.setViewVisibility(R.id.progress, View.VISIBLE); 1392 } else { 1393 contentView.setViewVisibility(R.id.progress, View.GONE); 1394 } 1395 } 1396 if (mWhen != 0) { 1397 if (mUseChronometer) { 1398 contentView.setViewVisibility(R.id.chronometer, View.VISIBLE); 1399 contentView.setLong(R.id.chronometer, "setBase", 1400 mWhen + (SystemClock.elapsedRealtime() - System.currentTimeMillis())); 1401 contentView.setBoolean(R.id.chronometer, "setStarted", true); 1402 } else { 1403 contentView.setViewVisibility(R.id.time, View.VISIBLE); 1404 contentView.setLong(R.id.time, "setTime", mWhen); 1405 } 1406 } 1407 contentView.setViewVisibility(R.id.line3, hasLine3 ? View.VISIBLE : View.GONE); 1408 return contentView; 1409 } 1410 1411 private RemoteViews applyStandardTemplateWithActions(int layoutId) { 1412 RemoteViews big = applyStandardTemplate(layoutId); 1413 1414 int N = mActions.size(); 1415 if (N > 0) { 1416 Log.d("Notification", "has actions: " + mContentText); 1417 big.setViewVisibility(R.id.actions, View.VISIBLE); 1418 if (N>3) N=3; 1419 for (int i=0; i<N; i++) { 1420 final RemoteViews button = generateActionButton(mActions.get(i)); 1421 Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title); 1422 big.addView(R.id.actions, button); 1423 } 1424 } 1425 return big; 1426 } 1427 1428 private RemoteViews makeContentView() { 1429 if (mContentView != null) { 1430 return mContentView; 1431 } else { 1432 return applyStandardTemplate(R.layout.notification_template_base); // no more special large_icon flavor 1433 } 1434 } 1435 1436 private RemoteViews makeTickerView() { 1437 if (mTickerView != null) { 1438 return mTickerView; 1439 } else { 1440 if (mContentView == null) { 1441 return applyStandardTemplate(mLargeIcon == null 1442 ? R.layout.status_bar_latest_event_ticker 1443 : R.layout.status_bar_latest_event_ticker_large_icon); 1444 } else { 1445 return null; 1446 } 1447 } 1448 } 1449 1450 private RemoteViews makeBigContentView() { 1451 if (mActions.size() == 0) return null; 1452 1453 return applyStandardTemplateWithActions(R.layout.notification_template_base); 1454 } 1455 1456 private RemoteViews generateActionButton(Action action) { 1457 RemoteViews button = new RemoteViews(mContext.getPackageName(), R.layout.notification_action); 1458 button.setTextViewCompoundDrawables(R.id.action0, action.icon, 0, 0, 0); 1459 button.setTextViewText(R.id.action0, action.title); 1460 button.setOnClickPendingIntent(R.id.action0, action.actionIntent); 1461 button.setContentDescription(R.id.action0, action.title); 1462 return button; 1463 } 1464 1465 /** 1466 * Combine all of the options that have been set and return a new {@link Notification} 1467 * object. 1468 */ 1469 public Notification getNotification() { 1470 Notification n = new Notification(); 1471 n.when = mWhen; 1472 n.icon = mSmallIcon; 1473 n.iconLevel = mSmallIconLevel; 1474 n.number = mNumber; 1475 n.contentView = makeContentView(); 1476 n.contentIntent = mContentIntent; 1477 n.deleteIntent = mDeleteIntent; 1478 n.fullScreenIntent = mFullScreenIntent; 1479 n.tickerText = mTickerText; 1480 n.tickerView = makeTickerView(); 1481 n.largeIcon = mLargeIcon; 1482 n.sound = mSound; 1483 n.audioStreamType = mAudioStreamType; 1484 n.vibrate = mVibrate; 1485 n.ledARGB = mLedArgb; 1486 n.ledOnMS = mLedOnMs; 1487 n.ledOffMS = mLedOffMs; 1488 n.defaults = mDefaults; 1489 n.flags = mFlags; 1490 n.bigContentView = makeBigContentView(); 1491 if (mLedOnMs != 0 && mLedOffMs != 0) { 1492 n.flags |= FLAG_SHOW_LIGHTS; 1493 } 1494 if ((mDefaults & DEFAULT_LIGHTS) != 0) { 1495 n.flags |= FLAG_SHOW_LIGHTS; 1496 } 1497 if (mKindList.size() > 0) { 1498 n.kind = new String[mKindList.size()]; 1499 mKindList.toArray(n.kind); 1500 } else { 1501 n.kind = null; 1502 } 1503 n.priority = mPriority; 1504 n.extras = mExtras != null ? new Bundle(mExtras) : null; 1505 if (mActions.size() > 0) { 1506 n.actions = new Action[mActions.size()]; 1507 mActions.toArray(n.actions); 1508 } 1509 return n; 1510 } 1511 } 1512 1513 /** 1514 * Helper class for generating large-format notifications that include a large image attachment. 1515 * 1516 * This class is a "rebuilder": It consumes a Builder object and modifies its behavior, like so: 1517 * <pre class="prettyprint"> 1518 * Notification noti = new Notification.BigPictureStyle( 1519 * new Notification.Builder() 1520 * .setContentTitle("New photo from " + sender.toString()) 1521 * .setContentText(subject) 1522 * .setSmallIcon(R.drawable.new_post) 1523 * .setLargeIcon(aBitmap)) 1524 * .bigPicture(aBigBitmap) 1525 * .build(); 1526 * </pre> 1527 * 1528 * @see Notification#bigContentView 1529 */ 1530 public static class BigPictureStyle { 1531 private Builder mBuilder; 1532 private Bitmap mPicture; 1533 1534 public BigPictureStyle(Builder builder) { 1535 mBuilder = builder; 1536 } 1537 1538 public BigPictureStyle bigPicture(Bitmap b) { 1539 mPicture = b; 1540 return this; 1541 } 1542 1543 private RemoteViews makeBigContentView() { 1544 RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_big_picture); 1545 1546 contentView.setImageViewBitmap(R.id.big_picture, mPicture); 1547 1548 return contentView; 1549 } 1550 1551 public Notification build() { 1552 Notification wip = mBuilder.getNotification(); 1553 wip.bigContentView = makeBigContentView(); 1554 return wip; 1555 } 1556 } 1557 1558 /** 1559 * Helper class for generating large-format notifications that include a lot of text. 1560 * 1561 * This class is a "rebuilder": It consumes a Builder object and modifies its behavior, like so: 1562 * <pre class="prettyprint"> 1563 * Notification noti = new Notification.BigPictureStyle( 1564 * new Notification.Builder() 1565 * .setContentTitle("New mail from " + sender.toString()) 1566 * .setContentText(subject) 1567 * .setSmallIcon(R.drawable.new_mail) 1568 * .setLargeIcon(aBitmap)) 1569 * .bigText(aVeryLongString) 1570 * .build(); 1571 * </pre> 1572 * 1573 * @see Notification#bigContentView 1574 */ 1575 public static class BigTextStyle { 1576 private Builder mBuilder; 1577 private CharSequence mBigText; 1578 1579 public BigTextStyle(Builder builder) { 1580 mBuilder = builder; 1581 } 1582 1583 public BigTextStyle bigText(CharSequence cs) { 1584 mBigText = cs; 1585 return this; 1586 } 1587 1588 private RemoteViews makeBigContentView() { 1589 RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_big_text); 1590 1591 contentView.setTextViewText(R.id.big_text, mBigText); 1592 contentView.setViewVisibility(R.id.big_text, View.VISIBLE); 1593 contentView.setTextViewText(R.id.text, ""); // XXX: what do do with this spot? 1594 1595 return contentView; 1596 } 1597 1598 public Notification build() { 1599 Notification wip = mBuilder.getNotification(); 1600 wip.bigContentView = makeBigContentView(); 1601 return wip; 1602 } 1603 } 1604 1605 /** 1606 * Helper class for generating large-format notifications that include a list of (up to 5) strings. 1607 * 1608 * This class is a "rebuilder": It consumes a Builder object and modifies its behavior, like so: 1609 * <pre class="prettyprint"> 1610 * Notification noti = new Notification.DigestStyle( 1611 * new Notification.Builder() 1612 * .setContentTitle("New mail from " + sender.toString()) 1613 * .setContentText(subject) 1614 * .setSmallIcon(R.drawable.new_mail) 1615 * .setLargeIcon(aBitmap)) 1616 * .addLine(str1) 1617 * .addLine(str2) 1618 * .build(); 1619 * </pre> 1620 * 1621 * @see Notification#bigContentView 1622 */ 1623 public static class InboxStyle { 1624 private Builder mBuilder; 1625 private ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>(5); 1626 1627 public InboxStyle(Builder builder) { 1628 mBuilder = builder; 1629 } 1630 1631 public InboxStyle addLine(CharSequence cs) { 1632 mTexts.add(cs); 1633 return this; 1634 } 1635 1636 private RemoteViews makeBigContentView() { 1637 RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_inbox); 1638 1639 int[] rowIds = {R.id.inbox_text0, R.id.inbox_text1, R.id.inbox_text2, R.id.inbox_text3, R.id.inbox_text4}; 1640 1641 int i=0; 1642 while (i < mTexts.size() && i < rowIds.length) { 1643 CharSequence str = mTexts.get(i); 1644 if (str != null && !str.equals("")) { 1645 contentView.setViewVisibility(rowIds[i], View.VISIBLE); 1646 contentView.setTextViewText(rowIds[i], str); 1647 } 1648 i++; 1649 } 1650 1651 return contentView; 1652 } 1653 1654 public Notification build() { 1655 Notification wip = mBuilder.getNotification(); 1656 wip.bigContentView = makeBigContentView(); 1657 return wip; 1658 } 1659 } 1660} 1661