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 com.android.internal.R;
     20 
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.graphics.Bitmap;
     24 import android.net.Uri;
     25 import android.os.Parcel;
     26 import android.os.Parcelable;
     27 import android.text.TextUtils;
     28 import android.view.View;
     29 import android.widget.ProgressBar;
     30 import android.widget.RemoteViews;
     31 
     32 import java.text.NumberFormat;
     33 
     34 /**
     35  * A class that represents how a persistent notification is to be presented to
     36  * the user using the {@link android.app.NotificationManager}.
     37  *
     38  * <p>The {@link Notification.Builder Notification.Builder} has been added to make it
     39  * easier to construct Notifications.</p>
     40  *
     41  * <div class="special reference">
     42  * <h3>Developer Guides</h3>
     43  * <p>For a guide to creating notifications, read the
     44  * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
     45  * developer guide.</p>
     46  * </div>
     47  */
     48 public class Notification implements Parcelable
     49 {
     50     /**
     51      * Use all default values (where applicable).
     52      */
     53     public static final int DEFAULT_ALL = ~0;
     54 
     55     /**
     56      * Use the default notification sound. This will ignore any given
     57      * {@link #sound}.
     58      *
     59      * @see #defaults
     60      */
     61     public static final int DEFAULT_SOUND = 1;
     62 
     63     /**
     64      * Use the default notification vibrate. This will ignore any given
     65      * {@link #vibrate}. Using phone vibration requires the
     66      * {@link android.Manifest.permission#VIBRATE VIBRATE} permission.
     67      *
     68      * @see #defaults
     69      */
     70     public static final int DEFAULT_VIBRATE = 2;
     71 
     72     /**
     73      * Use the default notification lights. This will ignore the
     74      * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or
     75      * {@link #ledOnMS}.
     76      *
     77      * @see #defaults
     78      */
     79     public static final int DEFAULT_LIGHTS = 4;
     80 
     81     /**
     82      * The timestamp for the notification.  The icons and expanded views
     83      * are sorted by this key.
     84      */
     85     public long when;
     86 
     87     /**
     88      * The resource id of a drawable to use as the icon in the status bar.
     89      * This is required; notifications with an invalid icon resource will not be shown.
     90      */
     91     public int icon;
     92 
     93     /**
     94      * If the icon in the status bar is to have more than one level, you can set this.  Otherwise,
     95      * leave it at its default value of 0.
     96      *
     97      * @see android.widget.ImageView#setImageLevel
     98      * @see android.graphics.drawable#setLevel
     99      */
    100     public int iconLevel;
    101 
    102     /**
    103      * The number of events that this notification represents.  For example, in a new mail
    104      * notification, this could be the number of unread messages.  This number is superimposed over
    105      * the icon in the status bar.  If the number is 0 or negative, it is not shown in the status
    106      * bar.
    107      */
    108     public int number;
    109 
    110     /**
    111      * The intent to execute when the expanded status entry is clicked.  If
    112      * this is an activity, it must include the
    113      * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
    114      * that you take care of task management as described in the
    115      * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
    116      * Stack</a> document.
    117      */
    118     public PendingIntent contentIntent;
    119 
    120     /**
    121      * The intent to execute when the status entry is deleted by the user
    122      * with the "Clear All Notifications" button. This probably shouldn't
    123      * be launching an activity since several of those will be sent at the
    124      * same time.
    125      */
    126     public PendingIntent deleteIntent;
    127 
    128     /**
    129      * An intent to launch instead of posting the notification to the status bar.
    130      *
    131      * @see Notification.Builder#setFullScreenIntent
    132      */
    133     public PendingIntent fullScreenIntent;
    134 
    135     /**
    136      * Text to scroll across the screen when this item is added to
    137      * the status bar on large and smaller devices.
    138      *
    139      * <p>This field is provided separately from the other ticker fields
    140      * both for compatibility and to allow an application to choose different
    141      * text for when the text scrolls in and when it is displayed all at once
    142      * in conjunction with one or more icons.
    143      *
    144      * @see #tickerView
    145      */
    146     public CharSequence tickerText;
    147 
    148     /**
    149      * The view to show as the ticker in the status bar when the notification
    150      * is posted.
    151      */
    152     public RemoteViews tickerView;
    153 
    154     /**
    155      * The view that will represent this notification in the expanded status bar.
    156      */
    157     public RemoteViews contentView;
    158 
    159     /**
    160      * The bitmap that may escape the bounds of the panel and bar.
    161      */
    162     public Bitmap largeIcon;
    163 
    164     /**
    165      * The sound to play.
    166      *
    167      * <p>
    168      * To play the default notification sound, see {@link #defaults}.
    169      * </p>
    170      */
    171     public Uri sound;
    172 
    173     /**
    174      * Use this constant as the value for audioStreamType to request that
    175      * the default stream type for notifications be used.  Currently the
    176      * default stream type is STREAM_RING.
    177      */
    178     public static final int STREAM_DEFAULT = -1;
    179 
    180     /**
    181      * The audio stream type to use when playing the sound.
    182      * Should be one of the STREAM_ constants from
    183      * {@link android.media.AudioManager}.
    184      */
    185     public int audioStreamType = STREAM_DEFAULT;
    186 
    187 
    188     /**
    189      * The pattern with which to vibrate.
    190      *
    191      * <p>
    192      * To vibrate the default pattern, see {@link #defaults}.
    193      * </p>
    194      *
    195      * @see android.os.Vibrator#vibrate(long[],int)
    196      */
    197     public long[] vibrate;
    198 
    199     /**
    200      * The color of the led.  The hardware will do its best approximation.
    201      *
    202      * @see #FLAG_SHOW_LIGHTS
    203      * @see #flags
    204      */
    205     public int ledARGB;
    206 
    207     /**
    208      * The number of milliseconds for the LED to be on while it's flashing.
    209      * The hardware will do its best approximation.
    210      *
    211      * @see #FLAG_SHOW_LIGHTS
    212      * @see #flags
    213      */
    214     public int ledOnMS;
    215 
    216     /**
    217      * The number of milliseconds for the LED to be off while it's flashing.
    218      * The hardware will do its best approximation.
    219      *
    220      * @see #FLAG_SHOW_LIGHTS
    221      * @see #flags
    222      */
    223     public int ledOffMS;
    224 
    225     /**
    226      * Specifies which values should be taken from the defaults.
    227      * <p>
    228      * To set, OR the desired from {@link #DEFAULT_SOUND},
    229      * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default
    230      * values, use {@link #DEFAULT_ALL}.
    231      * </p>
    232      */
    233     public int defaults;
    234 
    235 
    236     /**
    237      * Bit to be bitwise-ored into the {@link #flags} field that should be
    238      * set if you want the LED on for this notification.
    239      * <ul>
    240      * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB
    241      *      or 0 for both ledOnMS and ledOffMS.</li>
    242      * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li>
    243      * <li>To flash the LED, pass the number of milliseconds that it should
    244      *      be on and off to ledOnMS and ledOffMS.</li>
    245      * </ul>
    246      * <p>
    247      * Since hardware varies, you are not guaranteed that any of the values
    248      * you pass are honored exactly.  Use the system defaults (TODO) if possible
    249      * because they will be set to values that work on any given hardware.
    250      * <p>
    251      * The alpha channel must be set for forward compatibility.
    252      *
    253      */
    254     public static final int FLAG_SHOW_LIGHTS        = 0x00000001;
    255 
    256     /**
    257      * Bit to be bitwise-ored into the {@link #flags} field that should be
    258      * set if this notification is in reference to something that is ongoing,
    259      * like a phone call.  It should not be set if this notification is in
    260      * reference to something that happened at a particular point in time,
    261      * like a missed phone call.
    262      */
    263     public static final int FLAG_ONGOING_EVENT      = 0x00000002;
    264 
    265     /**
    266      * Bit to be bitwise-ored into the {@link #flags} field that if set,
    267      * the audio will be repeated until the notification is
    268      * cancelled or the notification window is opened.
    269      */
    270     public static final int FLAG_INSISTENT          = 0x00000004;
    271 
    272     /**
    273      * Bit to be bitwise-ored into the {@link #flags} field that should be
    274      * set if you want the sound and/or vibration play each time the
    275      * notification is sent, even if it has not been canceled before that.
    276      */
    277     public static final int FLAG_ONLY_ALERT_ONCE    = 0x00000008;
    278 
    279     /**
    280      * Bit to be bitwise-ored into the {@link #flags} field that should be
    281      * set if the notification should be canceled when it is clicked by the
    282      * user.  On tablets, the
    283      */
    284     public static final int FLAG_AUTO_CANCEL        = 0x00000010;
    285 
    286     /**
    287      * Bit to be bitwise-ored into the {@link #flags} field that should be
    288      * set if the notification should not be canceled when the user clicks
    289      * the Clear all button.
    290      */
    291     public static final int FLAG_NO_CLEAR           = 0x00000020;
    292 
    293     /**
    294      * Bit to be bitwise-ored into the {@link #flags} field that should be
    295      * set if this notification represents a currently running service.  This
    296      * will normally be set for you by {@link Service#startForeground}.
    297      */
    298     public static final int FLAG_FOREGROUND_SERVICE = 0x00000040;
    299 
    300     /**
    301      * Bit to be bitwise-ored into the {@link #flags} field that should be set if this notification
    302      * represents a high-priority event that may be shown to the user even if notifications are
    303      * otherwise unavailable (that is, when the status bar is hidden). This flag is ideally used
    304      * in conjunction with {@link #fullScreenIntent}.
    305      */
    306     public static final int FLAG_HIGH_PRIORITY = 0x00000080;
    307 
    308     public int flags;
    309 
    310     /**
    311      * Constructs a Notification object with everything set to 0.
    312      * You might want to consider using {@link Builder} instead.
    313      */
    314     public Notification()
    315     {
    316         this.when = System.currentTimeMillis();
    317     }
    318 
    319     /**
    320      * @hide
    321      */
    322     public Notification(Context context, int icon, CharSequence tickerText, long when,
    323             CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
    324     {
    325         this.when = when;
    326         this.icon = icon;
    327         this.tickerText = tickerText;
    328         setLatestEventInfo(context, contentTitle, contentText,
    329                 PendingIntent.getActivity(context, 0, contentIntent, 0));
    330     }
    331 
    332     /**
    333      * Constructs a Notification object with the information needed to
    334      * have a status bar icon without the standard expanded view.
    335      *
    336      * @param icon          The resource id of the icon to put in the status bar.
    337      * @param tickerText    The text that flows by in the status bar when the notification first
    338      *                      activates.
    339      * @param when          The time to show in the time field.  In the System.currentTimeMillis
    340      *                      timebase.
    341      *
    342      * @deprecated Use {@link Builder} instead.
    343      */
    344     @Deprecated
    345     public Notification(int icon, CharSequence tickerText, long when)
    346     {
    347         this.icon = icon;
    348         this.tickerText = tickerText;
    349         this.when = when;
    350     }
    351 
    352     /**
    353      * Unflatten the notification from a parcel.
    354      */
    355     public Notification(Parcel parcel)
    356     {
    357         int version = parcel.readInt();
    358 
    359         when = parcel.readLong();
    360         icon = parcel.readInt();
    361         number = parcel.readInt();
    362         if (parcel.readInt() != 0) {
    363             contentIntent = PendingIntent.CREATOR.createFromParcel(parcel);
    364         }
    365         if (parcel.readInt() != 0) {
    366             deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel);
    367         }
    368         if (parcel.readInt() != 0) {
    369             tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
    370         }
    371         if (parcel.readInt() != 0) {
    372             tickerView = RemoteViews.CREATOR.createFromParcel(parcel);
    373         }
    374         if (parcel.readInt() != 0) {
    375             contentView = RemoteViews.CREATOR.createFromParcel(parcel);
    376         }
    377         if (parcel.readInt() != 0) {
    378             largeIcon = Bitmap.CREATOR.createFromParcel(parcel);
    379         }
    380         defaults = parcel.readInt();
    381         flags = parcel.readInt();
    382         if (parcel.readInt() != 0) {
    383             sound = Uri.CREATOR.createFromParcel(parcel);
    384         }
    385 
    386         audioStreamType = parcel.readInt();
    387         vibrate = parcel.createLongArray();
    388         ledARGB = parcel.readInt();
    389         ledOnMS = parcel.readInt();
    390         ledOffMS = parcel.readInt();
    391         iconLevel = parcel.readInt();
    392 
    393         if (parcel.readInt() != 0) {
    394             fullScreenIntent = PendingIntent.CREATOR.createFromParcel(parcel);
    395         }
    396     }
    397 
    398     @Override
    399     public Notification clone() {
    400         Notification that = new Notification();
    401 
    402         that.when = this.when;
    403         that.icon = this.icon;
    404         that.number = this.number;
    405 
    406         // PendingIntents are global, so there's no reason (or way) to clone them.
    407         that.contentIntent = this.contentIntent;
    408         that.deleteIntent = this.deleteIntent;
    409         that.fullScreenIntent = this.fullScreenIntent;
    410 
    411         if (this.tickerText != null) {
    412             that.tickerText = this.tickerText.toString();
    413         }
    414         if (this.tickerView != null) {
    415             that.tickerView = this.tickerView.clone();
    416         }
    417         if (this.contentView != null) {
    418             that.contentView = this.contentView.clone();
    419         }
    420         if (this.largeIcon != null) {
    421             that.largeIcon = Bitmap.createBitmap(this.largeIcon);
    422         }
    423         that.iconLevel = this.iconLevel;
    424         that.sound = this.sound; // android.net.Uri is immutable
    425         that.audioStreamType = this.audioStreamType;
    426 
    427         final long[] vibrate = this.vibrate;
    428         if (vibrate != null) {
    429             final int N = vibrate.length;
    430             final long[] vib = that.vibrate = new long[N];
    431             System.arraycopy(vibrate, 0, vib, 0, N);
    432         }
    433 
    434         that.ledARGB = this.ledARGB;
    435         that.ledOnMS = this.ledOnMS;
    436         that.ledOffMS = this.ledOffMS;
    437         that.defaults = this.defaults;
    438 
    439         that.flags = this.flags;
    440 
    441         return that;
    442     }
    443 
    444     public int describeContents() {
    445         return 0;
    446     }
    447 
    448     /**
    449      * Flatten this notification from a parcel.
    450      */
    451     public void writeToParcel(Parcel parcel, int flags)
    452     {
    453         parcel.writeInt(1);
    454 
    455         parcel.writeLong(when);
    456         parcel.writeInt(icon);
    457         parcel.writeInt(number);
    458         if (contentIntent != null) {
    459             parcel.writeInt(1);
    460             contentIntent.writeToParcel(parcel, 0);
    461         } else {
    462             parcel.writeInt(0);
    463         }
    464         if (deleteIntent != null) {
    465             parcel.writeInt(1);
    466             deleteIntent.writeToParcel(parcel, 0);
    467         } else {
    468             parcel.writeInt(0);
    469         }
    470         if (tickerText != null) {
    471             parcel.writeInt(1);
    472             TextUtils.writeToParcel(tickerText, parcel, flags);
    473         } else {
    474             parcel.writeInt(0);
    475         }
    476         if (tickerView != null) {
    477             parcel.writeInt(1);
    478             tickerView.writeToParcel(parcel, 0);
    479         } else {
    480             parcel.writeInt(0);
    481         }
    482         if (contentView != null) {
    483             parcel.writeInt(1);
    484             contentView.writeToParcel(parcel, 0);
    485         } else {
    486             parcel.writeInt(0);
    487         }
    488         if (largeIcon != null) {
    489             parcel.writeInt(1);
    490             largeIcon.writeToParcel(parcel, 0);
    491         } else {
    492             parcel.writeInt(0);
    493         }
    494 
    495         parcel.writeInt(defaults);
    496         parcel.writeInt(this.flags);
    497 
    498         if (sound != null) {
    499             parcel.writeInt(1);
    500             sound.writeToParcel(parcel, 0);
    501         } else {
    502             parcel.writeInt(0);
    503         }
    504         parcel.writeInt(audioStreamType);
    505         parcel.writeLongArray(vibrate);
    506         parcel.writeInt(ledARGB);
    507         parcel.writeInt(ledOnMS);
    508         parcel.writeInt(ledOffMS);
    509         parcel.writeInt(iconLevel);
    510 
    511         if (fullScreenIntent != null) {
    512             parcel.writeInt(1);
    513             fullScreenIntent.writeToParcel(parcel, 0);
    514         } else {
    515             parcel.writeInt(0);
    516         }
    517     }
    518 
    519     /**
    520      * Parcelable.Creator that instantiates Notification objects
    521      */
    522     public static final Parcelable.Creator<Notification> CREATOR
    523             = new Parcelable.Creator<Notification>()
    524     {
    525         public Notification createFromParcel(Parcel parcel)
    526         {
    527             return new Notification(parcel);
    528         }
    529 
    530         public Notification[] newArray(int size)
    531         {
    532             return new Notification[size];
    533         }
    534     };
    535 
    536     /**
    537      * Sets the {@link #contentView} field to be a view with the standard "Latest Event"
    538      * layout.
    539      *
    540      * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields
    541      * in the view.</p>
    542      * @param context       The context for your application / activity.
    543      * @param contentTitle The title that goes in the expanded entry.
    544      * @param contentText  The text that goes in the expanded entry.
    545      * @param contentIntent The intent to launch when the user clicks the expanded notification.
    546      * If this is an activity, it must include the
    547      * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
    548      * that you take care of task management as described in the
    549      * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
    550      * Stack</a> document.
    551      *
    552      * @deprecated Use {@link Builder} instead.
    553      */
    554     @Deprecated
    555     public void setLatestEventInfo(Context context,
    556             CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
    557         RemoteViews contentView = new RemoteViews(context.getPackageName(),
    558                 R.layout.status_bar_latest_event_content);
    559         if (this.icon != 0) {
    560             contentView.setImageViewResource(R.id.icon, this.icon);
    561         }
    562         if (contentTitle != null) {
    563             contentView.setTextViewText(R.id.title, contentTitle);
    564         }
    565         if (contentText != null) {
    566             contentView.setTextViewText(R.id.text, contentText);
    567         }
    568         if (this.when != 0) {
    569             contentView.setLong(R.id.time, "setTime", when);
    570         }
    571 
    572         this.contentView = contentView;
    573         this.contentIntent = contentIntent;
    574     }
    575 
    576     @Override
    577     public String toString() {
    578         StringBuilder sb = new StringBuilder();
    579         sb.append("Notification(contentView=");
    580         if (contentView != null) {
    581             sb.append(contentView.getPackage());
    582             sb.append("/0x");
    583             sb.append(Integer.toHexString(contentView.getLayoutId()));
    584         } else {
    585             sb.append("null");
    586         }
    587         sb.append(" vibrate=");
    588         if (this.vibrate != null) {
    589             int N = this.vibrate.length-1;
    590             sb.append("[");
    591             for (int i=0; i<N; i++) {
    592                 sb.append(this.vibrate[i]);
    593                 sb.append(',');
    594             }
    595             if (N != -1) {
    596                 sb.append(this.vibrate[N]);
    597             }
    598             sb.append("]");
    599         } else if ((this.defaults & DEFAULT_VIBRATE) != 0) {
    600             sb.append("default");
    601         } else {
    602             sb.append("null");
    603         }
    604         sb.append(",sound=");
    605         if (this.sound != null) {
    606             sb.append(this.sound.toString());
    607         } else if ((this.defaults & DEFAULT_SOUND) != 0) {
    608             sb.append("default");
    609         } else {
    610             sb.append("null");
    611         }
    612         sb.append(",defaults=0x");
    613         sb.append(Integer.toHexString(this.defaults));
    614         sb.append(",flags=0x");
    615         sb.append(Integer.toHexString(this.flags));
    616         if ((this.flags & FLAG_HIGH_PRIORITY) != 0) {
    617             sb.append("!!!1!one!");
    618         }
    619         sb.append(")");
    620         return sb.toString();
    621     }
    622 
    623     /**
    624      * Builder class for {@link Notification} objects.  Allows easier control over
    625      * all the flags, as well as help constructing the typical notification layouts.
    626      */
    627     public static class Builder {
    628         private Context mContext;
    629 
    630         private long mWhen;
    631         private int mSmallIcon;
    632         private int mSmallIconLevel;
    633         private int mNumber;
    634         private CharSequence mContentTitle;
    635         private CharSequence mContentText;
    636         private CharSequence mContentInfo;
    637         private PendingIntent mContentIntent;
    638         private RemoteViews mContentView;
    639         private PendingIntent mDeleteIntent;
    640         private PendingIntent mFullScreenIntent;
    641         private CharSequence mTickerText;
    642         private RemoteViews mTickerView;
    643         private Bitmap mLargeIcon;
    644         private Uri mSound;
    645         private int mAudioStreamType;
    646         private long[] mVibrate;
    647         private int mLedArgb;
    648         private int mLedOnMs;
    649         private int mLedOffMs;
    650         private int mDefaults;
    651         private int mFlags;
    652         private int mProgressMax;
    653         private int mProgress;
    654         private boolean mProgressIndeterminate;
    655 
    656         /**
    657          * Constructor.
    658          *
    659          * Automatically sets the when field to {@link System#currentTimeMillis()
    660          * System.currentTimeMllis()} and the audio stream to the {@link #STREAM_DEFAULT}.
    661          *
    662          * @param context A {@link Context} that will be used to construct the
    663          *      RemoteViews. The Context will not be held past the lifetime of this
    664          *      Builder object.
    665          */
    666         public Builder(Context context) {
    667             mContext = context;
    668 
    669             // Set defaults to match the defaults of a Notification
    670             mWhen = System.currentTimeMillis();
    671             mAudioStreamType = STREAM_DEFAULT;
    672         }
    673 
    674         /**
    675          * Set the time that the event occurred.  Notifications in the panel are
    676          * sorted by this time.
    677          */
    678         public Builder setWhen(long when) {
    679             mWhen = when;
    680             return this;
    681         }
    682 
    683         /**
    684          * Set the small icon to use in the notification layouts.  Different classes of devices
    685          * may return different sizes.  See the UX guidelines for more information on how to
    686          * design these icons.
    687          *
    688          * @param icon A resource ID in the application's package of the drawble to use.
    689          */
    690         public Builder setSmallIcon(int icon) {
    691             mSmallIcon = icon;
    692             return this;
    693         }
    694 
    695         /**
    696          * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
    697          * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
    698          * LevelListDrawable}.
    699          *
    700          * @param icon A resource ID in the application's package of the drawble to use.
    701          * @param level The level to use for the icon.
    702          *
    703          * @see android.graphics.drawable.LevelListDrawable
    704          */
    705         public Builder setSmallIcon(int icon, int level) {
    706             mSmallIcon = icon;
    707             mSmallIconLevel = level;
    708             return this;
    709         }
    710 
    711         /**
    712          * Set the title (first row) of the notification, in a standard notification.
    713          */
    714         public Builder setContentTitle(CharSequence title) {
    715             mContentTitle = title;
    716             return this;
    717         }
    718 
    719         /**
    720          * Set the text (second row) of the notification, in a standard notification.
    721          */
    722         public Builder setContentText(CharSequence text) {
    723             mContentText = text;
    724             return this;
    725         }
    726 
    727         /**
    728          * Set the large number at the right-hand side of the notification.  This is
    729          * equivalent to setContentInfo, although it might show the number in a different
    730          * font size for readability.
    731          */
    732         public Builder setNumber(int number) {
    733             mNumber = number;
    734             return this;
    735         }
    736 
    737         /**
    738          * Set the large text at the right-hand side of the notification.
    739          */
    740         public Builder setContentInfo(CharSequence info) {
    741             mContentInfo = info;
    742             return this;
    743         }
    744 
    745         /**
    746          * Set the progress this notification represents, which may be
    747          * represented as a {@link ProgressBar}.
    748          */
    749         public Builder setProgress(int max, int progress, boolean indeterminate) {
    750             mProgressMax = max;
    751             mProgress = progress;
    752             mProgressIndeterminate = indeterminate;
    753             return this;
    754         }
    755 
    756         /**
    757          * Supply a custom RemoteViews to use instead of the standard one.
    758          */
    759         public Builder setContent(RemoteViews views) {
    760             mContentView = views;
    761             return this;
    762         }
    763 
    764         /**
    765          * Supply a {@link PendingIntent} to send when the notification is clicked.
    766          * If you do not supply an intent, you can now add PendingIntents to individual
    767          * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
    768          * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.
    769          */
    770         public Builder setContentIntent(PendingIntent intent) {
    771             mContentIntent = intent;
    772             return this;
    773         }
    774 
    775         /**
    776          * Supply a {@link PendingIntent} to send when the notification is cleared by the user
    777          * directly from the notification panel.  For example, this intent is sent when the user
    778          * clicks the "Clear all" button, or the individual "X" buttons on notifications.  This
    779          * intent is not sent when the application calls {@link NotificationManager#cancel
    780          * NotificationManager.cancel(int)}.
    781          */
    782         public Builder setDeleteIntent(PendingIntent intent) {
    783             mDeleteIntent = intent;
    784             return this;
    785         }
    786 
    787         /**
    788          * An intent to launch instead of posting the notification to the status bar.
    789          * Only for use with extremely high-priority notifications demanding the user's
    790          * <strong>immediate</strong> attention, such as an incoming phone call or
    791          * alarm clock that the user has explicitly set to a particular time.
    792          * If this facility is used for something else, please give the user an option
    793          * to turn it off and use a normal notification, as this can be extremely
    794          * disruptive.
    795          *
    796          * @param intent The pending intent to launch.
    797          * @param highPriority Passing true will cause this notification to be sent
    798          *          even if other notifications are suppressed.
    799          */
    800         public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
    801             mFullScreenIntent = intent;
    802             setFlag(FLAG_HIGH_PRIORITY, highPriority);
    803             return this;
    804         }
    805 
    806         /**
    807          * Set the text that is displayed in the status bar when the notification first
    808          * arrives.
    809          */
    810         public Builder setTicker(CharSequence tickerText) {
    811             mTickerText = tickerText;
    812             return this;
    813         }
    814 
    815         /**
    816          * Set the text that is displayed in the status bar when the notification first
    817          * arrives, and also a RemoteViews object that may be displayed instead on some
    818          * devices.
    819          */
    820         public Builder setTicker(CharSequence tickerText, RemoteViews views) {
    821             mTickerText = tickerText;
    822             mTickerView = views;
    823             return this;
    824         }
    825 
    826         /**
    827          * Set the large icon that is shown in the ticker and notification.
    828          */
    829         public Builder setLargeIcon(Bitmap icon) {
    830             mLargeIcon = icon;
    831             return this;
    832         }
    833 
    834         /**
    835          * Set the sound to play.  It will play on the default stream.
    836          */
    837         public Builder setSound(Uri sound) {
    838             mSound = sound;
    839             mAudioStreamType = STREAM_DEFAULT;
    840             return this;
    841         }
    842 
    843         /**
    844          * Set the sound to play.  It will play on the stream you supply.
    845          *
    846          * @see #STREAM_DEFAULT
    847          * @see AudioManager for the <code>STREAM_</code> constants.
    848          */
    849         public Builder setSound(Uri sound, int streamType) {
    850             mSound = sound;
    851             mAudioStreamType = streamType;
    852             return this;
    853         }
    854 
    855         /**
    856          * Set the vibration pattern to use.
    857          *
    858          * @see android.os.Vibrator for a discussion of the <code>pattern</code>
    859          * parameter.
    860          */
    861         public Builder setVibrate(long[] pattern) {
    862             mVibrate = pattern;
    863             return this;
    864         }
    865 
    866         /**
    867          * Set the argb value that you would like the LED on the device to blnk, as well as the
    868          * rate.  The rate is specified in terms of the number of milliseconds to be on
    869          * and then the number of milliseconds to be off.
    870          */
    871         public Builder setLights(int argb, int onMs, int offMs) {
    872             mLedArgb = argb;
    873             mLedOnMs = onMs;
    874             mLedOffMs = offMs;
    875             return this;
    876         }
    877 
    878         /**
    879          * Set whether this is an ongoing notification.
    880          *
    881          * <p>Ongoing notifications differ from regular notifications in the following ways:
    882          * <ul>
    883          *   <li>Ongoing notifications are sorted above the regular notifications in the
    884          *   notification panel.</li>
    885          *   <li>Ongoing notifications do not have an 'X' close button, and are not affected
    886          *   by the "Clear all" button.
    887          * </ul>
    888          */
    889         public Builder setOngoing(boolean ongoing) {
    890             setFlag(FLAG_ONGOING_EVENT, ongoing);
    891             return this;
    892         }
    893 
    894         /**
    895          * Set this flag if you would only like the sound, vibrate
    896          * and ticker to be played if the notification is not already showing.
    897          */
    898         public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
    899             setFlag(FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
    900             return this;
    901         }
    902 
    903         /**
    904          * Setting this flag will make it so the notification is automatically
    905          * canceled when the user clicks it in the panel.  The PendingIntent
    906          * set with {@link #setDeleteIntent} will be broadcast when the notification
    907          * is canceled.
    908          */
    909         public Builder setAutoCancel(boolean autoCancel) {
    910             setFlag(FLAG_AUTO_CANCEL, autoCancel);
    911             return this;
    912         }
    913 
    914         /**
    915          * Set the default notification options that will be used.
    916          * <p>
    917          * The value should be one or more of the following fields combined with
    918          * bitwise-or:
    919          * {@link #DEFAULT_SOUND}, {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}.
    920          * <p>
    921          * For all default values, use {@link #DEFAULT_ALL}.
    922          */
    923         public Builder setDefaults(int defaults) {
    924             mDefaults = defaults;
    925             return this;
    926         }
    927 
    928         private void setFlag(int mask, boolean value) {
    929             if (value) {
    930                 mFlags |= mask;
    931             } else {
    932                 mFlags &= ~mask;
    933             }
    934         }
    935 
    936         private RemoteViews makeRemoteViews(int resId) {
    937             RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId);
    938             boolean hasLine3 = false;
    939             if (mSmallIcon != 0) {
    940                 contentView.setImageViewResource(R.id.icon, mSmallIcon);
    941                 contentView.setViewVisibility(R.id.icon, View.VISIBLE);
    942             } else {
    943                 contentView.setViewVisibility(R.id.icon, View.GONE);
    944             }
    945             if (mContentTitle != null) {
    946                 contentView.setTextViewText(R.id.title, mContentTitle);
    947             }
    948             if (mContentText != null) {
    949                 contentView.setTextViewText(R.id.text, mContentText);
    950                 hasLine3 = true;
    951             }
    952             if (mContentInfo != null) {
    953                 contentView.setTextViewText(R.id.info, mContentInfo);
    954                 contentView.setViewVisibility(R.id.info, View.VISIBLE);
    955                 hasLine3 = true;
    956             } else if (mNumber > 0) {
    957                 final int tooBig = mContext.getResources().getInteger(
    958                         R.integer.status_bar_notification_info_maxnum);
    959                 if (mNumber > tooBig) {
    960                     contentView.setTextViewText(R.id.info, mContext.getResources().getString(
    961                                 R.string.status_bar_notification_info_overflow));
    962                 } else {
    963                     NumberFormat f = NumberFormat.getIntegerInstance();
    964                     contentView.setTextViewText(R.id.info, f.format(mNumber));
    965                 }
    966                 contentView.setViewVisibility(R.id.info, View.VISIBLE);
    967                 hasLine3 = true;
    968             } else {
    969                 contentView.setViewVisibility(R.id.info, View.GONE);
    970             }
    971             if (mProgressMax != 0 || mProgressIndeterminate) {
    972                 contentView.setProgressBar(
    973                         R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
    974                 contentView.setViewVisibility(R.id.progress, View.VISIBLE);
    975             } else {
    976                 contentView.setViewVisibility(R.id.progress, View.GONE);
    977             }
    978             if (mWhen != 0) {
    979                 contentView.setLong(R.id.time, "setTime", mWhen);
    980             }
    981             contentView.setViewVisibility(R.id.line3, hasLine3 ? View.VISIBLE : View.GONE);
    982             return contentView;
    983         }
    984 
    985         private RemoteViews makeContentView() {
    986             if (mContentView != null) {
    987                 return mContentView;
    988             } else {
    989                     return makeRemoteViews(mLargeIcon == null
    990                             ? R.layout.status_bar_latest_event_content
    991                         : R.layout.status_bar_latest_event_content_large_icon);
    992             }
    993         }
    994 
    995         private RemoteViews makeTickerView() {
    996             if (mTickerView != null) {
    997                 return mTickerView;
    998             } else {
    999                 if (mContentView == null) {
   1000                     return makeRemoteViews(mLargeIcon == null
   1001                             ? R.layout.status_bar_latest_event_ticker
   1002                             : R.layout.status_bar_latest_event_ticker_large_icon);
   1003                 } else {
   1004                     return null;
   1005                 }
   1006             }
   1007         }
   1008 
   1009         /**
   1010          * Combine all of the options that have been set and return a new {@link Notification}
   1011          * object.
   1012          */
   1013         public Notification getNotification() {
   1014             Notification n = new Notification();
   1015             n.when = mWhen;
   1016             n.icon = mSmallIcon;
   1017             n.iconLevel = mSmallIconLevel;
   1018             n.number = mNumber;
   1019             n.contentView = makeContentView();
   1020             n.contentIntent = mContentIntent;
   1021             n.deleteIntent = mDeleteIntent;
   1022             n.fullScreenIntent = mFullScreenIntent;
   1023             n.tickerText = mTickerText;
   1024             n.tickerView = makeTickerView();
   1025             n.largeIcon = mLargeIcon;
   1026             n.sound = mSound;
   1027             n.audioStreamType = mAudioStreamType;
   1028             n.vibrate = mVibrate;
   1029             n.ledARGB = mLedArgb;
   1030             n.ledOnMS = mLedOnMs;
   1031             n.ledOffMS = mLedOffMs;
   1032             n.defaults = mDefaults;
   1033             n.flags = mFlags;
   1034             if (mLedOnMs != 0 && mLedOffMs != 0) {
   1035                 n.flags |= FLAG_SHOW_LIGHTS;
   1036             }
   1037             if ((mDefaults & DEFAULT_LIGHTS) != 0) {
   1038                 n.flags |= FLAG_SHOW_LIGHTS;
   1039             }
   1040             return n;
   1041         }
   1042     }
   1043 }
   1044