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