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