NotificationCompat.java revision cd05a19c0775e69e93e4c93b0a48ab044b531d7a
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.PendingIntent;
21import android.content.Context;
22import android.graphics.Bitmap;
23import android.graphics.Color;
24import android.media.AudioManager;
25import android.net.Uri;
26import android.os.Build;
27import android.os.Bundle;
28import android.widget.RemoteViews;
29
30import java.util.ArrayList;
31
32/**
33 * Helper for accessing features in {@link android.app.Notification}
34 * introduced after API level 4 in a backwards compatible fashion.
35 */
36public class NotificationCompat {
37
38    /**
39     * Use all default values (where applicable).
40     */
41    public static final int DEFAULT_ALL = ~0;
42
43    /**
44     * Use the default notification sound. This will ignore any sound set using
45     * {@link Builder#setSound}
46     *
47     * @see Builder#setDefaults
48     */
49    public static final int DEFAULT_SOUND = 1;
50
51    /**
52     * Use the default notification vibrate. This will ignore any vibrate set using
53     * {@link Builder#setVibrate}. Using phone vibration requires the
54     * {@link android.Manifest.permission#VIBRATE VIBRATE} permission.
55     *
56     * @see Builder#setDefaults
57     */
58    public static final int DEFAULT_VIBRATE = 2;
59
60    /**
61     * Use the default notification lights. This will ignore the
62     * {@link #FLAG_SHOW_LIGHTS} bit, and values set with {@link Builder#setLights}.
63     *
64     * @see Builder#setDefaults
65     */
66    public static final int DEFAULT_LIGHTS = 4;
67
68    /**
69     * Use this constant as the value for audioStreamType to request that
70     * the default stream type for notifications be used.  Currently the
71     * default stream type is {@link AudioManager#STREAM_NOTIFICATION}.
72     */
73    public static final int STREAM_DEFAULT = -1;
74
75    /**
76     * Bit set in the Notification flags field when LEDs should be turned on
77     * for this notification.
78     */
79    public static final int FLAG_SHOW_LIGHTS        = 0x00000001;
80
81    /**
82     * Bit set in the Notification flags field if this notification is in
83     * reference to something that is ongoing, like a phone call.  It should
84     * not be set if this notification is in reference to something that
85     * happened at a particular point in time, like a missed phone call.
86     */
87    public static final int FLAG_ONGOING_EVENT      = 0x00000002;
88
89    /**
90     * Bit set in the Notification flags field if
91     * the audio will be repeated until the notification is
92     * cancelled or the notification window is opened.
93     */
94    public static final int FLAG_INSISTENT          = 0x00000004;
95
96    /**
97     * Bit set in the Notification flags field if the notification's sound,
98     * vibrate and ticker should only be played if the notification is not already showing.
99     */
100    public static final int FLAG_ONLY_ALERT_ONCE    = 0x00000008;
101
102    /**
103     * Bit set in the Notification flags field if the notification should be canceled when
104     * it is clicked by the user.
105     */
106    public static final int FLAG_AUTO_CANCEL        = 0x00000010;
107
108    /**
109     * Bit set in the Notification flags field if the notification should not be canceled
110     * when the user clicks the Clear all button.
111     */
112    public static final int FLAG_NO_CLEAR           = 0x00000020;
113
114    /**
115     * Bit set in the Notification flags field if this notification represents a currently
116     * running service.  This will normally be set for you by
117     * {@link android.app.Service#startForeground}.
118     */
119    public static final int FLAG_FOREGROUND_SERVICE = 0x00000040;
120
121    /**
122     * Obsolete flag indicating high-priority notifications; use the priority field instead.
123     *
124     * @deprecated Use {@link NotificationCompat.Builder#setPriority(int)} with a positive value.
125     */
126    public static final int FLAG_HIGH_PRIORITY      = 0x00000080;
127
128    /**
129     * Bit set in the Notification flags field if this notification is relevant to the current
130     * device only and it is not recommended that it bridge to other devices.
131     */
132    public static final int FLAG_LOCAL_ONLY         = 0x00000100;
133
134    /**
135     * Bit set in the Notification flags field if this notification is the group summary for a
136     * group of notifications. Grouped notifications may display in a cluster or stack on devices
137     * which support such rendering. Requires a group key also be set using
138     * {@link Builder#setGroup}.
139     */
140    public static final int FLAG_GROUP_SUMMARY      = 0x00000200;
141
142    /**
143     * Default notification priority for {@link NotificationCompat.Builder#setPriority(int)}.
144     * If your application does not prioritize its own notifications,
145     * use this value for all notifications.
146     */
147    public static final int PRIORITY_DEFAULT = 0;
148
149    /**
150     * Lower notification priority for {@link NotificationCompat.Builder#setPriority(int)},
151     * for items that are less important. The UI may choose to show
152     * these items smaller, or at a different position in the list,
153     * compared with your app's {@link #PRIORITY_DEFAULT} items.
154     */
155    public static final int PRIORITY_LOW = -1;
156
157    /**
158     * Lowest notification priority for {@link NotificationCompat.Builder#setPriority(int)};
159     * these items might not be shown to the user except under
160     * special circumstances, such as detailed notification logs.
161     */
162    public static final int PRIORITY_MIN = -2;
163
164    /**
165     * Higher notification priority for {@link NotificationCompat.Builder#setPriority(int)},
166     * for more important notifications or alerts. The UI may choose
167     * to show these items larger, or at a different position in
168     * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items.
169     */
170    public static final int PRIORITY_HIGH = 1;
171
172    /**
173     * Highest notification priority for {@link NotificationCompat.Builder#setPriority(int)},
174     * for your application's most important items that require the user's
175     * prompt attention or input.
176     */
177    public static final int PRIORITY_MAX = 2;
178
179    /**
180     * Notification extras key: this is the title of the notification,
181     * as supplied to {@link Builder#setContentTitle(CharSequence)}.
182     */
183    public static final String EXTRA_TITLE = "android.title";
184
185    /**
186     * Notification extras key: this is the title of the notification when shown in expanded form,
187     * e.g. as supplied to {@link BigTextStyle#setBigContentTitle(CharSequence)}.
188     */
189    public static final String EXTRA_TITLE_BIG = EXTRA_TITLE + ".big";
190
191    /**
192     * Notification extras key: this is the main text payload, as supplied to
193     * {@link Builder#setContentText(CharSequence)}.
194     */
195    public static final String EXTRA_TEXT = "android.text";
196
197    /**
198     * Notification extras key: this is a third line of text, as supplied to
199     * {@link Builder#setSubText(CharSequence)}.
200     */
201    public static final String EXTRA_SUB_TEXT = "android.subText";
202
203    /**
204     * Notification extras key: this is a small piece of additional text as supplied to
205     * {@link Builder#setContentInfo(CharSequence)}.
206     */
207    public static final String EXTRA_INFO_TEXT = "android.infoText";
208
209    /**
210     * Notification extras key: this is a line of summary information intended to be shown
211     * alongside expanded notifications, as supplied to (e.g.)
212     * {@link BigTextStyle#setSummaryText(CharSequence)}.
213     */
214    public static final String EXTRA_SUMMARY_TEXT = "android.summaryText";
215
216    /**
217     * Notification extras key: this is the resource ID of the notification's main small icon, as
218     * supplied to {@link Builder#setSmallIcon(int)}.
219     */
220    public static final String EXTRA_SMALL_ICON = "android.icon";
221
222    /**
223     * Notification extras key: this is a bitmap to be used instead of the small icon when showing the
224     * notification payload, as
225     * supplied to {@link Builder#setLargeIcon(android.graphics.Bitmap)}.
226     */
227    public static final String EXTRA_LARGE_ICON = "android.largeIcon";
228
229    /**
230     * Notification extras key: this is a bitmap to be used instead of the one from
231     * {@link Builder#setLargeIcon(android.graphics.Bitmap)} when the notification is
232     * shown in its expanded form, as supplied to
233     * {@link BigPictureStyle#bigLargeIcon(android.graphics.Bitmap)}.
234     */
235    public static final String EXTRA_LARGE_ICON_BIG = EXTRA_LARGE_ICON + ".big";
236
237    /**
238     * Notification extras key: this is the progress value supplied to
239     * {@link Builder#setProgress(int, int, boolean)}.
240     */
241    public static final String EXTRA_PROGRESS = "android.progress";
242
243    /**
244     * Notification extras key: this is the maximum value supplied to
245     * {@link Builder#setProgress(int, int, boolean)}.
246     */
247    public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
248
249    /**
250     * Notification extras key: whether the progress bar is indeterminate, supplied to
251     * {@link Builder#setProgress(int, int, boolean)}.
252     */
253    public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
254
255    /**
256     * Notification extras key: whether the when field set using {@link Builder#setWhen} should
257     * be shown as a count-up timer (specifically a {@link android.widget.Chronometer}) instead
258     * of a timestamp, as supplied to {@link Builder#setUsesChronometer(boolean)}.
259     */
260    public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
261
262    /**
263     * Notification extras key: this is a bitmap to be shown in {@link BigPictureStyle} expanded
264     * notifications, supplied to {@link BigPictureStyle#bigPicture(android.graphics.Bitmap)}.
265     */
266    public static final String EXTRA_PICTURE = "android.picture";
267
268    /**
269     * Notification extras key: An array of CharSequences to show in {@link InboxStyle} expanded
270     * notifications, each of which was supplied to {@link InboxStyle#addLine(CharSequence)}.
271     */
272    public static final String EXTRA_TEXT_LINES = "android.textLines";
273
274    /**
275     * Notification extras key: An array of people that this notification relates to, specified
276     * by contacts provider contact URI.
277     */
278    public static final String EXTRA_PEOPLE = "android.people";
279
280    /**
281     * Value of {@link Notification#color} equal to 0 (also known as
282     * {@link android.graphics.Color#TRANSPARENT Color.TRANSPARENT}),
283     * telling the system not to decorate this notification with any special color but instead use
284     * default colors when presenting this notification.
285     */
286    public static final int COLOR_DEFAULT = Color.TRANSPARENT;
287
288    /**
289     * Notification visibility: Show this notification in its entirety on all lockscreens.
290     *
291     * {@see android.app.Notification#visibility}
292     */
293    public static final int VISIBILITY_PUBLIC = 1;
294
295    /**
296     * Notification visibility: Show this notification on all lockscreens, but conceal sensitive or
297     * private information on secure lockscreens.
298     *
299     * {@see android.app.Notification#visibility}
300     */
301    public static final int VISIBILITY_PRIVATE = 0;
302
303    /**
304     * Notification visibility: Do not reveal any part of this notification on a secure lockscreen.
305     *
306     * {@see android.app.Notification#visibility}
307     */
308    public static final int VISIBILITY_SECRET = -1;
309
310    private static final NotificationCompatImpl IMPL;
311
312    interface NotificationCompatImpl {
313        public Notification build(Builder b);
314        public Bundle getExtras(Notification n);
315        public int getActionCount(Notification n);
316        public Action getAction(Notification n, int actionIndex);
317        public boolean getLocalOnly(Notification n);
318        public String getGroup(Notification n);
319        public boolean isGroupSummary(Notification n);
320        public String getSortKey(Notification n);
321    }
322
323    static class NotificationCompatImplBase implements NotificationCompatImpl {
324        @Override
325        public Notification build(Builder b) {
326            Notification result = b.mNotification;
327            result.setLatestEventInfo(b.mContext, b.mContentTitle,
328                    b.mContentText, b.mContentIntent);
329            // translate high priority requests into legacy flag
330            if (b.mPriority > PRIORITY_DEFAULT) {
331                result.flags |= FLAG_HIGH_PRIORITY;
332            }
333            return result;
334        }
335
336        @Override
337        public Bundle getExtras(Notification n) {
338            return null;
339        }
340
341        @Override
342        public int getActionCount(Notification n) {
343            return 0;
344        }
345
346        @Override
347        public Action getAction(Notification n, int actionIndex) {
348            return null;
349        }
350
351        @Override
352        public boolean getLocalOnly(Notification n) {
353            return false;
354        }
355
356        @Override
357        public String getGroup(Notification n) {
358            return null;
359        }
360
361        @Override
362        public boolean isGroupSummary(Notification n) {
363            return false;
364        }
365
366        @Override
367        public String getSortKey(Notification n) {
368            return null;
369        }
370    }
371
372    static class NotificationCompatImplGingerbread extends NotificationCompatImplBase {
373        @Override
374        public Notification build(Builder b) {
375            Notification result = b.mNotification;
376            result.setLatestEventInfo(b.mContext, b.mContentTitle,
377                    b.mContentText, b.mContentIntent);
378            result = NotificationCompatGingerbread.add(result, b.mContext,
379                    b.mContentTitle, b.mContentText, b.mContentIntent, b.mFullScreenIntent);
380            // translate high priority requests into legacy flag
381            if (b.mPriority > PRIORITY_DEFAULT) {
382                result.flags |= FLAG_HIGH_PRIORITY;
383            }
384            return result;
385        }
386    }
387
388    static class NotificationCompatImplHoneycomb extends NotificationCompatImplBase {
389        @Override
390        public Notification build(Builder b) {
391            return NotificationCompatHoneycomb.add(b.mContext, b.mNotification,
392                    b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
393                    b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon);
394        }
395    }
396
397    static class NotificationCompatImplIceCreamSandwich extends NotificationCompatImplBase {
398        @Override
399        public Notification build(Builder b) {
400            return NotificationCompatIceCreamSandwich.add(b.mContext, b.mNotification,
401                    b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
402                    b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
403                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate);
404        }
405    }
406
407    static class NotificationCompatImplJellybean extends NotificationCompatImplBase {
408        @Override
409        public Notification build(Builder b) {
410            NotificationCompatJellybean.Builder builder = new NotificationCompatJellybean.Builder(
411                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
412                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
413                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
414                    b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras,
415                    b.mGroupKey, b.mGroupSummary, b.mSortKey);
416            addActionsToBuilder(builder, b.mActions);
417            addStyleToBuilderJellybean(builder, b.mStyle);
418            return builder.build();
419        }
420
421        @Override
422        public Bundle getExtras(Notification n) {
423            return NotificationCompatJellybean.getExtras(n);
424        }
425
426        @Override
427        public int getActionCount(Notification n) {
428            return NotificationCompatJellybean.getActionCount(n);
429        }
430
431        @Override
432        public Action getAction(Notification n, int actionIndex) {
433            return (Action) NotificationCompatJellybean.getAction(n, actionIndex, Action.FACTORY,
434                    RemoteInput.FACTORY);
435        }
436
437        @Override
438        public boolean getLocalOnly(Notification n) {
439            return NotificationCompatJellybean.getLocalOnly(n);
440        }
441
442        @Override
443        public String getGroup(Notification n) {
444            return NotificationCompatJellybean.getGroup(n);
445        }
446
447        @Override
448        public boolean isGroupSummary(Notification n) {
449            return NotificationCompatJellybean.isGroupSummary(n);
450        }
451
452        @Override
453        public String getSortKey(Notification n) {
454            return NotificationCompatJellybean.getSortKey(n);
455        }
456    }
457
458    static class NotificationCompatImplKitKat extends NotificationCompatImplJellybean {
459        @Override
460        public Notification build(Builder b) {
461            NotificationCompatKitKat.Builder builder = new NotificationCompatKitKat.Builder(
462                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
463                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
464                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
465                    b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mPeople, b.mExtras,
466                    b.mGroupKey, b.mGroupSummary, b.mSortKey);
467            addActionsToBuilder(builder, b.mActions);
468            addStyleToBuilderJellybean(builder, b.mStyle);
469            return builder.build();
470        }
471
472        @Override
473        public Bundle getExtras(Notification n) {
474            return NotificationCompatKitKat.getExtras(n);
475        }
476
477        @Override
478        public int getActionCount(Notification n) {
479            return NotificationCompatKitKat.getActionCount(n);
480        }
481
482        @Override
483        public Action getAction(Notification n, int actionIndex) {
484            return (Action) NotificationCompatKitKat.getAction(n, actionIndex, Action.FACTORY,
485                    RemoteInput.FACTORY);
486        }
487
488        @Override
489        public boolean getLocalOnly(Notification n) {
490            return NotificationCompatKitKat.getLocalOnly(n);
491        }
492
493        @Override
494        public String getGroup(Notification n) {
495            return NotificationCompatKitKat.getGroup(n);
496        }
497
498        @Override
499        public boolean isGroupSummary(Notification n) {
500            return NotificationCompatKitKat.isGroupSummary(n);
501        }
502
503        @Override
504        public String getSortKey(Notification n) {
505            return NotificationCompatKitKat.getSortKey(n);
506        }
507    }
508
509    static class NotificationCompatImplApi20 extends NotificationCompatImplKitKat {
510        @Override
511        public Notification build(Builder b) {
512            NotificationCompatApi20.Builder builder = new NotificationCompatApi20.Builder(
513                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
514                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
515                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
516                    b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory,
517                    b.mPeople, b.mExtras, b.mColor, b.mVisibility, b.mPublicVersion,
518                    b.mGroupKey, b.mGroupSummary, b.mSortKey);
519            addActionsToBuilder(builder, b.mActions);
520            addStyleToBuilderJellybean(builder, b.mStyle);
521            return builder.build();
522        }
523
524        @Override
525        public Action getAction(Notification n, int actionIndex) {
526            return (Action) NotificationCompatApi20.getAction(n, actionIndex, Action.FACTORY,
527                    RemoteInput.FACTORY);
528        }
529
530        @Override
531        public boolean getLocalOnly(Notification n) {
532            return NotificationCompatApi20.getLocalOnly(n);
533        }
534
535        @Override
536        public String getGroup(Notification n) {
537            return NotificationCompatApi20.getGroup(n);
538        }
539
540        @Override
541        public boolean isGroupSummary(Notification n) {
542            return NotificationCompatApi20.isGroupSummary(n);
543        }
544
545        @Override
546        public String getSortKey(Notification n) {
547            return NotificationCompatApi20.getSortKey(n);
548        }
549    }
550
551    private static void addActionsToBuilder(NotificationBuilderWithActions builder,
552            ArrayList<Action> actions) {
553        for (Action action : actions) {
554            builder.addAction(action);
555        }
556    }
557
558    private static void addStyleToBuilderJellybean(NotificationBuilderWithBuilderAccessor builder,
559            Style style) {
560        if (style != null) {
561            if (style instanceof BigTextStyle) {
562                BigTextStyle bigTextStyle = (BigTextStyle) style;
563                NotificationCompatJellybean.addBigTextStyle(builder,
564                        bigTextStyle.mBigContentTitle,
565                        bigTextStyle.mSummaryTextSet,
566                        bigTextStyle.mSummaryText,
567                        bigTextStyle.mBigText);
568            } else if (style instanceof InboxStyle) {
569                InboxStyle inboxStyle = (InboxStyle) style;
570                NotificationCompatJellybean.addInboxStyle(builder,
571                        inboxStyle.mBigContentTitle,
572                        inboxStyle.mSummaryTextSet,
573                        inboxStyle.mSummaryText,
574                        inboxStyle.mTexts);
575            } else if (style instanceof BigPictureStyle) {
576                BigPictureStyle bigPictureStyle = (BigPictureStyle) style;
577                NotificationCompatJellybean.addBigPictureStyle(builder,
578                        bigPictureStyle.mBigContentTitle,
579                        bigPictureStyle.mSummaryTextSet,
580                        bigPictureStyle.mSummaryText,
581                        bigPictureStyle.mPicture,
582                        bigPictureStyle.mBigLargeIcon,
583                        bigPictureStyle.mBigLargeIconSet);
584            }
585        }
586    }
587
588    static {
589        // TODO: Replace this if clause when SDK_INT is incremented to 20.
590        if (Build.VERSION.RELEASE.equals("L")) {
591            IMPL = new NotificationCompatImplApi20();
592        } else if (Build.VERSION.SDK_INT >= 19) {
593            IMPL = new NotificationCompatImplKitKat();
594        } else if (Build.VERSION.SDK_INT >= 16) {
595            IMPL = new NotificationCompatImplJellybean();
596        } else if (Build.VERSION.SDK_INT >= 14) {
597            IMPL = new NotificationCompatImplIceCreamSandwich();
598        } else if (Build.VERSION.SDK_INT >= 11) {
599            IMPL = new NotificationCompatImplHoneycomb();
600        } else if (Build.VERSION.SDK_INT >= 9) {
601            IMPL = new NotificationCompatImplGingerbread();
602        } else {
603            IMPL = new NotificationCompatImplBase();
604        }
605    }
606
607    /**
608     * Builder class for {@link NotificationCompat} objects.  Allows easier control over
609     * all the flags, as well as help constructing the typical notification layouts.
610     * <p>
611     * On platform versions that don't offer expanded notifications, methods that depend on
612     * expanded notifications have no effect.
613     * </p>
614     * <p>
615     * For example, action buttons won't appear on platforms prior to Android 4.1. Action
616     * buttons depend on expanded notifications, which are only available in Android 4.1
617     * and later.
618     * <p>
619     * For this reason, you should always ensure that UI controls in a notification are also
620     * available in an {@link android.app.Activity} in your app, and you should always start that
621     * {@link android.app.Activity} when users click the notification. To do this, use the
622     * {@link NotificationCompat.Builder#setContentIntent setContentIntent()}
623     * method.
624     * </p>
625     *
626     */
627    public static class Builder {
628        Context mContext;
629
630        CharSequence mContentTitle;
631        CharSequence mContentText;
632        PendingIntent mContentIntent;
633        PendingIntent mFullScreenIntent;
634        RemoteViews mTickerView;
635        Bitmap mLargeIcon;
636        CharSequence mContentInfo;
637        int mNumber;
638        int mPriority;
639        boolean mUseChronometer;
640        Style mStyle;
641        CharSequence mSubText;
642        int mProgressMax;
643        int mProgress;
644        boolean mProgressIndeterminate;
645        String mGroupKey;
646        boolean mGroupSummary;
647        String mSortKey;
648        ArrayList<Action> mActions = new ArrayList<Action>();
649        boolean mLocalOnly = false;
650        String mCategory;
651        Bundle mExtras;
652        int mColor = COLOR_DEFAULT;
653        int mVisibility = VISIBILITY_PRIVATE;
654        Notification mPublicVersion;
655
656        Notification mNotification = new Notification();
657        public ArrayList<String> mPeople;
658
659        /**
660         * Constructor.
661         *
662         * Automatically sets the when field to {@link System#currentTimeMillis()
663         * System.currentTimeMillis()} and the audio stream to the
664         * {@link Notification#STREAM_DEFAULT}.
665         *
666         * @param context A {@link Context} that will be used to construct the
667         *      RemoteViews. The Context will not be held past the lifetime of this
668         *      Builder object.
669         */
670        public Builder(Context context) {
671            mContext = context;
672
673            // Set defaults to match the defaults of a Notification
674            mNotification.when = System.currentTimeMillis();
675            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
676            mPriority = PRIORITY_DEFAULT;
677            mPeople = new ArrayList<String>();
678        }
679
680        /**
681         * Set the time that the event occurred.  Notifications in the panel are
682         * sorted by this time.
683         */
684        public Builder setWhen(long when) {
685            mNotification.when = when;
686            return this;
687        }
688
689        /**
690         * Show the {@link Notification#when} field as a stopwatch.
691         *
692         * Instead of presenting <code>when</code> as a timestamp, the notification will show an
693         * automatically updating display of the minutes and seconds since <code>when</code>.
694         *
695         * Useful when showing an elapsed time (like an ongoing phone call).
696         *
697         * @see android.widget.Chronometer
698         * @see Notification#when
699         */
700        public Builder setUsesChronometer(boolean b) {
701            mUseChronometer = b;
702            return this;
703        }
704
705        /**
706         * Set the small icon to use in the notification layouts.  Different classes of devices
707         * may return different sizes.  See the UX guidelines for more information on how to
708         * design these icons.
709         *
710         * @param icon A resource ID in the application's package of the drawble to use.
711         */
712        public Builder setSmallIcon(int icon) {
713            mNotification.icon = icon;
714            return this;
715        }
716
717        /**
718         * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
719         * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
720         * LevelListDrawable}.
721         *
722         * @param icon A resource ID in the application's package of the drawble to use.
723         * @param level The level to use for the icon.
724         *
725         * @see android.graphics.drawable.LevelListDrawable
726         */
727        public Builder setSmallIcon(int icon, int level) {
728            mNotification.icon = icon;
729            mNotification.iconLevel = level;
730            return this;
731        }
732
733        /**
734         * Set the title (first row) of the notification, in a standard notification.
735         */
736        public Builder setContentTitle(CharSequence title) {
737            mContentTitle = title;
738            return this;
739        }
740
741        /**
742         * Set the text (second row) of the notification, in a standard notification.
743         */
744        public Builder setContentText(CharSequence text) {
745            mContentText = text;
746            return this;
747        }
748
749        /**
750         * Set the third line of text in the platform notification template.
751         * Don't use if you're also using {@link #setProgress(int, int, boolean)};
752         * they occupy the same location in the standard template.
753         * <br>
754         * If the platform does not provide large-format notifications, this method has no effect.
755         * The third line of text only appears in expanded view.
756         * <br>
757         */
758        public Builder setSubText(CharSequence text) {
759            mSubText = text;
760            return this;
761        }
762
763        /**
764         * Set the large number at the right-hand side of the notification.  This is
765         * equivalent to setContentInfo, although it might show the number in a different
766         * font size for readability.
767         */
768        public Builder setNumber(int number) {
769            mNumber = number;
770            return this;
771        }
772
773        /**
774         * Set the large text at the right-hand side of the notification.
775         */
776        public Builder setContentInfo(CharSequence info) {
777            mContentInfo = info;
778            return this;
779        }
780
781        /**
782         * Set the progress this notification represents, which may be
783         * represented as a {@link android.widget.ProgressBar}.
784         */
785        public Builder setProgress(int max, int progress, boolean indeterminate) {
786            mProgressMax = max;
787            mProgress = progress;
788            mProgressIndeterminate = indeterminate;
789            return this;
790        }
791
792        /**
793         * Supply a custom RemoteViews to use instead of the standard one.
794         */
795        public Builder setContent(RemoteViews views) {
796            mNotification.contentView = views;
797            return this;
798        }
799
800        /**
801         * Supply a {@link PendingIntent} to send when the notification is clicked.
802         * If you do not supply an intent, you can now add PendingIntents to individual
803         * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
804         * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.  Be sure to
805         * read {@link Notification#contentIntent Notification.contentIntent} for
806         * how to correctly use this.
807         */
808        public Builder setContentIntent(PendingIntent intent) {
809            mContentIntent = intent;
810            return this;
811        }
812
813        /**
814         * Supply a {@link PendingIntent} to send when the notification is cleared by the user
815         * directly from the notification panel.  For example, this intent is sent when the user
816         * clicks the "Clear all" button, or the individual "X" buttons on notifications.  This
817         * intent is not sent when the application calls
818         * {@link android.app.NotificationManager#cancel NotificationManager.cancel(int)}.
819         */
820        public Builder setDeleteIntent(PendingIntent intent) {
821            mNotification.deleteIntent = intent;
822            return this;
823        }
824
825        /**
826         * An intent to launch instead of posting the notification to the status bar.
827         * Only for use with extremely high-priority notifications demanding the user's
828         * <strong>immediate</strong> attention, such as an incoming phone call or
829         * alarm clock that the user has explicitly set to a particular time.
830         * If this facility is used for something else, please give the user an option
831         * to turn it off and use a normal notification, as this can be extremely
832         * disruptive.
833         *
834         * @param intent The pending intent to launch.
835         * @param highPriority Passing true will cause this notification to be sent
836         *          even if other notifications are suppressed.
837         */
838        public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
839            mFullScreenIntent = intent;
840            setFlag(FLAG_HIGH_PRIORITY, highPriority);
841            return this;
842        }
843
844        /**
845         * Set the text that is displayed in the status bar when the notification first
846         * arrives.
847         */
848        public Builder setTicker(CharSequence tickerText) {
849            mNotification.tickerText = tickerText;
850            return this;
851        }
852
853        /**
854         * Set the text that is displayed in the status bar when the notification first
855         * arrives, and also a RemoteViews object that may be displayed instead on some
856         * devices.
857         */
858        public Builder setTicker(CharSequence tickerText, RemoteViews views) {
859            mNotification.tickerText = tickerText;
860            mTickerView = views;
861            return this;
862        }
863
864        /**
865         * Set the large icon that is shown in the ticker and notification.
866         */
867        public Builder setLargeIcon(Bitmap icon) {
868            mLargeIcon = icon;
869            return this;
870        }
871
872        /**
873         * Set the sound to play.  It will play on the default stream.
874         */
875        public Builder setSound(Uri sound) {
876            mNotification.sound = sound;
877            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
878            return this;
879        }
880
881        /**
882         * Set the sound to play.  It will play on the stream you supply.
883         *
884         * @see Notification#STREAM_DEFAULT
885         * @see AudioManager for the <code>STREAM_</code> constants.
886         */
887        public Builder setSound(Uri sound, int streamType) {
888            mNotification.sound = sound;
889            mNotification.audioStreamType = streamType;
890            return this;
891        }
892
893        /**
894         * Set the vibration pattern to use.
895         *
896         * @see android.os.Vibrator for a discussion of the <code>pattern</code>
897         * parameter.
898         */
899        public Builder setVibrate(long[] pattern) {
900            mNotification.vibrate = pattern;
901            return this;
902        }
903
904        /**
905         * Set the argb value that you would like the LED on the device to blnk, as well as the
906         * rate.  The rate is specified in terms of the number of milliseconds to be on
907         * and then the number of milliseconds to be off.
908         */
909        public Builder setLights(int argb, int onMs, int offMs) {
910            mNotification.ledARGB = argb;
911            mNotification.ledOnMS = onMs;
912            mNotification.ledOffMS = offMs;
913            boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0;
914            mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) |
915                    (showLights ? Notification.FLAG_SHOW_LIGHTS : 0);
916            return this;
917        }
918
919        /**
920         * Set whether this is an ongoing notification.
921         *
922         * <p>Ongoing notifications differ from regular notifications in the following ways:
923         * <ul>
924         *   <li>Ongoing notifications are sorted above the regular notifications in the
925         *   notification panel.</li>
926         *   <li>Ongoing notifications do not have an 'X' close button, and are not affected
927         *   by the "Clear all" button.
928         * </ul>
929         */
930        public Builder setOngoing(boolean ongoing) {
931            setFlag(Notification.FLAG_ONGOING_EVENT, ongoing);
932            return this;
933        }
934
935        /**
936         * Set this flag if you would only like the sound, vibrate
937         * and ticker to be played if the notification is not already showing.
938         */
939        public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
940            setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
941            return this;
942        }
943
944        /**
945         * Setting this flag will make it so the notification is automatically
946         * canceled when the user clicks it in the panel.  The PendingIntent
947         * set with {@link #setDeleteIntent} will be broadcast when the notification
948         * is canceled.
949         */
950        public Builder setAutoCancel(boolean autoCancel) {
951            setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel);
952            return this;
953        }
954
955        /**
956         * Set whether or not this notification is only relevant to the current device.
957         *
958         * <p>Some notifications can be bridged to other devices for remote display.
959         * This hint can be set to recommend this notification not be bridged.
960         */
961        public Builder setLocalOnly(boolean b) {
962            mLocalOnly = b;
963            return this;
964        }
965
966        /**
967         * Set the notification category.
968         *
969         * <p>Must be one of the predefined notification categories (see the <code>CATEGORY_*</code>
970         * constants in {@link Notification}) that best describes this notification.
971         * May be used by the system for ranking and filtering.
972         */
973        public Builder setCategory(String category) {
974            mCategory = category;
975            return this;
976        }
977
978        /**
979         * Set the default notification options that will be used.
980         * <p>
981         * The value should be one or more of the following fields combined with
982         * bitwise-or:
983         * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE},
984         * {@link Notification#DEFAULT_LIGHTS}.
985         * <p>
986         * For all default values, use {@link Notification#DEFAULT_ALL}.
987         */
988        public Builder setDefaults(int defaults) {
989            mNotification.defaults = defaults;
990            if ((defaults & Notification.DEFAULT_LIGHTS) != 0) {
991                mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
992            }
993            return this;
994        }
995
996        private void setFlag(int mask, boolean value) {
997            if (value) {
998                mNotification.flags |= mask;
999            } else {
1000                mNotification.flags &= ~mask;
1001            }
1002        }
1003
1004        /**
1005         * Set the relative priority for this notification.
1006         *
1007         * Priority is an indication of how much of the user's
1008         * valuable attention should be consumed by this
1009         * notification. Low-priority notifications may be hidden from
1010         * the user in certain situations, while the user might be
1011         * interrupted for a higher-priority notification.
1012         * The system sets a notification's priority based on various factors including the
1013         * setPriority value. The effect may differ slightly on different platforms.
1014         *
1015         * @param pri Relative priority for this notification. Must be one of
1016         *     the priority constants defined by {@link NotificationCompat}.
1017         *     Acceptable values range from {@link
1018         *     NotificationCompat#PRIORITY_MIN} (-2) to {@link
1019         *     NotificationCompat#PRIORITY_MAX} (2).
1020         */
1021        public Builder setPriority(int pri) {
1022            mPriority = pri;
1023            return this;
1024        }
1025
1026        /**
1027         * Add a person that is relevant to this notification.
1028         *
1029         * @see Notification#EXTRA_PEOPLE
1030         */
1031        public Builder addPerson(String handle) {
1032            mPeople.add(handle);
1033            return this;
1034        }
1035
1036        /**
1037         * Set this notification to be part of a group of notifications sharing the same key.
1038         * Grouped notifications may display in a cluster or stack on devices which
1039         * support such rendering.
1040         *
1041         * <p>To make this notification the summary for its group, also call
1042         * {@link #setGroupSummary}. A sort order can be specified for group members by using
1043         * {@link #setSortKey}.
1044         * @param groupKey The group key of the group.
1045         * @return this object for method chaining
1046         */
1047        public Builder setGroup(String groupKey) {
1048            mGroupKey = groupKey;
1049            return this;
1050        }
1051
1052        /**
1053         * Set this notification to be the group summary for a group of notifications.
1054         * Grouped notifications may display in a cluster or stack on devices which
1055         * support such rendering. Requires a group key also be set using {@link #setGroup}.
1056         * @param isGroupSummary Whether this notification should be a group summary.
1057         * @return this object for method chaining
1058         */
1059        public Builder setGroupSummary(boolean isGroupSummary) {
1060            mGroupSummary = isGroupSummary;
1061            return this;
1062        }
1063
1064        /**
1065         * Set a sort key that orders this notification among other notifications from the
1066         * same package. This can be useful if an external sort was already applied and an app
1067         * would like to preserve this. Notifications will be sorted lexicographically using this
1068         * value, although providing different priorities in addition to providing sort key may
1069         * cause this value to be ignored.
1070         *
1071         * <p>This sort key can also be used to order members of a notification group. See
1072         * {@link Builder#setGroup}.
1073         *
1074         * @see String#compareTo(String)
1075         */
1076        public Builder setSortKey(String sortKey) {
1077            mSortKey = sortKey;
1078            return this;
1079        }
1080
1081        /**
1082         * Merge additional metadata into this notification.
1083         *
1084         * <p>Values within the Bundle will replace existing extras values in this Builder.
1085         *
1086         * @see Notification#extras
1087         */
1088        public Builder addExtras(Bundle extras) {
1089            if (extras != null) {
1090                if (mExtras == null) {
1091                    mExtras = new Bundle(extras);
1092                } else {
1093                    mExtras.putAll(extras);
1094                }
1095            }
1096            return this;
1097        }
1098
1099        /**
1100         * Set metadata for this notification.
1101         *
1102         * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's
1103         * current contents are copied into the Notification each time {@link #build()} is
1104         * called.
1105         *
1106         * <p>Replaces any existing extras values with those from the provided Bundle.
1107         * Use {@link #addExtras} to merge in metadata instead.
1108         *
1109         * @see Notification#extras
1110         */
1111        public Builder setExtras(Bundle extras) {
1112            mExtras = extras;
1113            return this;
1114        }
1115
1116        /**
1117         * Get the current metadata Bundle used by this notification Builder.
1118         *
1119         * <p>The returned Bundle is shared with this Builder.
1120         *
1121         * <p>The current contents of this Bundle are copied into the Notification each time
1122         * {@link #build()} is called.
1123         *
1124         * @see Notification#extras
1125         */
1126        public Bundle getExtras() {
1127            if (mExtras == null) {
1128                mExtras = new Bundle();
1129            }
1130            return mExtras;
1131        }
1132
1133        /**
1134         * Add an action to this notification. Actions are typically displayed by
1135         * the system as a button adjacent to the notification content.
1136         * <br>
1137         * Action buttons won't appear on platforms prior to Android 4.1. Action
1138         * buttons depend on expanded notifications, which are only available in Android 4.1
1139         * and later. To ensure that an action button's functionality is always available, first
1140         * implement the functionality in the {@link android.app.Activity} that starts when a user
1141         * clicks the  notification (see {@link #setContentIntent setContentIntent()}), and then
1142         * enhance the notification by implementing the same functionality with
1143         * {@link #addAction addAction()}.
1144         *
1145         * @param icon Resource ID of a drawable that represents the action.
1146         * @param title Text describing the action.
1147         * @param intent {@link android.app.PendingIntent} to be fired when the action is invoked.
1148         */
1149        public Builder addAction(int icon, CharSequence title, PendingIntent intent) {
1150            mActions.add(new Action(icon, title, intent));
1151            return this;
1152        }
1153
1154        /**
1155         * Add an action to this notification. Actions are typically displayed by
1156         * the system as a button adjacent to the notification content.
1157         * <br>
1158         * Action buttons won't appear on platforms prior to Android 4.1. Action
1159         * buttons depend on expanded notifications, which are only available in Android 4.1
1160         * and later. To ensure that an action button's functionality is always available, first
1161         * implement the functionality in the {@link android.app.Activity} that starts when a user
1162         * clicks the  notification (see {@link #setContentIntent setContentIntent()}), and then
1163         * enhance the notification by implementing the same functionality with
1164         * {@link #addAction addAction()}.
1165         *
1166         * @param action The action to add.
1167         */
1168        public Builder addAction(Action action) {
1169            mActions.add(action);
1170            return this;
1171        }
1172
1173        /**
1174         * Add a rich notification style to be applied at build time.
1175         * <br>
1176         * If the platform does not provide rich notification styles, this method has no effect. The
1177         * user will always see the normal notification style.
1178         *
1179         * @param style Object responsible for modifying the notification style.
1180         */
1181        public Builder setStyle(Style style) {
1182            if (mStyle != style) {
1183                mStyle = style;
1184                if (mStyle != null) {
1185                    mStyle.setBuilder(this);
1186                }
1187            }
1188            return this;
1189        }
1190
1191        /**
1192         * Sets {@link Notification#color}.
1193         *
1194         * @param argb The accent color to use
1195         *
1196         * @return The same Builder.
1197         */
1198        public Builder setColor(int argb) {
1199            mColor = argb;
1200            return this;
1201        }
1202
1203        /**
1204         * Sets {@link Notification#visibility}.
1205         *
1206         * @param visibility One of {@link Notification#VISIBILITY_PRIVATE} (the default),
1207         *                   {@link Notification#VISIBILITY_PUBLIC}, or
1208         *                   {@link Notification#VISIBILITY_SECRET}.
1209         */
1210        public Builder setVisibility(int visibility) {
1211            mVisibility = visibility;
1212            return this;
1213        }
1214
1215        /**
1216         * Supply a replacement Notification whose contents should be shown in insecure contexts
1217         * (i.e. atop the secure lockscreen). See {@link Notification#visibility} and
1218         * {@link #VISIBILITY_PUBLIC}.
1219         *
1220         * @param n A replacement notification, presumably with some or all info redacted.
1221         * @return The same Builder.
1222         */
1223        public Builder setPublicVersion(Notification n) {
1224            mPublicVersion = n;
1225            return this;
1226        }
1227
1228        /**
1229         * Apply an extender to this notification builder. Extenders may be used to add
1230         * metadata or change options on this builder.
1231         */
1232        public Builder apply(Extender extender) {
1233            extender.applyTo(this);
1234            return this;
1235        }
1236
1237        /**
1238         * Extender interface for use with {@link #apply}. Extenders may be used to add
1239         * metadata or change options on this builder.
1240         */
1241        public interface Extender {
1242            /**
1243             * Apply this extender to a notification builder.
1244             * @param builder the builder to be modified.
1245             * @return the build object for chaining.
1246             */
1247            public Builder applyTo(Builder builder);
1248        }
1249
1250        /**
1251         * @deprecated Use {@link #build()} instead.
1252         */
1253        @Deprecated
1254        public Notification getNotification() {
1255            return IMPL.build(this);
1256        }
1257
1258        /**
1259         * Combine all of the options that have been set and return a new {@link Notification}
1260         * object.
1261         */
1262        public Notification build() {
1263            return IMPL.build(this);
1264        }
1265    }
1266
1267    /**
1268     * An object that can apply a rich notification style to a {@link Notification.Builder}
1269     * object.
1270     * <br>
1271     * If the platform does not provide rich notification styles, methods in this class have no
1272     * effect.
1273     */
1274    public static abstract class Style {
1275        Builder mBuilder;
1276        CharSequence mBigContentTitle;
1277        CharSequence mSummaryText;
1278        boolean mSummaryTextSet = false;
1279
1280        public void setBuilder(Builder builder) {
1281            if (mBuilder != builder) {
1282                mBuilder = builder;
1283                if (mBuilder != null) {
1284                    mBuilder.setStyle(this);
1285                }
1286            }
1287        }
1288
1289        public Notification build() {
1290            Notification notification = null;
1291            if (mBuilder != null) {
1292                notification = mBuilder.build();
1293            }
1294            return notification;
1295        }
1296    }
1297
1298    /**
1299     * Helper class for generating large-format notifications that include a large image attachment.
1300     * <br>
1301     * If the platform does not provide large-format notifications, this method has no effect. The
1302     * user will always see the normal notification view.
1303     * <br>
1304     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
1305     * <pre class="prettyprint">
1306     * Notification noti = new Notification.Builder()
1307     *     .setContentTitle(&quot;New photo from &quot; + sender.toString())
1308     *     .setContentText(subject)
1309     *     .setSmallIcon(R.drawable.new_post)
1310     *     .setLargeIcon(aBitmap)
1311     *     .setStyle(new Notification.BigPictureStyle()
1312     *         .bigPicture(aBigBitmap))
1313     *     .build();
1314     * </pre>
1315     *
1316     * @see Notification#bigContentView
1317     */
1318    public static class BigPictureStyle extends Style {
1319        Bitmap mPicture;
1320        Bitmap mBigLargeIcon;
1321        boolean mBigLargeIconSet;
1322
1323        public BigPictureStyle() {
1324        }
1325
1326        public BigPictureStyle(Builder builder) {
1327            setBuilder(builder);
1328        }
1329
1330        /**
1331         * Overrides ContentTitle in the big form of the template.
1332         * This defaults to the value passed to setContentTitle().
1333         */
1334        public BigPictureStyle setBigContentTitle(CharSequence title) {
1335            mBigContentTitle = title;
1336            return this;
1337        }
1338
1339        /**
1340         * Set the first line of text after the detail section in the big form of the template.
1341         */
1342        public BigPictureStyle setSummaryText(CharSequence cs) {
1343            mSummaryText = cs;
1344            mSummaryTextSet = true;
1345            return this;
1346        }
1347
1348        /**
1349         * Provide the bitmap to be used as the payload for the BigPicture notification.
1350         */
1351        public BigPictureStyle bigPicture(Bitmap b) {
1352            mPicture = b;
1353            return this;
1354        }
1355
1356        /**
1357         * Override the large icon when the big notification is shown.
1358         */
1359        public BigPictureStyle bigLargeIcon(Bitmap b) {
1360            mBigLargeIcon = b;
1361            mBigLargeIconSet = true;
1362            return this;
1363        }
1364    }
1365
1366    /**
1367     * Helper class for generating large-format notifications that include a lot of text.
1368     *
1369     * <br>
1370     * If the platform does not provide large-format notifications, this method has no effect. The
1371     * user will always see the normal notification view.
1372     * <br>
1373     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
1374     * <pre class="prettyprint">
1375     * Notification noti = new Notification.Builder()
1376     *     .setContentTitle(&quot;New mail from &quot; + sender.toString())
1377     *     .setContentText(subject)
1378     *     .setSmallIcon(R.drawable.new_mail)
1379     *     .setLargeIcon(aBitmap)
1380     *     .setStyle(new Notification.BigTextStyle()
1381     *         .bigText(aVeryLongString))
1382     *     .build();
1383     * </pre>
1384     *
1385     * @see Notification#bigContentView
1386     */
1387    public static class BigTextStyle extends Style {
1388        CharSequence mBigText;
1389
1390        public BigTextStyle() {
1391        }
1392
1393        public BigTextStyle(Builder builder) {
1394            setBuilder(builder);
1395        }
1396
1397        /**
1398         * Overrides ContentTitle in the big form of the template.
1399         * This defaults to the value passed to setContentTitle().
1400         */
1401        public BigTextStyle setBigContentTitle(CharSequence title) {
1402            mBigContentTitle = title;
1403            return this;
1404        }
1405
1406        /**
1407         * Set the first line of text after the detail section in the big form of the template.
1408         */
1409        public BigTextStyle setSummaryText(CharSequence cs) {
1410            mSummaryText = cs;
1411            mSummaryTextSet = true;
1412            return this;
1413        }
1414
1415        /**
1416         * Provide the longer text to be displayed in the big form of the
1417         * template in place of the content text.
1418         */
1419        public BigTextStyle bigText(CharSequence cs) {
1420            mBigText = cs;
1421            return this;
1422        }
1423    }
1424
1425    /**
1426     * Helper class for generating large-format notifications that include a list of (up to 5) strings.
1427     *
1428     * <br>
1429     * If the platform does not provide large-format notifications, this method has no effect. The
1430     * user will always see the normal notification view.
1431     * <br>
1432     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
1433     * <pre class="prettyprint">
1434     * Notification noti = new Notification.Builder()
1435     *     .setContentTitle(&quot;5 New mails from &quot; + sender.toString())
1436     *     .setContentText(subject)
1437     *     .setSmallIcon(R.drawable.new_mail)
1438     *     .setLargeIcon(aBitmap)
1439     *     .setStyle(new Notification.InboxStyle()
1440     *         .addLine(str1)
1441     *         .addLine(str2)
1442     *         .setContentTitle(&quot;&quot;)
1443     *         .setSummaryText(&quot;+3 more&quot;))
1444     *     .build();
1445     * </pre>
1446     *
1447     * @see Notification#bigContentView
1448     */
1449    public static class InboxStyle extends Style {
1450        ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
1451
1452        public InboxStyle() {
1453        }
1454
1455        public InboxStyle(Builder builder) {
1456            setBuilder(builder);
1457        }
1458
1459        /**
1460         * Overrides ContentTitle in the big form of the template.
1461         * This defaults to the value passed to setContentTitle().
1462         */
1463        public InboxStyle setBigContentTitle(CharSequence title) {
1464            mBigContentTitle = title;
1465            return this;
1466        }
1467
1468        /**
1469         * Set the first line of text after the detail section in the big form of the template.
1470         */
1471        public InboxStyle setSummaryText(CharSequence cs) {
1472            mSummaryText = cs;
1473            mSummaryTextSet = true;
1474            return this;
1475        }
1476
1477        /**
1478         * Append a line to the digest section of the Inbox notification.
1479         */
1480        public InboxStyle addLine(CharSequence cs) {
1481            mTexts.add(cs);
1482            return this;
1483        }
1484    }
1485
1486    /**
1487     * Structure to encapsulate a named action that can be shown as part of this notification.
1488     * It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is
1489     * selected by the user. Action buttons won't appear on platforms prior to Android 4.1.
1490     * <p>
1491     * Apps should use {@link NotificationCompat.Builder#addAction(int, CharSequence, PendingIntent)}
1492     * or {@link NotificationCompat.Builder#addAction(NotificationCompat.Action)}
1493     * to attach actions.
1494     */
1495    public static class Action extends NotificationCompatBase.Action {
1496        private final Bundle mExtras;
1497        private RemoteInput[] mRemoteInputs;
1498
1499        /**
1500         * Small icon representing the action.
1501         */
1502        public int icon;
1503        /**
1504         * Title of the action.
1505         */
1506        public CharSequence title;
1507        /**
1508         * Intent to send when the user invokes this action. May be null, in which case the action
1509         * may be rendered in a disabled presentation.
1510         */
1511        public PendingIntent actionIntent;
1512
1513        public Action(int icon, CharSequence title, PendingIntent intent) {
1514            this(icon, title, intent, new Bundle(), null);
1515        }
1516
1517        private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras,
1518                RemoteInput[] remoteInputs) {
1519            this.icon = icon;
1520            this.title = title;
1521            this.actionIntent = intent;
1522            this.mExtras = extras != null ? extras : new Bundle();
1523            this.mRemoteInputs = remoteInputs;
1524        }
1525
1526        @Override
1527        protected int getIcon() {
1528            return icon;
1529        }
1530
1531        @Override
1532        protected CharSequence getTitle() {
1533            return title;
1534        }
1535
1536        @Override
1537        protected PendingIntent getActionIntent() {
1538            return actionIntent;
1539        }
1540
1541        /**
1542         * Get additional metadata carried around with this Action.
1543         */
1544        public Bundle getExtras() {
1545            return mExtras;
1546        }
1547
1548        /**
1549         * Get the list of inputs to be collected from the user when this action is sent.
1550         * May return null if no remote inputs were added.
1551         */
1552        public RemoteInput[] getRemoteInputs() {
1553            return mRemoteInputs;
1554        }
1555
1556        /**
1557         * Builder class for {@link Action} objects.
1558         */
1559        public static final class Builder {
1560            private final int mIcon;
1561            private final CharSequence mTitle;
1562            private final PendingIntent mIntent;
1563            private final Bundle mExtras;
1564            private ArrayList<RemoteInput> mRemoteInputs;
1565
1566            /**
1567             * Construct a new builder for {@link Action} object.
1568             * @param icon icon to show for this action
1569             * @param title the title of the action
1570             * @param intent the {@link PendingIntent} to fire when users trigger this action
1571             */
1572            public Builder(int icon, CharSequence title, PendingIntent intent) {
1573                this(icon, title, intent, new Bundle());
1574            }
1575
1576            /**
1577             * Construct a new builder for {@link Action} object using the fields from an
1578             * {@link Action}.
1579             * @param action the action to read fields from.
1580             */
1581            public Builder(Action action) {
1582                this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras));
1583            }
1584
1585            private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
1586                mIcon = icon;
1587                mTitle = title;
1588                mIntent = intent;
1589                mExtras = extras;
1590            }
1591
1592            /**
1593             * Merge additional metadata into this builder.
1594             *
1595             * <p>Values within the Bundle will replace existing extras values in this Builder.
1596             *
1597             * @see NotificationCompat.Action#getExtras
1598             */
1599            public Builder addExtras(Bundle extras) {
1600                if (extras != null) {
1601                    mExtras.putAll(extras);
1602                }
1603                return this;
1604            }
1605
1606            /**
1607             * Get the metadata Bundle used by this Builder.
1608             *
1609             * <p>The returned Bundle is shared with this Builder.
1610             */
1611            public Bundle getExtras() {
1612                return mExtras;
1613            }
1614
1615            /**
1616             * Add an input to be collected from the user when this action is sent.
1617             * Response values can be retrieved from the fired intent by using the
1618             * {@link RemoteInput#getResultsFromIntent} function.
1619             * @param remoteInput a {@link RemoteInput} to add to the action
1620             * @return this object for method chaining
1621             */
1622            public Builder addRemoteInput(RemoteInput remoteInput) {
1623                if (mRemoteInputs == null) {
1624                    mRemoteInputs = new ArrayList<RemoteInput>();
1625                }
1626                mRemoteInputs.add(remoteInput);
1627                return this;
1628            }
1629
1630            /**
1631             * Apply an extender to this action builder. Extenders may be used to add
1632             * metadata or change options on this builder.
1633             */
1634            public Builder apply(Extender extender) {
1635                extender.applyTo(this);
1636                return this;
1637            }
1638
1639            /**
1640             * Extender interface for use with {@link #apply}. Extenders may be used to add
1641             * metadata or change options on this builder.
1642             */
1643            public interface Extender {
1644                /**
1645                 * Apply this extender to a notification action builder.
1646                 * @param builder the builder to be modified.
1647                 * @return the build object for chaining.
1648                 */
1649                public Builder applyTo(Builder builder);
1650            }
1651
1652            /**
1653             * Combine all of the options that have been set and return a new {@link Action}
1654             * object.
1655             * @return the built action
1656             */
1657            public Action build() {
1658                RemoteInput[] remoteInputs = mRemoteInputs != null
1659                        ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null;
1660                return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs);
1661            }
1662        }
1663
1664        /** @hide */
1665        public static final Factory FACTORY = new Factory() {
1666            @Override
1667            public Action build(int icon, CharSequence title,
1668                    PendingIntent actionIntent, Bundle extras,
1669                    RemoteInputCompatBase.RemoteInput[] remoteInputs) {
1670                return new Action(icon, title, actionIntent, extras,
1671                        (RemoteInput[]) remoteInputs);
1672            }
1673
1674            @Override
1675            public Action[] newArray(int length) {
1676                return new Action[length];
1677            }
1678        };
1679    }
1680
1681    /**
1682     * Gets the {@link Notification#extras} field from a notification in a backwards
1683     * compatible manner. Extras field was supported from JellyBean (Api level 16)
1684     * forwards. This function will return null on older api levels.
1685     */
1686    public static Bundle getExtras(Notification notif) {
1687        return IMPL.getExtras(notif);
1688    }
1689
1690    /**
1691     * Get the number of actions in this notification in a backwards compatible
1692     * manner. Actions were supported from JellyBean (Api level 16) forwards.
1693     */
1694    public static int getActionCount(Notification notif) {
1695        return IMPL.getActionCount(notif);
1696    }
1697
1698    /**
1699     * Get an action on this notification in a backwards compatible
1700     * manner. Actions were supported from JellyBean (Api level 16) forwards.
1701     * @param notif The notification to inspect.
1702     * @param actionIndex The index of the action to retrieve.
1703     */
1704    public static Action getAction(Notification notif, int actionIndex) {
1705        return IMPL.getAction(notif, actionIndex);
1706    }
1707
1708    /**
1709     * Get whether or not this notification is only relevant to the current device.
1710     *
1711     * <p>Some notifications can be bridged to other devices for remote display.
1712     * If this hint is set, it is recommend that this notification not be bridged.
1713     */
1714    public static boolean getLocalOnly(Notification notif) {
1715        return IMPL.getLocalOnly(notif);
1716    }
1717
1718    /**
1719     * Get the key used to group this notification into a cluster or stack
1720     * with other notifications on devices which support such rendering.
1721     */
1722    public static String getGroup(Notification notif) {
1723        return IMPL.getGroup(notif);
1724    }
1725
1726    /**
1727     * Get whether this notification to be the group summary for a group of notifications.
1728     * Grouped notifications may display in a cluster or stack on devices which
1729     * support such rendering. Requires a group key also be set using {@link Builder#setGroup}.
1730     * @return Whether this notification is a group summary.
1731     */
1732    public static boolean isGroupSummary(Notification notif) {
1733        return IMPL.isGroupSummary(notif);
1734    }
1735
1736    /**
1737     * Get a sort key that orders this notification among other notifications from the
1738     * same package. This can be useful if an external sort was already applied and an app
1739     * would like to preserve this. Notifications will be sorted lexicographically using this
1740     * value, although providing different priorities in addition to providing sort key may
1741     * cause this value to be ignored.
1742     *
1743     * <p>This sort key can also be used to order members of a notification group. See
1744     * {@link Builder#setGroup}.
1745     *
1746     * @see String#compareTo(String)
1747     */
1748    public static String getSortKey(Notification notif) {
1749        return IMPL.getSortKey(notif);
1750    }
1751}
1752