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 17 package android.app; 18 19 import com.android.internal.R; 20 21 import android.content.Context; 22 import android.content.Intent; 23 import android.graphics.Bitmap; 24 import android.net.Uri; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 import android.text.TextUtils; 28 import android.view.View; 29 import android.widget.ProgressBar; 30 import android.widget.RemoteViews; 31 32 import java.text.NumberFormat; 33 34 /** 35 * A class that represents how a persistent notification is to be presented to 36 * the user using the {@link android.app.NotificationManager}. 37 * 38 * <p>The {@link Notification.Builder Notification.Builder} has been added to make it 39 * easier to construct Notifications.</p> 40 * 41 * <div class="special reference"> 42 * <h3>Developer Guides</h3> 43 * <p>For a guide to creating notifications, read the 44 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a> 45 * developer guide.</p> 46 * </div> 47 */ 48 public class Notification implements Parcelable 49 { 50 /** 51 * Use all default values (where applicable). 52 */ 53 public static final int DEFAULT_ALL = ~0; 54 55 /** 56 * Use the default notification sound. This will ignore any given 57 * {@link #sound}. 58 * 59 * @see #defaults 60 */ 61 public static final int DEFAULT_SOUND = 1; 62 63 /** 64 * Use the default notification vibrate. This will ignore any given 65 * {@link #vibrate}. Using phone vibration requires the 66 * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. 67 * 68 * @see #defaults 69 */ 70 public static final int DEFAULT_VIBRATE = 2; 71 72 /** 73 * Use the default notification lights. This will ignore the 74 * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or 75 * {@link #ledOnMS}. 76 * 77 * @see #defaults 78 */ 79 public static final int DEFAULT_LIGHTS = 4; 80 81 /** 82 * The timestamp for the notification. The icons and expanded views 83 * are sorted by this key. 84 */ 85 public long when; 86 87 /** 88 * The resource id of a drawable to use as the icon in the status bar. 89 * This is required; notifications with an invalid icon resource will not be shown. 90 */ 91 public int icon; 92 93 /** 94 * If the icon in the status bar is to have more than one level, you can set this. Otherwise, 95 * leave it at its default value of 0. 96 * 97 * @see android.widget.ImageView#setImageLevel 98 * @see android.graphics.drawable#setLevel 99 */ 100 public int iconLevel; 101 102 /** 103 * The number of events that this notification represents. For example, in a new mail 104 * notification, this could be the number of unread messages. This number is superimposed over 105 * the icon in the status bar. If the number is 0 or negative, it is not shown in the status 106 * bar. 107 */ 108 public int number; 109 110 /** 111 * The intent to execute when the expanded status entry is clicked. If 112 * this is an activity, it must include the 113 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 114 * that you take care of task management as described in the 115 * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back 116 * Stack</a> document. 117 */ 118 public PendingIntent contentIntent; 119 120 /** 121 * The intent to execute when the status entry is deleted by the user 122 * with the "Clear All Notifications" button. This probably shouldn't 123 * be launching an activity since several of those will be sent at the 124 * same time. 125 */ 126 public PendingIntent deleteIntent; 127 128 /** 129 * An intent to launch instead of posting the notification to the status bar. 130 * 131 * @see Notification.Builder#setFullScreenIntent 132 */ 133 public PendingIntent fullScreenIntent; 134 135 /** 136 * Text to scroll across the screen when this item is added to 137 * the status bar on large and smaller devices. 138 * 139 * <p>This field is provided separately from the other ticker fields 140 * both for compatibility and to allow an application to choose different 141 * text for when the text scrolls in and when it is displayed all at once 142 * in conjunction with one or more icons. 143 * 144 * @see #tickerView 145 */ 146 public CharSequence tickerText; 147 148 /** 149 * The view to show as the ticker in the status bar when the notification 150 * is posted. 151 */ 152 public RemoteViews tickerView; 153 154 /** 155 * The view that will represent this notification in the expanded status bar. 156 */ 157 public RemoteViews contentView; 158 159 /** 160 * The bitmap that may escape the bounds of the panel and bar. 161 */ 162 public Bitmap largeIcon; 163 164 /** 165 * The sound to play. 166 * 167 * <p> 168 * To play the default notification sound, see {@link #defaults}. 169 * </p> 170 */ 171 public Uri sound; 172 173 /** 174 * Use this constant as the value for audioStreamType to request that 175 * the default stream type for notifications be used. Currently the 176 * default stream type is STREAM_RING. 177 */ 178 public static final int STREAM_DEFAULT = -1; 179 180 /** 181 * The audio stream type to use when playing the sound. 182 * Should be one of the STREAM_ constants from 183 * {@link android.media.AudioManager}. 184 */ 185 public int audioStreamType = STREAM_DEFAULT; 186 187 188 /** 189 * The pattern with which to vibrate. 190 * 191 * <p> 192 * To vibrate the default pattern, see {@link #defaults}. 193 * </p> 194 * 195 * @see android.os.Vibrator#vibrate(long[],int) 196 */ 197 public long[] vibrate; 198 199 /** 200 * The color of the led. The hardware will do its best approximation. 201 * 202 * @see #FLAG_SHOW_LIGHTS 203 * @see #flags 204 */ 205 public int ledARGB; 206 207 /** 208 * The number of milliseconds for the LED to be on while it's flashing. 209 * The hardware will do its best approximation. 210 * 211 * @see #FLAG_SHOW_LIGHTS 212 * @see #flags 213 */ 214 public int ledOnMS; 215 216 /** 217 * The number of milliseconds for the LED to be off while it's flashing. 218 * The hardware will do its best approximation. 219 * 220 * @see #FLAG_SHOW_LIGHTS 221 * @see #flags 222 */ 223 public int ledOffMS; 224 225 /** 226 * Specifies which values should be taken from the defaults. 227 * <p> 228 * To set, OR the desired from {@link #DEFAULT_SOUND}, 229 * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default 230 * values, use {@link #DEFAULT_ALL}. 231 * </p> 232 */ 233 public int defaults; 234 235 236 /** 237 * Bit to be bitwise-ored into the {@link #flags} field that should be 238 * set if you want the LED on for this notification. 239 * <ul> 240 * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB 241 * or 0 for both ledOnMS and ledOffMS.</li> 242 * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li> 243 * <li>To flash the LED, pass the number of milliseconds that it should 244 * be on and off to ledOnMS and ledOffMS.</li> 245 * </ul> 246 * <p> 247 * Since hardware varies, you are not guaranteed that any of the values 248 * you pass are honored exactly. Use the system defaults (TODO) if possible 249 * because they will be set to values that work on any given hardware. 250 * <p> 251 * The alpha channel must be set for forward compatibility. 252 * 253 */ 254 public static final int FLAG_SHOW_LIGHTS = 0x00000001; 255 256 /** 257 * Bit to be bitwise-ored into the {@link #flags} field that should be 258 * set if this notification is in reference to something that is ongoing, 259 * like a phone call. It should not be set if this notification is in 260 * reference to something that happened at a particular point in time, 261 * like a missed phone call. 262 */ 263 public static final int FLAG_ONGOING_EVENT = 0x00000002; 264 265 /** 266 * Bit to be bitwise-ored into the {@link #flags} field that if set, 267 * the audio will be repeated until the notification is 268 * cancelled or the notification window is opened. 269 */ 270 public static final int FLAG_INSISTENT = 0x00000004; 271 272 /** 273 * Bit to be bitwise-ored into the {@link #flags} field that should be 274 * set if you want the sound and/or vibration play each time the 275 * notification is sent, even if it has not been canceled before that. 276 */ 277 public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008; 278 279 /** 280 * Bit to be bitwise-ored into the {@link #flags} field that should be 281 * set if the notification should be canceled when it is clicked by the 282 * user. On tablets, the 283 */ 284 public static final int FLAG_AUTO_CANCEL = 0x00000010; 285 286 /** 287 * Bit to be bitwise-ored into the {@link #flags} field that should be 288 * set if the notification should not be canceled when the user clicks 289 * the Clear all button. 290 */ 291 public static final int FLAG_NO_CLEAR = 0x00000020; 292 293 /** 294 * Bit to be bitwise-ored into the {@link #flags} field that should be 295 * set if this notification represents a currently running service. This 296 * will normally be set for you by {@link Service#startForeground}. 297 */ 298 public static final int FLAG_FOREGROUND_SERVICE = 0x00000040; 299 300 /** 301 * Bit to be bitwise-ored into the {@link #flags} field that should be set if this notification 302 * represents a high-priority event that may be shown to the user even if notifications are 303 * otherwise unavailable (that is, when the status bar is hidden). This flag is ideally used 304 * in conjunction with {@link #fullScreenIntent}. 305 */ 306 public static final int FLAG_HIGH_PRIORITY = 0x00000080; 307 308 public int flags; 309 310 /** 311 * Constructs a Notification object with everything set to 0. 312 * You might want to consider using {@link Builder} instead. 313 */ 314 public Notification() 315 { 316 this.when = System.currentTimeMillis(); 317 } 318 319 /** 320 * @hide 321 */ 322 public Notification(Context context, int icon, CharSequence tickerText, long when, 323 CharSequence contentTitle, CharSequence contentText, Intent contentIntent) 324 { 325 this.when = when; 326 this.icon = icon; 327 this.tickerText = tickerText; 328 setLatestEventInfo(context, contentTitle, contentText, 329 PendingIntent.getActivity(context, 0, contentIntent, 0)); 330 } 331 332 /** 333 * Constructs a Notification object with the information needed to 334 * have a status bar icon without the standard expanded view. 335 * 336 * @param icon The resource id of the icon to put in the status bar. 337 * @param tickerText The text that flows by in the status bar when the notification first 338 * activates. 339 * @param when The time to show in the time field. In the System.currentTimeMillis 340 * timebase. 341 * 342 * @deprecated Use {@link Builder} instead. 343 */ 344 @Deprecated 345 public Notification(int icon, CharSequence tickerText, long when) 346 { 347 this.icon = icon; 348 this.tickerText = tickerText; 349 this.when = when; 350 } 351 352 /** 353 * Unflatten the notification from a parcel. 354 */ 355 public Notification(Parcel parcel) 356 { 357 int version = parcel.readInt(); 358 359 when = parcel.readLong(); 360 icon = parcel.readInt(); 361 number = parcel.readInt(); 362 if (parcel.readInt() != 0) { 363 contentIntent = PendingIntent.CREATOR.createFromParcel(parcel); 364 } 365 if (parcel.readInt() != 0) { 366 deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel); 367 } 368 if (parcel.readInt() != 0) { 369 tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 370 } 371 if (parcel.readInt() != 0) { 372 tickerView = RemoteViews.CREATOR.createFromParcel(parcel); 373 } 374 if (parcel.readInt() != 0) { 375 contentView = RemoteViews.CREATOR.createFromParcel(parcel); 376 } 377 if (parcel.readInt() != 0) { 378 largeIcon = Bitmap.CREATOR.createFromParcel(parcel); 379 } 380 defaults = parcel.readInt(); 381 flags = parcel.readInt(); 382 if (parcel.readInt() != 0) { 383 sound = Uri.CREATOR.createFromParcel(parcel); 384 } 385 386 audioStreamType = parcel.readInt(); 387 vibrate = parcel.createLongArray(); 388 ledARGB = parcel.readInt(); 389 ledOnMS = parcel.readInt(); 390 ledOffMS = parcel.readInt(); 391 iconLevel = parcel.readInt(); 392 393 if (parcel.readInt() != 0) { 394 fullScreenIntent = PendingIntent.CREATOR.createFromParcel(parcel); 395 } 396 } 397 398 @Override 399 public Notification clone() { 400 Notification that = new Notification(); 401 402 that.when = this.when; 403 that.icon = this.icon; 404 that.number = this.number; 405 406 // PendingIntents are global, so there's no reason (or way) to clone them. 407 that.contentIntent = this.contentIntent; 408 that.deleteIntent = this.deleteIntent; 409 that.fullScreenIntent = this.fullScreenIntent; 410 411 if (this.tickerText != null) { 412 that.tickerText = this.tickerText.toString(); 413 } 414 if (this.tickerView != null) { 415 that.tickerView = this.tickerView.clone(); 416 } 417 if (this.contentView != null) { 418 that.contentView = this.contentView.clone(); 419 } 420 if (this.largeIcon != null) { 421 that.largeIcon = Bitmap.createBitmap(this.largeIcon); 422 } 423 that.iconLevel = this.iconLevel; 424 that.sound = this.sound; // android.net.Uri is immutable 425 that.audioStreamType = this.audioStreamType; 426 427 final long[] vibrate = this.vibrate; 428 if (vibrate != null) { 429 final int N = vibrate.length; 430 final long[] vib = that.vibrate = new long[N]; 431 System.arraycopy(vibrate, 0, vib, 0, N); 432 } 433 434 that.ledARGB = this.ledARGB; 435 that.ledOnMS = this.ledOnMS; 436 that.ledOffMS = this.ledOffMS; 437 that.defaults = this.defaults; 438 439 that.flags = this.flags; 440 441 return that; 442 } 443 444 public int describeContents() { 445 return 0; 446 } 447 448 /** 449 * Flatten this notification from a parcel. 450 */ 451 public void writeToParcel(Parcel parcel, int flags) 452 { 453 parcel.writeInt(1); 454 455 parcel.writeLong(when); 456 parcel.writeInt(icon); 457 parcel.writeInt(number); 458 if (contentIntent != null) { 459 parcel.writeInt(1); 460 contentIntent.writeToParcel(parcel, 0); 461 } else { 462 parcel.writeInt(0); 463 } 464 if (deleteIntent != null) { 465 parcel.writeInt(1); 466 deleteIntent.writeToParcel(parcel, 0); 467 } else { 468 parcel.writeInt(0); 469 } 470 if (tickerText != null) { 471 parcel.writeInt(1); 472 TextUtils.writeToParcel(tickerText, parcel, flags); 473 } else { 474 parcel.writeInt(0); 475 } 476 if (tickerView != null) { 477 parcel.writeInt(1); 478 tickerView.writeToParcel(parcel, 0); 479 } else { 480 parcel.writeInt(0); 481 } 482 if (contentView != null) { 483 parcel.writeInt(1); 484 contentView.writeToParcel(parcel, 0); 485 } else { 486 parcel.writeInt(0); 487 } 488 if (largeIcon != null) { 489 parcel.writeInt(1); 490 largeIcon.writeToParcel(parcel, 0); 491 } else { 492 parcel.writeInt(0); 493 } 494 495 parcel.writeInt(defaults); 496 parcel.writeInt(this.flags); 497 498 if (sound != null) { 499 parcel.writeInt(1); 500 sound.writeToParcel(parcel, 0); 501 } else { 502 parcel.writeInt(0); 503 } 504 parcel.writeInt(audioStreamType); 505 parcel.writeLongArray(vibrate); 506 parcel.writeInt(ledARGB); 507 parcel.writeInt(ledOnMS); 508 parcel.writeInt(ledOffMS); 509 parcel.writeInt(iconLevel); 510 511 if (fullScreenIntent != null) { 512 parcel.writeInt(1); 513 fullScreenIntent.writeToParcel(parcel, 0); 514 } else { 515 parcel.writeInt(0); 516 } 517 } 518 519 /** 520 * Parcelable.Creator that instantiates Notification objects 521 */ 522 public static final Parcelable.Creator<Notification> CREATOR 523 = new Parcelable.Creator<Notification>() 524 { 525 public Notification createFromParcel(Parcel parcel) 526 { 527 return new Notification(parcel); 528 } 529 530 public Notification[] newArray(int size) 531 { 532 return new Notification[size]; 533 } 534 }; 535 536 /** 537 * Sets the {@link #contentView} field to be a view with the standard "Latest Event" 538 * layout. 539 * 540 * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields 541 * in the view.</p> 542 * @param context The context for your application / activity. 543 * @param contentTitle The title that goes in the expanded entry. 544 * @param contentText The text that goes in the expanded entry. 545 * @param contentIntent The intent to launch when the user clicks the expanded notification. 546 * If this is an activity, it must include the 547 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 548 * that you take care of task management as described in the 549 * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back 550 * Stack</a> document. 551 * 552 * @deprecated Use {@link Builder} instead. 553 */ 554 @Deprecated 555 public void setLatestEventInfo(Context context, 556 CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) { 557 RemoteViews contentView = new RemoteViews(context.getPackageName(), 558 R.layout.status_bar_latest_event_content); 559 if (this.icon != 0) { 560 contentView.setImageViewResource(R.id.icon, this.icon); 561 } 562 if (contentTitle != null) { 563 contentView.setTextViewText(R.id.title, contentTitle); 564 } 565 if (contentText != null) { 566 contentView.setTextViewText(R.id.text, contentText); 567 } 568 if (this.when != 0) { 569 contentView.setLong(R.id.time, "setTime", when); 570 } 571 572 this.contentView = contentView; 573 this.contentIntent = contentIntent; 574 } 575 576 @Override 577 public String toString() { 578 StringBuilder sb = new StringBuilder(); 579 sb.append("Notification(contentView="); 580 if (contentView != null) { 581 sb.append(contentView.getPackage()); 582 sb.append("/0x"); 583 sb.append(Integer.toHexString(contentView.getLayoutId())); 584 } else { 585 sb.append("null"); 586 } 587 sb.append(" vibrate="); 588 if (this.vibrate != null) { 589 int N = this.vibrate.length-1; 590 sb.append("["); 591 for (int i=0; i<N; i++) { 592 sb.append(this.vibrate[i]); 593 sb.append(','); 594 } 595 if (N != -1) { 596 sb.append(this.vibrate[N]); 597 } 598 sb.append("]"); 599 } else if ((this.defaults & DEFAULT_VIBRATE) != 0) { 600 sb.append("default"); 601 } else { 602 sb.append("null"); 603 } 604 sb.append(",sound="); 605 if (this.sound != null) { 606 sb.append(this.sound.toString()); 607 } else if ((this.defaults & DEFAULT_SOUND) != 0) { 608 sb.append("default"); 609 } else { 610 sb.append("null"); 611 } 612 sb.append(",defaults=0x"); 613 sb.append(Integer.toHexString(this.defaults)); 614 sb.append(",flags=0x"); 615 sb.append(Integer.toHexString(this.flags)); 616 if ((this.flags & FLAG_HIGH_PRIORITY) != 0) { 617 sb.append("!!!1!one!"); 618 } 619 sb.append(")"); 620 return sb.toString(); 621 } 622 623 /** 624 * Builder class for {@link Notification} objects. Allows easier control over 625 * all the flags, as well as help constructing the typical notification layouts. 626 */ 627 public static class Builder { 628 private Context mContext; 629 630 private long mWhen; 631 private int mSmallIcon; 632 private int mSmallIconLevel; 633 private int mNumber; 634 private CharSequence mContentTitle; 635 private CharSequence mContentText; 636 private CharSequence mContentInfo; 637 private PendingIntent mContentIntent; 638 private RemoteViews mContentView; 639 private PendingIntent mDeleteIntent; 640 private PendingIntent mFullScreenIntent; 641 private CharSequence mTickerText; 642 private RemoteViews mTickerView; 643 private Bitmap mLargeIcon; 644 private Uri mSound; 645 private int mAudioStreamType; 646 private long[] mVibrate; 647 private int mLedArgb; 648 private int mLedOnMs; 649 private int mLedOffMs; 650 private int mDefaults; 651 private int mFlags; 652 private int mProgressMax; 653 private int mProgress; 654 private boolean mProgressIndeterminate; 655 656 /** 657 * Constructor. 658 * 659 * Automatically sets the when field to {@link System#currentTimeMillis() 660 * System.currentTimeMllis()} and the audio stream to the {@link #STREAM_DEFAULT}. 661 * 662 * @param context A {@link Context} that will be used to construct the 663 * RemoteViews. The Context will not be held past the lifetime of this 664 * Builder object. 665 */ 666 public Builder(Context context) { 667 mContext = context; 668 669 // Set defaults to match the defaults of a Notification 670 mWhen = System.currentTimeMillis(); 671 mAudioStreamType = STREAM_DEFAULT; 672 } 673 674 /** 675 * Set the time that the event occurred. Notifications in the panel are 676 * sorted by this time. 677 */ 678 public Builder setWhen(long when) { 679 mWhen = when; 680 return this; 681 } 682 683 /** 684 * Set the small icon to use in the notification layouts. Different classes of devices 685 * may return different sizes. See the UX guidelines for more information on how to 686 * design these icons. 687 * 688 * @param icon A resource ID in the application's package of the drawble to use. 689 */ 690 public Builder setSmallIcon(int icon) { 691 mSmallIcon = icon; 692 return this; 693 } 694 695 /** 696 * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional 697 * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable 698 * LevelListDrawable}. 699 * 700 * @param icon A resource ID in the application's package of the drawble to use. 701 * @param level The level to use for the icon. 702 * 703 * @see android.graphics.drawable.LevelListDrawable 704 */ 705 public Builder setSmallIcon(int icon, int level) { 706 mSmallIcon = icon; 707 mSmallIconLevel = level; 708 return this; 709 } 710 711 /** 712 * Set the title (first row) of the notification, in a standard notification. 713 */ 714 public Builder setContentTitle(CharSequence title) { 715 mContentTitle = title; 716 return this; 717 } 718 719 /** 720 * Set the text (second row) of the notification, in a standard notification. 721 */ 722 public Builder setContentText(CharSequence text) { 723 mContentText = text; 724 return this; 725 } 726 727 /** 728 * Set the large number at the right-hand side of the notification. This is 729 * equivalent to setContentInfo, although it might show the number in a different 730 * font size for readability. 731 */ 732 public Builder setNumber(int number) { 733 mNumber = number; 734 return this; 735 } 736 737 /** 738 * Set the large text at the right-hand side of the notification. 739 */ 740 public Builder setContentInfo(CharSequence info) { 741 mContentInfo = info; 742 return this; 743 } 744 745 /** 746 * Set the progress this notification represents, which may be 747 * represented as a {@link ProgressBar}. 748 */ 749 public Builder setProgress(int max, int progress, boolean indeterminate) { 750 mProgressMax = max; 751 mProgress = progress; 752 mProgressIndeterminate = indeterminate; 753 return this; 754 } 755 756 /** 757 * Supply a custom RemoteViews to use instead of the standard one. 758 */ 759 public Builder setContent(RemoteViews views) { 760 mContentView = views; 761 return this; 762 } 763 764 /** 765 * Supply a {@link PendingIntent} to send when the notification is clicked. 766 * If you do not supply an intent, you can now add PendingIntents to individual 767 * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent 768 * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. 769 */ 770 public Builder setContentIntent(PendingIntent intent) { 771 mContentIntent = intent; 772 return this; 773 } 774 775 /** 776 * Supply a {@link PendingIntent} to send when the notification is cleared by the user 777 * directly from the notification panel. For example, this intent is sent when the user 778 * clicks the "Clear all" button, or the individual "X" buttons on notifications. This 779 * intent is not sent when the application calls {@link NotificationManager#cancel 780 * NotificationManager.cancel(int)}. 781 */ 782 public Builder setDeleteIntent(PendingIntent intent) { 783 mDeleteIntent = intent; 784 return this; 785 } 786 787 /** 788 * An intent to launch instead of posting the notification to the status bar. 789 * Only for use with extremely high-priority notifications demanding the user's 790 * <strong>immediate</strong> attention, such as an incoming phone call or 791 * alarm clock that the user has explicitly set to a particular time. 792 * If this facility is used for something else, please give the user an option 793 * to turn it off and use a normal notification, as this can be extremely 794 * disruptive. 795 * 796 * @param intent The pending intent to launch. 797 * @param highPriority Passing true will cause this notification to be sent 798 * even if other notifications are suppressed. 799 */ 800 public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { 801 mFullScreenIntent = intent; 802 setFlag(FLAG_HIGH_PRIORITY, highPriority); 803 return this; 804 } 805 806 /** 807 * Set the text that is displayed in the status bar when the notification first 808 * arrives. 809 */ 810 public Builder setTicker(CharSequence tickerText) { 811 mTickerText = tickerText; 812 return this; 813 } 814 815 /** 816 * Set the text that is displayed in the status bar when the notification first 817 * arrives, and also a RemoteViews object that may be displayed instead on some 818 * devices. 819 */ 820 public Builder setTicker(CharSequence tickerText, RemoteViews views) { 821 mTickerText = tickerText; 822 mTickerView = views; 823 return this; 824 } 825 826 /** 827 * Set the large icon that is shown in the ticker and notification. 828 */ 829 public Builder setLargeIcon(Bitmap icon) { 830 mLargeIcon = icon; 831 return this; 832 } 833 834 /** 835 * Set the sound to play. It will play on the default stream. 836 */ 837 public Builder setSound(Uri sound) { 838 mSound = sound; 839 mAudioStreamType = STREAM_DEFAULT; 840 return this; 841 } 842 843 /** 844 * Set the sound to play. It will play on the stream you supply. 845 * 846 * @see #STREAM_DEFAULT 847 * @see AudioManager for the <code>STREAM_</code> constants. 848 */ 849 public Builder setSound(Uri sound, int streamType) { 850 mSound = sound; 851 mAudioStreamType = streamType; 852 return this; 853 } 854 855 /** 856 * Set the vibration pattern to use. 857 * 858 * @see android.os.Vibrator for a discussion of the <code>pattern</code> 859 * parameter. 860 */ 861 public Builder setVibrate(long[] pattern) { 862 mVibrate = pattern; 863 return this; 864 } 865 866 /** 867 * Set the argb value that you would like the LED on the device to blnk, as well as the 868 * rate. The rate is specified in terms of the number of milliseconds to be on 869 * and then the number of milliseconds to be off. 870 */ 871 public Builder setLights(int argb, int onMs, int offMs) { 872 mLedArgb = argb; 873 mLedOnMs = onMs; 874 mLedOffMs = offMs; 875 return this; 876 } 877 878 /** 879 * Set whether this is an ongoing notification. 880 * 881 * <p>Ongoing notifications differ from regular notifications in the following ways: 882 * <ul> 883 * <li>Ongoing notifications are sorted above the regular notifications in the 884 * notification panel.</li> 885 * <li>Ongoing notifications do not have an 'X' close button, and are not affected 886 * by the "Clear all" button. 887 * </ul> 888 */ 889 public Builder setOngoing(boolean ongoing) { 890 setFlag(FLAG_ONGOING_EVENT, ongoing); 891 return this; 892 } 893 894 /** 895 * Set this flag if you would only like the sound, vibrate 896 * and ticker to be played if the notification is not already showing. 897 */ 898 public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { 899 setFlag(FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); 900 return this; 901 } 902 903 /** 904 * Setting this flag will make it so the notification is automatically 905 * canceled when the user clicks it in the panel. The PendingIntent 906 * set with {@link #setDeleteIntent} will be broadcast when the notification 907 * is canceled. 908 */ 909 public Builder setAutoCancel(boolean autoCancel) { 910 setFlag(FLAG_AUTO_CANCEL, autoCancel); 911 return this; 912 } 913 914 /** 915 * Set the default notification options that will be used. 916 * <p> 917 * The value should be one or more of the following fields combined with 918 * bitwise-or: 919 * {@link #DEFAULT_SOUND}, {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. 920 * <p> 921 * For all default values, use {@link #DEFAULT_ALL}. 922 */ 923 public Builder setDefaults(int defaults) { 924 mDefaults = defaults; 925 return this; 926 } 927 928 private void setFlag(int mask, boolean value) { 929 if (value) { 930 mFlags |= mask; 931 } else { 932 mFlags &= ~mask; 933 } 934 } 935 936 private RemoteViews makeRemoteViews(int resId) { 937 RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); 938 boolean hasLine3 = false; 939 if (mSmallIcon != 0) { 940 contentView.setImageViewResource(R.id.icon, mSmallIcon); 941 contentView.setViewVisibility(R.id.icon, View.VISIBLE); 942 } else { 943 contentView.setViewVisibility(R.id.icon, View.GONE); 944 } 945 if (mContentTitle != null) { 946 contentView.setTextViewText(R.id.title, mContentTitle); 947 } 948 if (mContentText != null) { 949 contentView.setTextViewText(R.id.text, mContentText); 950 hasLine3 = true; 951 } 952 if (mContentInfo != null) { 953 contentView.setTextViewText(R.id.info, mContentInfo); 954 contentView.setViewVisibility(R.id.info, View.VISIBLE); 955 hasLine3 = true; 956 } else if (mNumber > 0) { 957 final int tooBig = mContext.getResources().getInteger( 958 R.integer.status_bar_notification_info_maxnum); 959 if (mNumber > tooBig) { 960 contentView.setTextViewText(R.id.info, mContext.getResources().getString( 961 R.string.status_bar_notification_info_overflow)); 962 } else { 963 NumberFormat f = NumberFormat.getIntegerInstance(); 964 contentView.setTextViewText(R.id.info, f.format(mNumber)); 965 } 966 contentView.setViewVisibility(R.id.info, View.VISIBLE); 967 hasLine3 = true; 968 } else { 969 contentView.setViewVisibility(R.id.info, View.GONE); 970 } 971 if (mProgressMax != 0 || mProgressIndeterminate) { 972 contentView.setProgressBar( 973 R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); 974 contentView.setViewVisibility(R.id.progress, View.VISIBLE); 975 } else { 976 contentView.setViewVisibility(R.id.progress, View.GONE); 977 } 978 if (mWhen != 0) { 979 contentView.setLong(R.id.time, "setTime", mWhen); 980 } 981 contentView.setViewVisibility(R.id.line3, hasLine3 ? View.VISIBLE : View.GONE); 982 return contentView; 983 } 984 985 private RemoteViews makeContentView() { 986 if (mContentView != null) { 987 return mContentView; 988 } else { 989 return makeRemoteViews(mLargeIcon == null 990 ? R.layout.status_bar_latest_event_content 991 : R.layout.status_bar_latest_event_content_large_icon); 992 } 993 } 994 995 private RemoteViews makeTickerView() { 996 if (mTickerView != null) { 997 return mTickerView; 998 } else { 999 if (mContentView == null) { 1000 return makeRemoteViews(mLargeIcon == null 1001 ? R.layout.status_bar_latest_event_ticker 1002 : R.layout.status_bar_latest_event_ticker_large_icon); 1003 } else { 1004 return null; 1005 } 1006 } 1007 } 1008 1009 /** 1010 * Combine all of the options that have been set and return a new {@link Notification} 1011 * object. 1012 */ 1013 public Notification getNotification() { 1014 Notification n = new Notification(); 1015 n.when = mWhen; 1016 n.icon = mSmallIcon; 1017 n.iconLevel = mSmallIconLevel; 1018 n.number = mNumber; 1019 n.contentView = makeContentView(); 1020 n.contentIntent = mContentIntent; 1021 n.deleteIntent = mDeleteIntent; 1022 n.fullScreenIntent = mFullScreenIntent; 1023 n.tickerText = mTickerText; 1024 n.tickerView = makeTickerView(); 1025 n.largeIcon = mLargeIcon; 1026 n.sound = mSound; 1027 n.audioStreamType = mAudioStreamType; 1028 n.vibrate = mVibrate; 1029 n.ledARGB = mLedArgb; 1030 n.ledOnMS = mLedOnMs; 1031 n.ledOffMS = mLedOffMs; 1032 n.defaults = mDefaults; 1033 n.flags = mFlags; 1034 if (mLedOnMs != 0 && mLedOffMs != 0) { 1035 n.flags |= FLAG_SHOW_LIGHTS; 1036 } 1037 if ((mDefaults & DEFAULT_LIGHTS) != 0) { 1038 n.flags |= FLAG_SHOW_LIGHTS; 1039 } 1040 return n; 1041 } 1042 } 1043 } 1044