NotificationCompat.java revision 080df8ffb0920eccb300baa39180eb956a000a53
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 Notification} objects.  Allows easier control over
164     * all the flags, as well as help constructing the typical notification layouts.
165     */
166    public static class Builder {
167        Context mContext;
168
169        CharSequence mContentTitle;
170        CharSequence mContentText;
171        PendingIntent mContentIntent;
172        PendingIntent mFullScreenIntent;
173        RemoteViews mTickerView;
174        Bitmap mLargeIcon;
175        CharSequence mContentInfo;
176        int mNumber;
177        int mPriority;
178        boolean mUseChronometer;
179        Style mStyle;
180        CharSequence mSubText;
181        int mProgressMax;
182        int mProgress;
183        boolean mProgressIndeterminate;
184        ArrayList<Action> mActions = new ArrayList<Action>();
185
186        Notification mNotification = new Notification();
187
188        /**
189         * Constructor.
190         *
191         * Automatically sets the when field to {@link System#currentTimeMillis()
192         * System.currentTimeMillis()} and the audio stream to the
193         * {@link Notification#STREAM_DEFAULT}.
194         *
195         * @param context A {@link Context} that will be used to construct the
196         *      RemoteViews. The Context will not be held past the lifetime of this
197         *      Builder object.
198         */
199        public Builder(Context context) {
200            mContext = context;
201
202            // Set defaults to match the defaults of a Notification
203            mNotification.when = System.currentTimeMillis();
204            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
205            mPriority = PRIORITY_DEFAULT;
206        }
207
208        /**
209         * Set the time that the event occurred.  Notifications in the panel are
210         * sorted by this time.
211         */
212        public Builder setWhen(long when) {
213            mNotification.when = when;
214            return this;
215        }
216
217        /**
218         * Show the {@link Notification#when} field as a stopwatch.
219         *
220         * Instead of presenting <code>when</code> as a timestamp, the notification will show an
221         * automatically updating display of the minutes and seconds since <code>when</code>.
222         *
223         * Useful when showing an elapsed time (like an ongoing phone call).
224         *
225         * @see android.widget.Chronometer
226         * @see Notification#when
227         */
228        public Builder setUsesChronometer(boolean b) {
229            mUseChronometer = b;
230            return this;
231        }
232
233        /**
234         * Set the small icon to use in the notification layouts.  Different classes of devices
235         * may return different sizes.  See the UX guidelines for more information on how to
236         * design these icons.
237         *
238         * @param icon A resource ID in the application's package of the drawble to use.
239         */
240        public Builder setSmallIcon(int icon) {
241            mNotification.icon = icon;
242            return this;
243        }
244
245        /**
246         * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
247         * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
248         * LevelListDrawable}.
249         *
250         * @param icon A resource ID in the application's package of the drawble to use.
251         * @param level The level to use for the icon.
252         *
253         * @see android.graphics.drawable.LevelListDrawable
254         */
255        public Builder setSmallIcon(int icon, int level) {
256            mNotification.icon = icon;
257            mNotification.iconLevel = level;
258            return this;
259        }
260
261        /**
262         * Set the title (first row) of the notification, in a standard notification.
263         */
264        public Builder setContentTitle(CharSequence title) {
265            mContentTitle = title;
266            return this;
267        }
268
269        /**
270         * Set the text (second row) of the notification, in a standard notification.
271         */
272        public Builder setContentText(CharSequence text) {
273            mContentText = text;
274            return this;
275        }
276
277        /**
278         * Set the third line of text in the platform notification template.
279         * Don't use if you're also using {@link #setProgress(int, int, boolean)};
280         * they occupy the same location in the standard template.
281         */
282        public Builder setSubText(CharSequence text) {
283            mSubText = text;
284            return this;
285        }
286
287        /**
288         * Set the large number at the right-hand side of the notification.  This is
289         * equivalent to setContentInfo, although it might show the number in a different
290         * font size for readability.
291         */
292        public Builder setNumber(int number) {
293            mNumber = number;
294            return this;
295        }
296
297        /**
298         * Set the large text at the right-hand side of the notification.
299         */
300        public Builder setContentInfo(CharSequence info) {
301            mContentInfo = info;
302            return this;
303        }
304
305        /**
306         * Set the progress this notification represents, which may be
307         * represented as a {@link android.widget.ProgressBar}.
308         */
309        public Builder setProgress(int max, int progress, boolean indeterminate) {
310            mProgressMax = max;
311            mProgress = progress;
312            mProgressIndeterminate = indeterminate;
313            return this;
314        }
315
316        /**
317         * Supply a custom RemoteViews to use instead of the standard one.
318         */
319        public Builder setContent(RemoteViews views) {
320            mNotification.contentView = views;
321            return this;
322        }
323
324        /**
325         * Supply a {@link PendingIntent} to send when the notification is clicked.
326         * If you do not supply an intent, you can now add PendingIntents to individual
327         * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
328         * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.  Be sure to
329         * read {@link Notification#contentIntent Notification.contentIntent} for
330         * how to correctly use this.
331         */
332        public Builder setContentIntent(PendingIntent intent) {
333            mContentIntent = intent;
334            return this;
335        }
336
337        /**
338         * Supply a {@link PendingIntent} to send when the notification is cleared by the user
339         * directly from the notification panel.  For example, this intent is sent when the user
340         * clicks the "Clear all" button, or the individual "X" buttons on notifications.  This
341         * intent is not sent when the application calls {@link NotificationManager#cancel
342         * NotificationManager.cancel(int)}.
343         */
344        public Builder setDeleteIntent(PendingIntent intent) {
345            mNotification.deleteIntent = intent;
346            return this;
347        }
348
349        /**
350         * An intent to launch instead of posting the notification to the status bar.
351         * Only for use with extremely high-priority notifications demanding the user's
352         * <strong>immediate</strong> attention, such as an incoming phone call or
353         * alarm clock that the user has explicitly set to a particular time.
354         * If this facility is used for something else, please give the user an option
355         * to turn it off and use a normal notification, as this can be extremely
356         * disruptive.
357         *
358         * @param intent The pending intent to launch.
359         * @param highPriority Passing true will cause this notification to be sent
360         *          even if other notifications are suppressed.
361         */
362        public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
363            mFullScreenIntent = intent;
364            setFlag(FLAG_HIGH_PRIORITY, highPriority);
365            return this;
366        }
367
368        /**
369         * Set the text that is displayed in the status bar when the notification first
370         * arrives.
371         */
372        public Builder setTicker(CharSequence tickerText) {
373            mNotification.tickerText = tickerText;
374            return this;
375        }
376
377        /**
378         * Set the text that is displayed in the status bar when the notification first
379         * arrives, and also a RemoteViews object that may be displayed instead on some
380         * devices.
381         */
382        public Builder setTicker(CharSequence tickerText, RemoteViews views) {
383            mNotification.tickerText = tickerText;
384            mTickerView = views;
385            return this;
386        }
387
388        /**
389         * Set the large icon that is shown in the ticker and notification.
390         */
391        public Builder setLargeIcon(Bitmap icon) {
392            mLargeIcon = icon;
393            return this;
394        }
395
396        /**
397         * Set the sound to play.  It will play on the default stream.
398         */
399        public Builder setSound(Uri sound) {
400            mNotification.sound = sound;
401            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
402            return this;
403        }
404
405        /**
406         * Set the sound to play.  It will play on the stream you supply.
407         *
408         * @see #STREAM_DEFAULT
409         * @see AudioManager for the <code>STREAM_</code> constants.
410         */
411        public Builder setSound(Uri sound, int streamType) {
412            mNotification.sound = sound;
413            mNotification.audioStreamType = streamType;
414            return this;
415        }
416
417        /**
418         * Set the vibration pattern to use.
419         *
420         * @see android.os.Vibrator for a discussion of the <code>pattern</code>
421         * parameter.
422         */
423        public Builder setVibrate(long[] pattern) {
424            mNotification.vibrate = pattern;
425            return this;
426        }
427
428        /**
429         * Set the argb value that you would like the LED on the device to blnk, as well as the
430         * rate.  The rate is specified in terms of the number of milliseconds to be on
431         * and then the number of milliseconds to be off.
432         */
433        public Builder setLights(int argb, int onMs, int offMs) {
434            mNotification.ledARGB = argb;
435            mNotification.ledOnMS = onMs;
436            mNotification.ledOffMS = offMs;
437            boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0;
438            mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) |
439                    (showLights ? Notification.FLAG_SHOW_LIGHTS : 0);
440            return this;
441        }
442
443        /**
444         * Set whether this is an ongoing notification.
445         *
446         * <p>Ongoing notifications differ from regular notifications in the following ways:
447         * <ul>
448         *   <li>Ongoing notifications are sorted above the regular notifications in the
449         *   notification panel.</li>
450         *   <li>Ongoing notifications do not have an 'X' close button, and are not affected
451         *   by the "Clear all" button.
452         * </ul>
453         */
454        public Builder setOngoing(boolean ongoing) {
455            setFlag(Notification.FLAG_ONGOING_EVENT, ongoing);
456            return this;
457        }
458
459        /**
460         * Set this flag if you would only like the sound, vibrate
461         * and ticker to be played if the notification is not already showing.
462         */
463        public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
464            setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
465            return this;
466        }
467
468        /**
469         * Setting this flag will make it so the notification is automatically
470         * canceled when the user clicks it in the panel.  The PendingIntent
471         * set with {@link #setDeleteIntent} will be broadcast when the notification
472         * is canceled.
473         */
474        public Builder setAutoCancel(boolean autoCancel) {
475            setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel);
476            return this;
477        }
478
479        /**
480         * Set the default notification options that will be used.
481         * <p>
482         * The value should be one or more of the following fields combined with
483         * bitwise-or:
484         * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE},
485         * {@link Notification#DEFAULT_LIGHTS}.
486         * <p>
487         * For all default values, use {@link Notification#DEFAULT_ALL}.
488         */
489        public Builder setDefaults(int defaults) {
490            mNotification.defaults = defaults;
491            if ((defaults & Notification.DEFAULT_LIGHTS) != 0) {
492                mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
493            }
494            return this;
495        }
496
497        private void setFlag(int mask, boolean value) {
498            if (value) {
499                mNotification.flags |= mask;
500            } else {
501                mNotification.flags &= ~mask;
502            }
503        }
504
505        /**
506         * Set the relative priority for this notification.
507         *
508         * Priority is an indication of how much of the user's
509         * valuable attention should be consumed by this
510         * notification. Low-priority notifications may be hidden from
511         * the user in certain situations, while the user might be
512         * interrupted for a higher-priority notification. The system
513         * will make a determination about how to interpret
514         * notification priority as described in MUMBLE MUMBLE.
515         */
516        public Builder setPriority(int pri) {
517            mPriority = pri;
518            return this;
519        }
520
521        /**
522         * Add an action to this notification. Actions are typically displayed by
523         * the system as a button adjacent to the notification content.
524         *
525         * @param icon Resource ID of a drawable that represents the action.
526         * @param title Text describing the action.
527         * @param intent PendingIntent to be fired when the action is invoked.
528         */
529        public Builder addAction(int icon, CharSequence title, PendingIntent intent) {
530            mActions.add(new Action(icon, title, intent));
531            return this;
532        }
533
534        /**
535         * Add a rich notification style to be applied at build time.
536         *
537         * @param style Object responsible for modifying the notification style.
538         */
539        public Builder setStyle(Style style) {
540            if (mStyle != style) {
541                mStyle = style;
542                if (mStyle != null) {
543                    mStyle.setBuilder(this);
544                }
545            }
546            return this;
547        }
548
549        /**
550         * @deprecated Use {@link #build()} instead.
551         */
552        @Deprecated
553        public Notification getNotification() {
554            return (Notification) IMPL.build(this);
555        }
556
557        /**
558         * Combine all of the options that have been set and return a new {@link Notification}
559         * object.
560         */
561        public Notification build() {
562            return (Notification) IMPL.build(this);
563        }
564    }
565
566    /**
567     * An object that can apply a rich notification style to a {@link Notification.Builder}
568     * object.
569     */
570    public static abstract class Style
571    {
572        Builder mBuilder;
573        CharSequence mBigContentTitle;
574        CharSequence mSummaryText;
575        boolean mSummaryTextSet = false;
576
577        public void setBuilder(Builder builder) {
578            if (mBuilder != builder) {
579                mBuilder = builder;
580                if (mBuilder != null) {
581                    mBuilder.setStyle(this);
582                }
583            }
584        }
585
586        public Notification build() {
587            Notification notification = null;
588            if (mBuilder != null) {
589                notification = mBuilder.build();
590            }
591            return notification;
592        }
593    }
594
595    /**
596     * Helper class for generating large-format notifications that include a large image attachment.
597     *
598     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
599     * <pre class="prettyprint">
600     * Notification noti = new Notification.Builder()
601     *     .setContentTitle(&quot;New photo from &quot; + sender.toString())
602     *     .setContentText(subject)
603     *     .setSmallIcon(R.drawable.new_post)
604     *     .setLargeIcon(aBitmap)
605     *     .setStyle(new Notification.BigPictureStyle()
606     *         .bigPicture(aBigBitmap))
607     *     .build();
608     * </pre>
609     *
610     * @see Notification#bigContentView
611     */
612    public static class BigPictureStyle extends Style {
613        Bitmap mPicture;
614
615        public BigPictureStyle() {
616        }
617
618        public BigPictureStyle(Builder builder) {
619            setBuilder(builder);
620        }
621
622        /**
623         * Overrides ContentTitle in the big form of the template.
624         * This defaults to the value passed to setContentTitle().
625         */
626        public BigPictureStyle setBigContentTitle(CharSequence title) {
627            mBigContentTitle = title;
628            return this;
629        }
630
631        /**
632         * Set the first line of text after the detail section in the big form of the template.
633         */
634        public BigPictureStyle setSummaryText(CharSequence cs) {
635            mSummaryText = cs;
636            mSummaryTextSet = true;
637            return this;
638        }
639
640        /**
641         * Provide the bitmap to be used as the payload for the BigPicture notification.
642         */
643        public BigPictureStyle bigPicture(Bitmap b) {
644            mPicture = b;
645            return this;
646        }
647    }
648
649    /**
650     * Helper class for generating large-format notifications that include a lot of text.
651     *
652     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
653     * <pre class="prettyprint">
654     * Notification noti = new Notification.Builder()
655     *     .setContentTitle(&quot;New mail from &quot; + sender.toString())
656     *     .setContentText(subject)
657     *     .setSmallIcon(R.drawable.new_mail)
658     *     .setLargeIcon(aBitmap)
659     *     .setStyle(new Notification.BigTextStyle()
660     *         .bigText(aVeryLongString))
661     *     .build();
662     * </pre>
663     *
664     * @see Notification#bigContentView
665     */
666    public static class BigTextStyle extends Style {
667        CharSequence mBigText;
668
669        public BigTextStyle() {
670        }
671
672        public BigTextStyle(Builder builder) {
673            setBuilder(builder);
674        }
675
676        /**
677         * Overrides ContentTitle in the big form of the template.
678         * This defaults to the value passed to setContentTitle().
679         */
680        public BigTextStyle setBigContentTitle(CharSequence title) {
681            mBigContentTitle = title;
682            return this;
683        }
684
685        /**
686         * Set the first line of text after the detail section in the big form of the template.
687         */
688        public BigTextStyle setSummaryText(CharSequence cs) {
689            mSummaryText = cs;
690            mSummaryTextSet = true;
691            return this;
692        }
693
694        /**
695         * Provide the longer text to be displayed in the big form of the
696         * template in place of the content text.
697         */
698        public BigTextStyle bigText(CharSequence cs) {
699            mBigText = cs;
700            return this;
701        }
702    }
703
704    /**
705     * Helper class for generating large-format notifications that include a list of (up to 5) strings.
706     *
707     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
708     * <pre class="prettyprint">
709     * Notification noti = new Notification.Builder()
710     *     .setContentTitle(&quot;5 New mails from &quot; + sender.toString())
711     *     .setContentText(subject)
712     *     .setSmallIcon(R.drawable.new_mail)
713     *     .setLargeIcon(aBitmap)
714     *     .setStyle(new Notification.InboxStyle()
715     *         .addLine(str1)
716     *         .addLine(str2)
717     *         .setContentTitle(&quot;&quot;)
718     *         .setSummaryText(&quot;+3 more&quot;))
719     *     .build();
720     * </pre>
721     *
722     * @see Notification#bigContentView
723     */
724    public static class InboxStyle extends Style {
725        ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
726
727        public InboxStyle() {
728        }
729
730        public InboxStyle(Builder builder) {
731            setBuilder(builder);
732        }
733
734        /**
735         * Overrides ContentTitle in the big form of the template.
736         * This defaults to the value passed to setContentTitle().
737         */
738        public InboxStyle setBigContentTitle(CharSequence title) {
739            mBigContentTitle = title;
740            return this;
741        }
742
743        /**
744         * Set the first line of text after the detail section in the big form of the template.
745         */
746        public InboxStyle setSummaryText(CharSequence cs) {
747            mSummaryText = cs;
748            mSummaryTextSet = true;
749            return this;
750        }
751
752        /**
753         * Append a line to the digest section of the Inbox notification.
754         */
755        public InboxStyle addLine(CharSequence cs) {
756            mTexts.add(cs);
757            return this;
758        }
759    }
760
761    public static class Action {
762        public int icon;
763        public CharSequence title;
764        public PendingIntent actionIntent;
765
766        public Action(int icon_, CharSequence title_, PendingIntent intent_) {
767            this.icon = icon_;
768            this.title = title_;
769            this.actionIntent = intent_;
770        }
771    }
772}
773