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