Home | History | Annotate | Download | only in app
      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      */
    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      */
    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      */
    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      */
    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 
    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 
    398     public int describeContents() {
    399         return 0;
    400     }
    401 
    402     /**
    403      * Flatten this notification from a parcel.
    404      */
    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      */
    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
    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