Notification.java revision e46cbd379a3c19708c7f7e5d3f35e2c596de0c46
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 java.util.Date; 20 21import android.app.PendingIntent; 22import android.content.Context; 23import android.content.Intent; 24import android.media.AudioManager; 25import android.net.Uri; 26import android.os.Parcel; 27import android.os.Parcelable; 28import android.text.TextUtils; 29import android.text.format.DateFormat; 30import android.text.format.DateUtils; 31import android.widget.RemoteViews; 32 33/** 34 * A class that represents how a persistent notification is to be presented to 35 * the user using the {@link android.app.NotificationManager}. 36 * 37 * <p>For a guide to creating notifications, see the 38 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status 39 * Bar Notifications</a> document in the Dev Guide.</p> 40 */ 41public class Notification implements Parcelable 42{ 43 /** 44 * Use all default values (where applicable). 45 */ 46 public static final int DEFAULT_ALL = ~0; 47 48 /** 49 * Use the default notification sound. This will ignore any given 50 * {@link #sound}. 51 * 52 * @see #defaults 53 */ 54 public static final int DEFAULT_SOUND = 1; 55 56 /** 57 * Use the default notification vibrate. This will ignore any given 58 * {@link #vibrate}. Using phone vibration requires the 59 * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. 60 * 61 * @see #defaults 62 */ 63 public static final int DEFAULT_VIBRATE = 2; 64 65 /** 66 * Use the default notification lights. This will ignore the 67 * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or 68 * {@link #ledOnMS}. 69 * 70 * @see #defaults 71 */ 72 public static final int DEFAULT_LIGHTS = 4; 73 74 /** 75 * The timestamp for the notification. The icons and expanded views 76 * are sorted by this key. 77 */ 78 public long when; 79 80 /** 81 * The resource id of a drawable to use as the icon in the status bar. 82 */ 83 public int icon; 84 85 /** 86 * The number of events that this notification represents. For example, in a new mail 87 * notification, this could be the number of unread messages. This number is superimposed over 88 * the icon in the status bar. If the number is 0 or negative, it is not shown in the status 89 * bar. 90 */ 91 public int number; 92 93 /** 94 * The intent to execute when the expanded status entry is clicked. If 95 * this is an activity, it must include the 96 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 97 * that you take care of task management as described in the <em>Activities and Tasks</em> 98 * section of the <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application 99 * Fundamentals</a> document. 100 */ 101 public PendingIntent contentIntent; 102 103 /** 104 * The intent to execute when the status entry is deleted by the user 105 * with the "Clear All Notifications" button. This probably shouldn't 106 * be launching an activity since several of those will be sent at the 107 * same time. 108 */ 109 public PendingIntent deleteIntent; 110 111 /** 112 * An intent to launch instead of posting the notification to the status bar. Only for use with 113 * extremely high-priority notifications demanding the user's attention, such as an incoming 114 * call (handled in the core Android Phone app with a full-screen Activity). 115 * Use with {@link #FLAG_HIGH_PRIORITY} to ensure that this notification will reach the user 116 * even when other notifications are suppressed. 117 */ 118 public PendingIntent fullScreenIntent; 119 120 /** 121 * Text to scroll across the screen when this item is added to 122 * the status bar. 123 */ 124 public CharSequence tickerText; 125 126 /** 127 * The view that will represent this notification in the expanded status bar. 128 */ 129 public RemoteViews contentView; 130 131 /** 132 * If the icon in the status bar is to have more than one level, you can set this. Otherwise, 133 * leave it at its default value of 0. 134 * 135 * @see android.widget.ImageView#setImageLevel 136 * @see android.graphics.drawable#setLevel 137 */ 138 public int iconLevel; 139 140 /** 141 * The sound to play. 142 * 143 * <p> 144 * To play the default notification sound, see {@link #defaults}. 145 * </p> 146 */ 147 public Uri sound; 148 149 /** 150 * Use this constant as the value for audioStreamType to request that 151 * the default stream type for notifications be used. Currently the 152 * default stream type is STREAM_RING. 153 */ 154 public static final int STREAM_DEFAULT = -1; 155 156 /** 157 * The audio stream type to use when playing the sound. 158 * Should be one of the STREAM_ constants from 159 * {@link android.media.AudioManager}. 160 */ 161 public int audioStreamType = STREAM_DEFAULT; 162 163 164 /** 165 * The pattern with which to vibrate. 166 * 167 * <p> 168 * To vibrate the default pattern, see {@link #defaults}. 169 * </p> 170 * 171 * @see android.os.Vibrator#vibrate(long[],int) 172 */ 173 public long[] vibrate; 174 175 /** 176 * The color of the led. The hardware will do its best approximation. 177 * 178 * @see #FLAG_SHOW_LIGHTS 179 * @see #flags 180 */ 181 public int ledARGB; 182 183 /** 184 * The number of milliseconds for the LED to be on while it's flashing. 185 * The hardware will do its best approximation. 186 * 187 * @see #FLAG_SHOW_LIGHTS 188 * @see #flags 189 */ 190 public int ledOnMS; 191 192 /** 193 * The number of milliseconds for the LED to be off while it's flashing. 194 * The hardware will do its best approximation. 195 * 196 * @see #FLAG_SHOW_LIGHTS 197 * @see #flags 198 */ 199 public int ledOffMS; 200 201 /** 202 * Specifies which values should be taken from the defaults. 203 * <p> 204 * To set, OR the desired from {@link #DEFAULT_SOUND}, 205 * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default 206 * values, use {@link #DEFAULT_ALL}. 207 * </p> 208 */ 209 public int defaults; 210 211 212 /** 213 * Bit to be bitwise-ored into the {@link #flags} field that should be 214 * set if you want the LED on for this notification. 215 * <ul> 216 * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB 217 * or 0 for both ledOnMS and ledOffMS.</li> 218 * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li> 219 * <li>To flash the LED, pass the number of milliseconds that it should 220 * be on and off to ledOnMS and ledOffMS.</li> 221 * </ul> 222 * <p> 223 * Since hardware varies, you are not guaranteed that any of the values 224 * you pass are honored exactly. Use the system defaults (TODO) if possible 225 * because they will be set to values that work on any given hardware. 226 * <p> 227 * The alpha channel must be set for forward compatibility. 228 * 229 */ 230 public static final int FLAG_SHOW_LIGHTS = 0x00000001; 231 232 /** 233 * Bit to be bitwise-ored into the {@link #flags} field that should be 234 * set if this notification is in reference to something that is ongoing, 235 * like a phone call. It should not be set if this notification is in 236 * reference to something that happened at a particular point in time, 237 * like a missed phone call. 238 */ 239 public static final int FLAG_ONGOING_EVENT = 0x00000002; 240 241 /** 242 * Bit to be bitwise-ored into the {@link #flags} field that if set, 243 * the audio will be repeated until the notification is 244 * cancelled or the notification window is opened. 245 */ 246 public static final int FLAG_INSISTENT = 0x00000004; 247 248 /** 249 * Bit to be bitwise-ored into the {@link #flags} field that should be 250 * set if you want the sound and/or vibration play each time the 251 * notification is sent, even if it has not been canceled before that. 252 */ 253 public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008; 254 255 /** 256 * Bit to be bitwise-ored into the {@link #flags} field that should be 257 * set if the notification should be canceled when it is clicked by the 258 * user. 259 */ 260 public static final int FLAG_AUTO_CANCEL = 0x00000010; 261 262 /** 263 * Bit to be bitwise-ored into the {@link #flags} field that should be 264 * set if the notification should not be canceled when the user clicks 265 * the Clear all button. 266 */ 267 public static final int FLAG_NO_CLEAR = 0x00000020; 268 269 /** 270 * Bit to be bitwise-ored into the {@link #flags} field that should be 271 * set if this notification represents a currently running service. This 272 * will normally be set for you by {@link Service#startForeground}. 273 */ 274 public static final int FLAG_FOREGROUND_SERVICE = 0x00000040; 275 276 /** 277 * Bit to be bitwise-ored into the {@link #flags} field that should be set if this notification 278 * represents a high-priority event that may be shown to the user even if notifications are 279 * otherwise unavailable (that is, when the status bar is hidden). This flag is ideally used 280 * in conjunction with {@link #fullScreenIntent}. 281 */ 282 public static final int FLAG_HIGH_PRIORITY = 0x00000080; 283 284 public int flags; 285 286 /** 287 * Constructs a Notification object with everything set to 0. 288 */ 289 public Notification() 290 { 291 this.when = System.currentTimeMillis(); 292 } 293 294 /** 295 * @deprecated use {@link #Notification(int,CharSequence,long)} and {@link #setLatestEventInfo}. 296 * @hide 297 */ 298 public Notification(Context context, int icon, CharSequence tickerText, long when, 299 CharSequence contentTitle, CharSequence contentText, Intent contentIntent) 300 { 301 this.when = when; 302 this.icon = icon; 303 this.tickerText = tickerText; 304 setLatestEventInfo(context, contentTitle, contentText, 305 PendingIntent.getActivity(context, 0, contentIntent, 0)); 306 } 307 308 /** 309 * Constructs a Notification object with the information needed to 310 * have a status bar icon without the standard expanded view. 311 * 312 * @param icon The resource id of the icon to put in the status bar. 313 * @param tickerText The text that flows by in the status bar when the notification first 314 * activates. 315 * @param when The time to show in the time field. In the System.currentTimeMillis 316 * timebase. 317 */ 318 public Notification(int icon, CharSequence tickerText, long when) 319 { 320 this.icon = icon; 321 this.tickerText = tickerText; 322 this.when = when; 323 } 324 325 /** 326 * Unflatten the notification from a parcel. 327 */ 328 public Notification(Parcel parcel) 329 { 330 int version = parcel.readInt(); 331 332 when = parcel.readLong(); 333 icon = parcel.readInt(); 334 number = parcel.readInt(); 335 if (parcel.readInt() != 0) { 336 contentIntent = PendingIntent.CREATOR.createFromParcel(parcel); 337 } 338 if (parcel.readInt() != 0) { 339 deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel); 340 } 341 if (parcel.readInt() != 0) { 342 tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); 343 } 344 if (parcel.readInt() != 0) { 345 contentView = RemoteViews.CREATOR.createFromParcel(parcel); 346 } 347 defaults = parcel.readInt(); 348 flags = parcel.readInt(); 349 if (parcel.readInt() != 0) { 350 sound = Uri.CREATOR.createFromParcel(parcel); 351 } 352 353 audioStreamType = parcel.readInt(); 354 vibrate = parcel.createLongArray(); 355 ledARGB = parcel.readInt(); 356 ledOnMS = parcel.readInt(); 357 ledOffMS = parcel.readInt(); 358 iconLevel = parcel.readInt(); 359 360 if (parcel.readInt() != 0) { 361 fullScreenIntent = PendingIntent.CREATOR.createFromParcel(parcel); 362 } 363 } 364 365 public Notification clone() { 366 Notification that = new Notification(); 367 368 that.when = this.when; 369 that.icon = this.icon; 370 that.number = this.number; 371 372 // PendingIntents are global, so there's no reason (or way) to clone them. 373 that.contentIntent = this.contentIntent; 374 that.deleteIntent = this.deleteIntent; 375 that.fullScreenIntent = this.fullScreenIntent; 376 377 if (this.tickerText != null) { 378 that.tickerText = this.tickerText.toString(); 379 } 380 if (this.contentView != null) { 381 that.contentView = this.contentView.clone(); 382 } 383 that.iconLevel = that.iconLevel; 384 that.sound = this.sound; // android.net.Uri is immutable 385 that.audioStreamType = this.audioStreamType; 386 387 final long[] vibrate = this.vibrate; 388 if (vibrate != null) { 389 final int N = vibrate.length; 390 final long[] vib = that.vibrate = new long[N]; 391 System.arraycopy(vibrate, 0, vib, 0, N); 392 } 393 394 that.ledARGB = this.ledARGB; 395 that.ledOnMS = this.ledOnMS; 396 that.ledOffMS = this.ledOffMS; 397 that.defaults = this.defaults; 398 399 that.flags = this.flags; 400 401 return that; 402 } 403 404 public int describeContents() { 405 return 0; 406 } 407 408 /** 409 * Flatten this notification from a parcel. 410 */ 411 public void writeToParcel(Parcel parcel, int flags) 412 { 413 parcel.writeInt(1); 414 415 parcel.writeLong(when); 416 parcel.writeInt(icon); 417 parcel.writeInt(number); 418 if (contentIntent != null) { 419 parcel.writeInt(1); 420 contentIntent.writeToParcel(parcel, 0); 421 } else { 422 parcel.writeInt(0); 423 } 424 if (deleteIntent != null) { 425 parcel.writeInt(1); 426 deleteIntent.writeToParcel(parcel, 0); 427 } else { 428 parcel.writeInt(0); 429 } 430 if (tickerText != null) { 431 parcel.writeInt(1); 432 TextUtils.writeToParcel(tickerText, parcel, flags); 433 } else { 434 parcel.writeInt(0); 435 } 436 if (contentView != null) { 437 parcel.writeInt(1); 438 contentView.writeToParcel(parcel, 0); 439 } else { 440 parcel.writeInt(0); 441 } 442 443 parcel.writeInt(defaults); 444 parcel.writeInt(this.flags); 445 446 if (sound != null) { 447 parcel.writeInt(1); 448 sound.writeToParcel(parcel, 0); 449 } else { 450 parcel.writeInt(0); 451 } 452 parcel.writeInt(audioStreamType); 453 parcel.writeLongArray(vibrate); 454 parcel.writeInt(ledARGB); 455 parcel.writeInt(ledOnMS); 456 parcel.writeInt(ledOffMS); 457 parcel.writeInt(iconLevel); 458 459 if (fullScreenIntent != null) { 460 parcel.writeInt(1); 461 fullScreenIntent.writeToParcel(parcel, 0); 462 } else { 463 parcel.writeInt(0); 464 } 465 } 466 467 /** 468 * Parcelable.Creator that instantiates Notification objects 469 */ 470 public static final Parcelable.Creator<Notification> CREATOR 471 = new Parcelable.Creator<Notification>() 472 { 473 public Notification createFromParcel(Parcel parcel) 474 { 475 return new Notification(parcel); 476 } 477 478 public Notification[] newArray(int size) 479 { 480 return new Notification[size]; 481 } 482 }; 483 484 /** 485 * Sets the {@link #contentView} field to be a view with the standard "Latest Event" 486 * layout. 487 * 488 * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields 489 * in the view.</p> 490 * @param context The context for your application / activity. 491 * @param contentTitle The title that goes in the expanded entry. 492 * @param contentText The text that goes in the expanded entry. 493 * @param contentIntent The intent to launch when the user clicks the expanded notification. 494 * If this is an activity, it must include the 495 * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires 496 * that you take care of task management as described in 497 * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals: Activities and Tasks</a>. 498 */ 499 public void setLatestEventInfo(Context context, 500 CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) { 501 RemoteViews contentView = new RemoteViews(context.getPackageName(), 502 com.android.internal.R.layout.status_bar_latest_event_content); 503 if (this.icon != 0) { 504 contentView.setImageViewResource(com.android.internal.R.id.icon, this.icon); 505 } 506 if (contentTitle != null) { 507 contentView.setTextViewText(com.android.internal.R.id.title, contentTitle); 508 } 509 if (contentText != null) { 510 contentView.setTextViewText(com.android.internal.R.id.text, contentText); 511 } 512 if (this.when != 0) { 513 contentView.setLong(com.android.internal.R.id.time, "setTime", when); 514 } 515 516 this.contentView = contentView; 517 this.contentIntent = contentIntent; 518 } 519 520 @Override 521 public String toString() { 522 StringBuilder sb = new StringBuilder(); 523 sb.append("Notification(vibrate="); 524 if (this.vibrate != null) { 525 int N = this.vibrate.length-1; 526 sb.append("["); 527 for (int i=0; i<N; i++) { 528 sb.append(this.vibrate[i]); 529 sb.append(','); 530 } 531 if (N != -1) { 532 sb.append(this.vibrate[N]); 533 } 534 sb.append("]"); 535 } else if ((this.defaults & DEFAULT_VIBRATE) != 0) { 536 sb.append("default"); 537 } else { 538 sb.append("null"); 539 } 540 sb.append(",sound="); 541 if (this.sound != null) { 542 sb.append(this.sound.toString()); 543 } else if ((this.defaults & DEFAULT_SOUND) != 0) { 544 sb.append("default"); 545 } else { 546 sb.append("null"); 547 } 548 sb.append(",defaults=0x"); 549 sb.append(Integer.toHexString(this.defaults)); 550 sb.append(",flags=0x"); 551 sb.append(Integer.toHexString(this.flags)); 552 if ((this.flags & FLAG_HIGH_PRIORITY) != 0) { 553 sb.append("!!!1!one!"); 554 } 555 sb.append(")"); 556 return sb.toString(); 557 } 558} 559