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