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