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 */ Notification()314 public Notification() 315 { 316 this.when = System.currentTimeMillis(); 317 } 318 319 /** 320 * @hide 321 */ Notification(Context context, int icon, CharSequence tickerText, long when, CharSequence contentTitle, CharSequence contentText, Intent contentIntent)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 Notification(int icon, CharSequence tickerText, long when)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 */ Notification(Parcel parcel)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 clone()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 describeContents()444 public int describeContents() { 445 return 0; 446 } 447 448 /** 449 * Flatten this notification from a parcel. 450 */ writeToParcel(Parcel parcel, int flags)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 setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent)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 toString()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 */ Builder(Context context)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 */ setWhen(long when)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 */ setSmallIcon(int icon)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 */ setSmallIcon(int icon, int level)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 */ setContentTitle(CharSequence title)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 */ setContentText(CharSequence text)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 */ setNumber(int number)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 */ setContentInfo(CharSequence info)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 */ setProgress(int max, int progress, boolean indeterminate)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 */ setContent(RemoteViews views)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 */ setContentIntent(PendingIntent intent)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 */ setDeleteIntent(PendingIntent intent)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 */ setFullScreenIntent(PendingIntent intent, boolean highPriority)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 */ setTicker(CharSequence tickerText)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 */ setTicker(CharSequence tickerText, RemoteViews views)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 */ setLargeIcon(Bitmap icon)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 */ setSound(Uri sound)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 */ setSound(Uri sound, int streamType)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 */ setVibrate(long[] pattern)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 */ setLights(int argb, int onMs, int offMs)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 */ setOngoing(boolean ongoing)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 */ setOnlyAlertOnce(boolean onlyAlertOnce)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 */ setAutoCancel(boolean autoCancel)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 */ setDefaults(int defaults)923 public Builder setDefaults(int defaults) { 924 mDefaults = defaults; 925 return this; 926 } 927 setFlag(int mask, boolean value)928 private void setFlag(int mask, boolean value) { 929 if (value) { 930 mFlags |= mask; 931 } else { 932 mFlags &= ~mask; 933 } 934 } 935 makeRemoteViews(int resId)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 makeContentView()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 makeTickerView()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 */ getNotification()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