• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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