NotificationCompat.java revision 47702147608084fec16a50640da54b412c737b9c
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.app;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.content.Context;
23import android.graphics.Bitmap;
24import android.media.AudioManager;
25import android.net.Uri;
26import android.os.Build;
27import android.os.Bundle;
28import android.widget.RemoteViews;
29import java.util.ArrayList;
30
31/**
32 * Helper for accessing features in {@link android.app.Notification}
33 * introduced after API level 4 in a backwards compatible fashion.
34 */
35public class NotificationCompat {
36    /**
37     * Obsolete flag indicating high-priority notifications; use the priority field instead.
38     *
39     * @deprecated Use {@link NotificationCompat.Builder#setPriority(int)} with a positive value.
40     */
41    public static final int FLAG_HIGH_PRIORITY = 0x00000080;
42
43    /**
44     * Default notification priority for {@link NotificationCompat.Builder#setPriority(int)}.
45     * If your application does not prioritize its own notifications,
46     * use this value for all notifications.
47     */
48    public static final int PRIORITY_DEFAULT = 0;
49
50    /**
51     * Lower notification priority for {@link NotificationCompat.Builder#setPriority(int)},
52     * for items that are less important. The UI may choose to show
53     * these items smaller, or at a different position in the list,
54     * compared with your app's {@link #PRIORITY_DEFAULT} items.
55     */
56    public static final int PRIORITY_LOW = -1;
57
58    /**
59     * Lowest notification priority for {@link NotificationCompat.Builder#setPriority(int)};
60     * these items might not be shown to the user except under
61     * special circumstances, such as detailed notification logs.
62     */
63    public static final int PRIORITY_MIN = -2;
64
65    /**
66     * Higher notification priority for {@link NotificationCompat.Builder#setPriority(int)},
67     * for more important notifications or alerts. The UI may choose
68     * to show these items larger, or at a different position in
69     * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items.
70     */
71    public static final int PRIORITY_HIGH = 1;
72
73    /**
74     * Highest notification priority for {@link NotificationCompat.Builder#setPriority(int)},
75     * for your application's most important items that require the user's
76     * prompt attention or input.
77     */
78    public static final int PRIORITY_MAX = 2;
79
80    private static final NotificationCompatImpl IMPL;
81
82    interface NotificationCompatImpl {
83        public Notification build(Builder b);
84        public Bundle getExtras(Notification n);
85        public boolean getLocalOnly(Notification n);
86    }
87
88    static class NotificationCompatImplBase implements NotificationCompatImpl {
89        @Override
90        public Notification build(Builder b) {
91            Notification result = b.mNotification;
92            result.setLatestEventInfo(b.mContext, b.mContentTitle,
93                    b.mContentText, b.mContentIntent);
94            // translate high priority requests into legacy flag
95            if (b.mPriority > PRIORITY_DEFAULT) {
96                result.flags |= FLAG_HIGH_PRIORITY;
97            }
98            return result;
99        }
100
101        @Override
102        public Bundle getExtras(Notification n) {
103            return null;
104        }
105
106        @Override
107        public boolean getLocalOnly(Notification n) {
108            return false;
109        }
110    }
111
112    static class NotificationCompatImplGingerbread extends NotificationCompatImplBase {
113        @Override
114        public Notification build(Builder b) {
115            Notification result = b.mNotification;
116            result.setLatestEventInfo(b.mContext, b.mContentTitle,
117                    b.mContentText, b.mContentIntent);
118            result = NotificationCompatGingerbread.add(result, b.mContext,
119                    b.mContentTitle, b.mContentText, b.mContentIntent, b.mFullScreenIntent);
120            // translate high priority requests into legacy flag
121            if (b.mPriority > PRIORITY_DEFAULT) {
122                result.flags |= FLAG_HIGH_PRIORITY;
123            }
124            return result;
125        }
126    }
127
128    static class NotificationCompatImplHoneycomb extends NotificationCompatImplBase {
129        @Override
130        public Notification build(Builder b) {
131            return NotificationCompatHoneycomb.add(b.mContext, b.mNotification,
132                    b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
133                    b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon);
134        }
135    }
136
137    static class NotificationCompatImplIceCreamSandwich extends NotificationCompatImplBase {
138        @Override
139        public Notification build(Builder b) {
140            return NotificationCompatIceCreamSandwich.add(b.mContext, b.mNotification,
141                    b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
142                    b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
143                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate);
144        }
145    }
146
147    static class NotificationCompatImplJellybean extends NotificationCompatImplBase {
148        @Override
149        public Notification build(Builder b) {
150            NotificationCompatJellybean.Builder builder = new NotificationCompatJellybean.Builder(
151                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
152                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
153                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
154                    b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras);
155            addActionsToBuilder(builder, b.mActions);
156            addStyleToBuilderJellybean(builder, b.mStyle);
157            return builder.build();
158        }
159
160        @Override
161        public Bundle getExtras(Notification n) {
162            return NotificationCompatJellybean.getExtras(n);
163        }
164
165        @Override
166        public boolean getLocalOnly(Notification n) {
167            return NotificationCompatJellybean.getLocalOnly(n);
168        }
169    }
170
171    static class NotificationCompatImplKitKat extends NotificationCompatImplBase {
172        @Override
173        public Notification build(Builder b) {
174            NotificationCompatKitKat.Builder builder = new NotificationCompatKitKat.Builder(
175                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
176                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
177                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
178                    b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras);
179            addActionsToBuilder(builder, b.mActions);
180            addStyleToBuilderJellybean(builder, b.mStyle);
181            return builder.build();
182        }
183
184        @Override
185        public Bundle getExtras(Notification n) {
186            return NotificationCompatKitKat.getExtras(n);
187        }
188
189        @Override
190        public boolean getLocalOnly(Notification n) {
191            return NotificationCompatKitKat.getLocalOnly(n);
192        }
193    }
194
195    static class NotificationCompatImplApi20 extends NotificationCompatImplBase {
196        @Override
197        public Notification build(Builder b) {
198            NotificationCompatApi20.Builder builder = new NotificationCompatApi20.Builder(
199                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
200                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
201                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
202                    b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras);
203            addActionsToBuilder(builder, b.mActions);
204            addStyleToBuilderJellybean(builder, b.mStyle);
205            return builder.build();
206        }
207
208        @Override
209        public Bundle getExtras(Notification n) {
210            return NotificationCompatKitKat.getExtras(n);
211        }
212
213        @Override
214        public boolean getLocalOnly(Notification n) {
215            return NotificationCompatApi20.getLocalOnly(n);
216        }
217    }
218
219    private static void addActionsToBuilder(NotificationBuilderWithActions builder,
220            ArrayList<Action> actions) {
221        for (Action action : actions) {
222            builder.addAction(action.icon, action.title, action.actionIntent);
223        }
224    }
225
226    private static void addStyleToBuilderJellybean(NotificationBuilderWithBuilderAccessor builder,
227            Style style) {
228        if (style != null) {
229            if (style instanceof BigTextStyle) {
230                BigTextStyle bigTextStyle = (BigTextStyle) style;
231                NotificationCompatJellybean.addBigTextStyle(builder,
232                        bigTextStyle.mBigContentTitle,
233                        bigTextStyle.mSummaryTextSet,
234                        bigTextStyle.mSummaryText,
235                        bigTextStyle.mBigText);
236            } else if (style instanceof InboxStyle) {
237                InboxStyle inboxStyle = (InboxStyle) style;
238                NotificationCompatJellybean.addInboxStyle(builder,
239                        inboxStyle.mBigContentTitle,
240                        inboxStyle.mSummaryTextSet,
241                        inboxStyle.mSummaryText,
242                        inboxStyle.mTexts);
243            } else if (style instanceof BigPictureStyle) {
244                BigPictureStyle bigPictureStyle = (BigPictureStyle) style;
245                NotificationCompatJellybean.addBigPictureStyle(builder,
246                        bigPictureStyle.mBigContentTitle,
247                        bigPictureStyle.mSummaryTextSet,
248                        bigPictureStyle.mSummaryText,
249                        bigPictureStyle.mPicture,
250                        bigPictureStyle.mBigLargeIcon,
251                        bigPictureStyle.mBigLargeIconSet);
252            }
253        }
254    }
255
256    static {
257        // TODO: Add NotificationCompatApi20 when SDK_INT is incremented.
258        if (Build.VERSION.SDK_INT >= 19) {
259            IMPL = new NotificationCompatImplKitKat();
260        } else if (Build.VERSION.SDK_INT >= 16) {
261            IMPL = new NotificationCompatImplJellybean();
262        } else if (Build.VERSION.SDK_INT >= 14) {
263            IMPL = new NotificationCompatImplIceCreamSandwich();
264        } else if (Build.VERSION.SDK_INT >= 11) {
265            IMPL = new NotificationCompatImplHoneycomb();
266        } else if (Build.VERSION.SDK_INT >= 9) {
267            IMPL = new NotificationCompatImplGingerbread();
268        } else {
269            IMPL = new NotificationCompatImplBase();
270        }
271    }
272
273    /**
274     * Builder class for {@link NotificationCompat} objects.  Allows easier control over
275     * all the flags, as well as help constructing the typical notification layouts.
276     * <p>
277     * On platform versions that don't offer expanded notifications, methods that depend on
278     * expanded notifications have no effect.
279     * </p>
280     * <p>
281     * For example, action buttons won't appear on platforms prior to Android 4.1. Action
282     * buttons depend on expanded notifications, which are only available in Android 4.1
283     * and later.
284     * <p>
285     * For this reason, you should always ensure that UI controls in a notification are also
286     * available in an {@link android.app.Activity} in your app, and you should always start that
287     * {@link android.app.Activity} when users click the notification. To do this, use the
288     * {@link NotificationCompat.Builder#setContentIntent setContentIntent()}
289     * method.
290     * </p>
291     *
292     */
293    public static class Builder {
294        Context mContext;
295
296        CharSequence mContentTitle;
297        CharSequence mContentText;
298        PendingIntent mContentIntent;
299        PendingIntent mFullScreenIntent;
300        RemoteViews mTickerView;
301        Bitmap mLargeIcon;
302        CharSequence mContentInfo;
303        int mNumber;
304        int mPriority;
305        boolean mUseChronometer;
306        Style mStyle;
307        CharSequence mSubText;
308        int mProgressMax;
309        int mProgress;
310        boolean mProgressIndeterminate;
311        ArrayList<Action> mActions = new ArrayList<Action>();
312        boolean mLocalOnly = false;
313        Bundle mExtras;
314
315        Notification mNotification = new Notification();
316
317        /**
318         * Constructor.
319         *
320         * Automatically sets the when field to {@link System#currentTimeMillis()
321         * System.currentTimeMillis()} and the audio stream to the
322         * {@link Notification#STREAM_DEFAULT}.
323         *
324         * @param context A {@link Context} that will be used to construct the
325         *      RemoteViews. The Context will not be held past the lifetime of this
326         *      Builder object.
327         */
328        public Builder(Context context) {
329            mContext = context;
330
331            // Set defaults to match the defaults of a Notification
332            mNotification.when = System.currentTimeMillis();
333            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
334            mPriority = PRIORITY_DEFAULT;
335        }
336
337        /**
338         * Set the time that the event occurred.  Notifications in the panel are
339         * sorted by this time.
340         */
341        public Builder setWhen(long when) {
342            mNotification.when = when;
343            return this;
344        }
345
346        /**
347         * Show the {@link Notification#when} field as a stopwatch.
348         *
349         * Instead of presenting <code>when</code> as a timestamp, the notification will show an
350         * automatically updating display of the minutes and seconds since <code>when</code>.
351         *
352         * Useful when showing an elapsed time (like an ongoing phone call).
353         *
354         * @see android.widget.Chronometer
355         * @see Notification#when
356         */
357        public Builder setUsesChronometer(boolean b) {
358            mUseChronometer = b;
359            return this;
360        }
361
362        /**
363         * Set the small icon to use in the notification layouts.  Different classes of devices
364         * may return different sizes.  See the UX guidelines for more information on how to
365         * design these icons.
366         *
367         * @param icon A resource ID in the application's package of the drawble to use.
368         */
369        public Builder setSmallIcon(int icon) {
370            mNotification.icon = icon;
371            return this;
372        }
373
374        /**
375         * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
376         * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
377         * LevelListDrawable}.
378         *
379         * @param icon A resource ID in the application's package of the drawble to use.
380         * @param level The level to use for the icon.
381         *
382         * @see android.graphics.drawable.LevelListDrawable
383         */
384        public Builder setSmallIcon(int icon, int level) {
385            mNotification.icon = icon;
386            mNotification.iconLevel = level;
387            return this;
388        }
389
390        /**
391         * Set the title (first row) of the notification, in a standard notification.
392         */
393        public Builder setContentTitle(CharSequence title) {
394            mContentTitle = title;
395            return this;
396        }
397
398        /**
399         * Set the text (second row) of the notification, in a standard notification.
400         */
401        public Builder setContentText(CharSequence text) {
402            mContentText = text;
403            return this;
404        }
405
406        /**
407         * Set the third line of text in the platform notification template.
408         * Don't use if you're also using {@link #setProgress(int, int, boolean)};
409         * they occupy the same location in the standard template.
410         * <br>
411         * If the platform does not provide large-format notifications, this method has no effect.
412         * The third line of text only appears in expanded view.
413         * <br>
414         */
415        public Builder setSubText(CharSequence text) {
416            mSubText = text;
417            return this;
418        }
419
420        /**
421         * Set the large number at the right-hand side of the notification.  This is
422         * equivalent to setContentInfo, although it might show the number in a different
423         * font size for readability.
424         */
425        public Builder setNumber(int number) {
426            mNumber = number;
427            return this;
428        }
429
430        /**
431         * Set the large text at the right-hand side of the notification.
432         */
433        public Builder setContentInfo(CharSequence info) {
434            mContentInfo = info;
435            return this;
436        }
437
438        /**
439         * Set the progress this notification represents, which may be
440         * represented as a {@link android.widget.ProgressBar}.
441         */
442        public Builder setProgress(int max, int progress, boolean indeterminate) {
443            mProgressMax = max;
444            mProgress = progress;
445            mProgressIndeterminate = indeterminate;
446            return this;
447        }
448
449        /**
450         * Supply a custom RemoteViews to use instead of the standard one.
451         */
452        public Builder setContent(RemoteViews views) {
453            mNotification.contentView = views;
454            return this;
455        }
456
457        /**
458         * Supply a {@link PendingIntent} to send when the notification is clicked.
459         * If you do not supply an intent, you can now add PendingIntents to individual
460         * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
461         * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.  Be sure to
462         * read {@link Notification#contentIntent Notification.contentIntent} for
463         * how to correctly use this.
464         */
465        public Builder setContentIntent(PendingIntent intent) {
466            mContentIntent = intent;
467            return this;
468        }
469
470        /**
471         * Supply a {@link PendingIntent} to send when the notification is cleared by the user
472         * directly from the notification panel.  For example, this intent is sent when the user
473         * clicks the "Clear all" button, or the individual "X" buttons on notifications.  This
474         * intent is not sent when the application calls {@link NotificationManager#cancel
475         * NotificationManager.cancel(int)}.
476         */
477        public Builder setDeleteIntent(PendingIntent intent) {
478            mNotification.deleteIntent = intent;
479            return this;
480        }
481
482        /**
483         * An intent to launch instead of posting the notification to the status bar.
484         * Only for use with extremely high-priority notifications demanding the user's
485         * <strong>immediate</strong> attention, such as an incoming phone call or
486         * alarm clock that the user has explicitly set to a particular time.
487         * If this facility is used for something else, please give the user an option
488         * to turn it off and use a normal notification, as this can be extremely
489         * disruptive.
490         *
491         * @param intent The pending intent to launch.
492         * @param highPriority Passing true will cause this notification to be sent
493         *          even if other notifications are suppressed.
494         */
495        public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
496            mFullScreenIntent = intent;
497            setFlag(FLAG_HIGH_PRIORITY, highPriority);
498            return this;
499        }
500
501        /**
502         * Set the text that is displayed in the status bar when the notification first
503         * arrives.
504         */
505        public Builder setTicker(CharSequence tickerText) {
506            mNotification.tickerText = tickerText;
507            return this;
508        }
509
510        /**
511         * Set the text that is displayed in the status bar when the notification first
512         * arrives, and also a RemoteViews object that may be displayed instead on some
513         * devices.
514         */
515        public Builder setTicker(CharSequence tickerText, RemoteViews views) {
516            mNotification.tickerText = tickerText;
517            mTickerView = views;
518            return this;
519        }
520
521        /**
522         * Set the large icon that is shown in the ticker and notification.
523         */
524        public Builder setLargeIcon(Bitmap icon) {
525            mLargeIcon = icon;
526            return this;
527        }
528
529        /**
530         * Set the sound to play.  It will play on the default stream.
531         */
532        public Builder setSound(Uri sound) {
533            mNotification.sound = sound;
534            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
535            return this;
536        }
537
538        /**
539         * Set the sound to play.  It will play on the stream you supply.
540         *
541         * @see Notification#STREAM_DEFAULT
542         * @see AudioManager for the <code>STREAM_</code> constants.
543         */
544        public Builder setSound(Uri sound, int streamType) {
545            mNotification.sound = sound;
546            mNotification.audioStreamType = streamType;
547            return this;
548        }
549
550        /**
551         * Set the vibration pattern to use.
552         *
553         * @see android.os.Vibrator for a discussion of the <code>pattern</code>
554         * parameter.
555         */
556        public Builder setVibrate(long[] pattern) {
557            mNotification.vibrate = pattern;
558            return this;
559        }
560
561        /**
562         * Set the argb value that you would like the LED on the device to blnk, as well as the
563         * rate.  The rate is specified in terms of the number of milliseconds to be on
564         * and then the number of milliseconds to be off.
565         */
566        public Builder setLights(int argb, int onMs, int offMs) {
567            mNotification.ledARGB = argb;
568            mNotification.ledOnMS = onMs;
569            mNotification.ledOffMS = offMs;
570            boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0;
571            mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) |
572                    (showLights ? Notification.FLAG_SHOW_LIGHTS : 0);
573            return this;
574        }
575
576        /**
577         * Set whether this is an ongoing notification.
578         *
579         * <p>Ongoing notifications differ from regular notifications in the following ways:
580         * <ul>
581         *   <li>Ongoing notifications are sorted above the regular notifications in the
582         *   notification panel.</li>
583         *   <li>Ongoing notifications do not have an 'X' close button, and are not affected
584         *   by the "Clear all" button.
585         * </ul>
586         */
587        public Builder setOngoing(boolean ongoing) {
588            setFlag(Notification.FLAG_ONGOING_EVENT, ongoing);
589            return this;
590        }
591
592        /**
593         * Set this flag if you would only like the sound, vibrate
594         * and ticker to be played if the notification is not already showing.
595         */
596        public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
597            setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
598            return this;
599        }
600
601        /**
602         * Setting this flag will make it so the notification is automatically
603         * canceled when the user clicks it in the panel.  The PendingIntent
604         * set with {@link #setDeleteIntent} will be broadcast when the notification
605         * is canceled.
606         */
607        public Builder setAutoCancel(boolean autoCancel) {
608            setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel);
609            return this;
610        }
611
612        /**
613         * Set whether or not this notification is only relevant to the current device.
614         *
615         * <p>Some notifications can be bridged to other devices for remote display.
616         * This hint can be set to recommend this notification not be bridged.
617         */
618        public Builder setLocalOnly(boolean b) {
619            mLocalOnly = b;
620            return this;
621        }
622
623        /**
624         * Set the default notification options that will be used.
625         * <p>
626         * The value should be one or more of the following fields combined with
627         * bitwise-or:
628         * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE},
629         * {@link Notification#DEFAULT_LIGHTS}.
630         * <p>
631         * For all default values, use {@link Notification#DEFAULT_ALL}.
632         */
633        public Builder setDefaults(int defaults) {
634            mNotification.defaults = defaults;
635            if ((defaults & Notification.DEFAULT_LIGHTS) != 0) {
636                mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
637            }
638            return this;
639        }
640
641        private void setFlag(int mask, boolean value) {
642            if (value) {
643                mNotification.flags |= mask;
644            } else {
645                mNotification.flags &= ~mask;
646            }
647        }
648
649        /**
650         * Set the relative priority for this notification.
651         *
652         * Priority is an indication of how much of the user's
653         * valuable attention should be consumed by this
654         * notification. Low-priority notifications may be hidden from
655         * the user in certain situations, while the user might be
656         * interrupted for a higher-priority notification.
657         * The system sets a notification's priority based on various factors including the
658         * setPriority value. The effect may differ slightly on different platforms.
659         */
660        public Builder setPriority(int pri) {
661            mPriority = pri;
662            return this;
663        }
664
665        /**
666         * Merge additional metadata into this notification.
667         *
668         * <p>Values within the Bundle will replace existing extras values in this Builder.
669         *
670         * @see Notification#extras
671         */
672        public Builder addExtras(Bundle bag) {
673            if (mExtras == null) {
674                mExtras = new Bundle(bag);
675            } else {
676                mExtras.putAll(bag);
677            }
678            return this;
679        }
680
681        /**
682         * Set metadata for this notification.
683         *
684         * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's
685         * current contents are copied into the Notification each time {@link #build()} is
686         * called.
687         *
688         * <p>Replaces any existing extras values with those from the provided Bundle.
689         * Use {@link #addExtras} to merge in metadata instead.
690         *
691         * @see Notification#extras
692         */
693        public Builder setExtras(Bundle bag) {
694            mExtras = bag;
695            return this;
696        }
697
698        /**
699         * Get the current metadata Bundle used by this notification Builder.
700         *
701         * <p>The returned Bundle is shared with this Builder.
702         *
703         * <p>The current contents of this Bundle are copied into the Notification each time
704         * {@link #build()} is called.
705         *
706         * @see Notification#extras
707         */
708        public Bundle getExtras() {
709            if (mExtras == null) {
710                mExtras = new Bundle();
711            }
712            return mExtras;
713        }
714
715        /**
716         * Add an action to this notification. Actions are typically displayed by
717         * the system as a button adjacent to the notification content.
718         * <br>
719         * Action buttons won't appear on platforms prior to Android 4.1. Action
720         * buttons depend on expanded notifications, which are only available in Android 4.1
721         * and later. To ensure that an action button's functionality is always available, first
722         * implement the functionality in the {@link android.app.Activity} that starts when a user
723         * clicks the  notification (see {@link #setContentIntent setContentIntent()}), and then
724         * enhance the notification by implementing the same functionality with
725         * {@link #addAction addAction()}.
726         *
727         * @param icon Resource ID of a drawable that represents the action.
728         * @param title Text describing the action.
729         * @param intent {@link android.app.PendingIntent} to be fired when the action is invoked.
730         */
731        public Builder addAction(int icon, CharSequence title, PendingIntent intent) {
732            mActions.add(new Action(icon, title, intent));
733            return this;
734        }
735
736        /**
737         * Add a rich notification style to be applied at build time.
738         * <br>
739         * If the platform does not provide rich notification styles, this method has no effect. The
740         * user will always see the normal notification style.
741         *
742         * @param style Object responsible for modifying the notification style.
743         */
744        public Builder setStyle(Style style) {
745            if (mStyle != style) {
746                mStyle = style;
747                if (mStyle != null) {
748                    mStyle.setBuilder(this);
749                }
750            }
751            return this;
752        }
753
754        /**
755         * @deprecated Use {@link #build()} instead.
756         */
757        @Deprecated
758        public Notification getNotification() {
759            return IMPL.build(this);
760        }
761
762        /**
763         * Combine all of the options that have been set and return a new {@link Notification}
764         * object.
765         */
766        public Notification build() {
767            return IMPL.build(this);
768        }
769    }
770
771    /**
772     * An object that can apply a rich notification style to a {@link Notification.Builder}
773     * object.
774     * <br>
775     * If the platform does not provide rich notification styles, methods in this class have no
776     * effect.
777     */
778    public static abstract class Style {
779        Builder mBuilder;
780        CharSequence mBigContentTitle;
781        CharSequence mSummaryText;
782        boolean mSummaryTextSet = false;
783
784        public void setBuilder(Builder builder) {
785            if (mBuilder != builder) {
786                mBuilder = builder;
787                if (mBuilder != null) {
788                    mBuilder.setStyle(this);
789                }
790            }
791        }
792
793        public Notification build() {
794            Notification notification = null;
795            if (mBuilder != null) {
796                notification = mBuilder.build();
797            }
798            return notification;
799        }
800    }
801
802    /**
803     * Helper class for generating large-format notifications that include a large image attachment.
804     * <br>
805     * If the platform does not provide large-format notifications, this method has no effect. The
806     * user will always see the normal notification view.
807     * <br>
808     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
809     * <pre class="prettyprint">
810     * Notification noti = new Notification.Builder()
811     *     .setContentTitle(&quot;New photo from &quot; + sender.toString())
812     *     .setContentText(subject)
813     *     .setSmallIcon(R.drawable.new_post)
814     *     .setLargeIcon(aBitmap)
815     *     .setStyle(new Notification.BigPictureStyle()
816     *         .bigPicture(aBigBitmap))
817     *     .build();
818     * </pre>
819     *
820     * @see Notification#bigContentView
821     */
822    public static class BigPictureStyle extends Style {
823        Bitmap mPicture;
824        Bitmap mBigLargeIcon;
825        boolean mBigLargeIconSet;
826
827        public BigPictureStyle() {
828        }
829
830        public BigPictureStyle(Builder builder) {
831            setBuilder(builder);
832        }
833
834        /**
835         * Overrides ContentTitle in the big form of the template.
836         * This defaults to the value passed to setContentTitle().
837         */
838        public BigPictureStyle setBigContentTitle(CharSequence title) {
839            mBigContentTitle = title;
840            return this;
841        }
842
843        /**
844         * Set the first line of text after the detail section in the big form of the template.
845         */
846        public BigPictureStyle setSummaryText(CharSequence cs) {
847            mSummaryText = cs;
848            mSummaryTextSet = true;
849            return this;
850        }
851
852        /**
853         * Provide the bitmap to be used as the payload for the BigPicture notification.
854         */
855        public BigPictureStyle bigPicture(Bitmap b) {
856            mPicture = b;
857            return this;
858        }
859
860        /**
861         * Override the large icon when the big notification is shown.
862         */
863        public BigPictureStyle bigLargeIcon(Bitmap b) {
864            mBigLargeIcon = b;
865            mBigLargeIconSet = true;
866            return this;
867        }
868    }
869
870    /**
871     * Helper class for generating large-format notifications that include a lot of text.
872     *
873     * <br>
874     * If the platform does not provide large-format notifications, this method has no effect. The
875     * user will always see the normal notification view.
876     * <br>
877     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
878     * <pre class="prettyprint">
879     * Notification noti = new Notification.Builder()
880     *     .setContentTitle(&quot;New mail from &quot; + sender.toString())
881     *     .setContentText(subject)
882     *     .setSmallIcon(R.drawable.new_mail)
883     *     .setLargeIcon(aBitmap)
884     *     .setStyle(new Notification.BigTextStyle()
885     *         .bigText(aVeryLongString))
886     *     .build();
887     * </pre>
888     *
889     * @see Notification#bigContentView
890     */
891    public static class BigTextStyle extends Style {
892        CharSequence mBigText;
893
894        public BigTextStyle() {
895        }
896
897        public BigTextStyle(Builder builder) {
898            setBuilder(builder);
899        }
900
901        /**
902         * Overrides ContentTitle in the big form of the template.
903         * This defaults to the value passed to setContentTitle().
904         */
905        public BigTextStyle setBigContentTitle(CharSequence title) {
906            mBigContentTitle = title;
907            return this;
908        }
909
910        /**
911         * Set the first line of text after the detail section in the big form of the template.
912         */
913        public BigTextStyle setSummaryText(CharSequence cs) {
914            mSummaryText = cs;
915            mSummaryTextSet = true;
916            return this;
917        }
918
919        /**
920         * Provide the longer text to be displayed in the big form of the
921         * template in place of the content text.
922         */
923        public BigTextStyle bigText(CharSequence cs) {
924            mBigText = cs;
925            return this;
926        }
927    }
928
929    /**
930     * Helper class for generating large-format notifications that include a list of (up to 5) strings.
931     *
932     * <br>
933     * If the platform does not provide large-format notifications, this method has no effect. The
934     * user will always see the normal notification view.
935     * <br>
936     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
937     * <pre class="prettyprint">
938     * Notification noti = new Notification.Builder()
939     *     .setContentTitle(&quot;5 New mails from &quot; + sender.toString())
940     *     .setContentText(subject)
941     *     .setSmallIcon(R.drawable.new_mail)
942     *     .setLargeIcon(aBitmap)
943     *     .setStyle(new Notification.InboxStyle()
944     *         .addLine(str1)
945     *         .addLine(str2)
946     *         .setContentTitle(&quot;&quot;)
947     *         .setSummaryText(&quot;+3 more&quot;))
948     *     .build();
949     * </pre>
950     *
951     * @see Notification#bigContentView
952     */
953    public static class InboxStyle extends Style {
954        ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
955
956        public InboxStyle() {
957        }
958
959        public InboxStyle(Builder builder) {
960            setBuilder(builder);
961        }
962
963        /**
964         * Overrides ContentTitle in the big form of the template.
965         * This defaults to the value passed to setContentTitle().
966         */
967        public InboxStyle setBigContentTitle(CharSequence title) {
968            mBigContentTitle = title;
969            return this;
970        }
971
972        /**
973         * Set the first line of text after the detail section in the big form of the template.
974         */
975        public InboxStyle setSummaryText(CharSequence cs) {
976            mSummaryText = cs;
977            mSummaryTextSet = true;
978            return this;
979        }
980
981        /**
982         * Append a line to the digest section of the Inbox notification.
983         */
984        public InboxStyle addLine(CharSequence cs) {
985            mTexts.add(cs);
986            return this;
987        }
988    }
989
990    public static class Action {
991        public int icon;
992        public CharSequence title;
993        public PendingIntent actionIntent;
994
995        public Action(int icon_, CharSequence title_, PendingIntent intent_) {
996            this.icon = icon_;
997            this.title = title_;
998            this.actionIntent = intent_;
999        }
1000    }
1001
1002    /**
1003     * Gets the {@link Notification#extras} field from a notification in a backwards
1004     * compatible manner. Extras field was supported from JellyBean (Api level 16)
1005     * forwards. This function will return null on older api levels.
1006     */
1007    public static Bundle getExtras(Notification notif) {
1008        return IMPL.getExtras(notif);
1009    }
1010
1011    /**
1012     * Get whether or not this notification is only relevant to the current device.
1013     *
1014     * <p>Some notifications can be bridged to other devices for remote display.
1015     * If this hint is set, it is recommend that this notification not be bridged.
1016     */
1017    public static boolean getLocalOnly(Notification notif) {
1018        return IMPL.getLocalOnly(notif);
1019    }
1020}
1021