NotificationCompat.java revision 884c97b0015a71381bc2a534438b2a0e7e7abd6a
1262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten/*
2262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten * Copyright (C) 2012 The Android Open Source Project
3262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten *
4262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten * you may not use this file except in compliance with the License.
65cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten * You may obtain a copy of the License at
7262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten *
8262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten *
10262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten * Unless required by applicable law or agreed to in writing, software
115321b3665e1a538cdcf894dea99d15c10b18ccf8Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten * See the License for the specific language governing permissions and
14262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten * limitations under the License.
15262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten */
16262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
17262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenpackage android.support.v4.app;
18262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
19262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenimport android.app.Notification;
20262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenimport android.app.NotificationManager;
217b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kastenimport android.app.PendingIntent;
225321b3665e1a538cdcf894dea99d15c10b18ccf8Glenn Kastenimport android.content.Context;
237b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kastenimport android.graphics.Bitmap;
24262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenimport android.media.AudioManager;
25262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenimport android.net.Uri;
26262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenimport android.os.Build;
27e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kastenimport android.widget.RemoteViews;
285cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kastenimport java.util.ArrayList;
29262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
30262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten/**
315cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten * Helper for accessing features in {@link android.app.Notification}
327b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten * introduced after API level 4 in a backwards compatible fashion.
337b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten */
34262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kastenpublic class NotificationCompat {
35262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    /**
36262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * Obsolete flag indicating high-priority notifications; use the priority field instead.
37262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     *
38262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * @deprecated Use {@link NotificationCompat.Builder#setPriority(int)} with a positive value.
39262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     */
40262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    public static final int FLAG_HIGH_PRIORITY = 0x00000080;
415cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten
425cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    /**
435cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * Default notification priority for {@link NotificationCompat.Builder#setPriority(int)}.
445cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * If your application does not prioritize its own notifications,
455cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * use this value for all notifications.
465cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     */
475cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    public static final int PRIORITY_DEFAULT = 0;
485cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten
495cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    /**
505cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * Lower notification priority for {@link NotificationCompat.Builder#setPriority(int)},
515cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * for items that are less important. The UI may choose to show
525cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * these items smaller, or at a different position in the list,
535cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * compared with your app's {@link #PRIORITY_DEFAULT} items.
545cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     */
555cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    public static final int PRIORITY_LOW = -1;
56262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
575cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    /**
585cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * Lowest notification priority for {@link NotificationCompat.Builder#setPriority(int)};
595cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     * these items might not be shown to the user except under
60e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kasten     * special circumstances, such as detailed notification logs.
615cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten     */
625cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    public static final int PRIORITY_MIN = -2;
635cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten
645cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    /**
654076e5009bfe70bc06a78f5aafec77af6c03201dGlenn Kasten     * Higher notification priority for {@link NotificationCompat.Builder#setPriority(int)},
66262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * for more important notifications or alerts. The UI may choose
67262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * to show these items larger, or at a different position in
68527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten     * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items.
69262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     */
70262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    public static final int PRIORITY_HIGH = 1;
71262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
725cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten    /**
73262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * Highest notification priority for {@link NotificationCompat.Builder#setPriority(int)},
74262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * for your application's most important items that require the user's
75262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * prompt attention or input.
76262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     */
777b726bdcd996f1cab3a584c04ce1afc07bc8fbe7Glenn Kasten    public static final int PRIORITY_MAX = 2;
78262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
79262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    private static final NotificationCompatImpl IMPL;
80262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
81527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten    interface NotificationCompatImpl {
82262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        public Notification build(Builder b);
83262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    }
84b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi
85b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    static class NotificationCompatImplBase implements NotificationCompatImpl {
86b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi        public Notification build(Builder b) {
87b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi            Notification result = (Notification) b.mNotification;
886e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi            result.setLatestEventInfo(b.mContext, b.mContentTitle,
89bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi                    b.mContentText, b.mContentIntent);
906e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi            // translate high priority requests into legacy flag
91bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            if (b.mPriority > PRIORITY_DEFAULT) {
9213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                result.flags |= FLAG_HIGH_PRIORITY;
9313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi            }
9468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi            return result;
9513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        }
96262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    }
97262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
98262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    static class NotificationCompatImplHoneycomb implements NotificationCompatImpl {
99bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        public Notification build(Builder b) {
100262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            return NotificationCompatHoneycomb.add(b.mContext, b.mNotification,
101262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
102262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon);
103262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        }
104262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    }
105262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
106262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    static class NotificationCompatImplIceCreamSandwich implements NotificationCompatImpl {
107262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        public Notification build(Builder b) {
108262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            return NotificationCompatIceCreamSandwich.add(b.mContext, b.mNotification,
109262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
110262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
111262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate);
112262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        }
113262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    }
114262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
115262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    static class NotificationCompatImplJellybean implements NotificationCompatImpl {
116262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        public Notification build(Builder b) {
117262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            NotificationCompatJellybean jbBuilder = new NotificationCompatJellybean(
118262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo,
119262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
1207f5cc1afe49395fefaad9b2bbd728a45d1bfda6aJean-Michel Trivi                    b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
121262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    b.mUseChronometer, b.mPriority, b.mSubText);
122262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            for (Action action: b.mActions) {
123262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                jbBuilder.addAction(action.icon, action.title, action.actionIntent);
124262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            }
125262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            if (b.mStyle != null) {
126262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                if (b.mStyle instanceof BigTextStyle) {
127262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    BigTextStyle style = (BigTextStyle) b.mStyle;
128262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    jbBuilder.addBigTextStyle(style.mBigContentTitle,
129262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mSummaryTextSet,
1302eac6c23b7bd8985e5bc842b9dec9fa3980dd100Glenn Kasten                            style.mSummaryText,
1316e7e174807fc639c49125ced8962aa369370fbf0Jean-Michel Trivi                            style.mBigText);
132262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                } else if (b.mStyle instanceof InboxStyle) {
133262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    InboxStyle style = (InboxStyle) b.mStyle;
134262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    jbBuilder.addInboxStyle(style.mBigContentTitle,
135262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mSummaryTextSet,
136262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mSummaryText,
137262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mTexts);
138262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                } else if (b.mStyle instanceof BigPictureStyle) {
139262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    BigPictureStyle style = (BigPictureStyle) b.mStyle;
140262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                    jbBuilder.addBigPictureStyle(style.mBigContentTitle,
141262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mSummaryTextSet,
142262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mSummaryText,
143262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                            style.mPicture);
144262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten                }
145262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            }
146262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            return(jbBuilder.build());
147262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        }
148262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    }
149262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
150262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    static {
151262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        if (Build.VERSION.SDK_INT >= 16) {
152262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            IMPL = new NotificationCompatImplJellybean();
153262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        } else if (Build.VERSION.SDK_INT >= 14) {
154262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            IMPL = new NotificationCompatImplIceCreamSandwich();
155262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        } else if (Build.VERSION.SDK_INT >= 11) {
156262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            IMPL = new NotificationCompatImplHoneycomb();
157262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        } else {
158262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten            IMPL = new NotificationCompatImplBase();
159262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        }
160262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    }
161262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten
1625321b3665e1a538cdcf894dea99d15c10b18ccf8Glenn Kasten    /**
163e7b0c260194d155513f5e07105841597f7bb9ab8-b master-pdk-dev     * Builder class for {@link NotificationCompat} objects.  Allows easier control over
164e7b0c260194d155513f5e07105841597f7bb9ab8-b master-pdk-dev     * all the flags, as well as help constructing the typical notification layouts.
165cde9b8b8bd0c84c62de49e73c08d224274280bfaJames Dong     * <p>
1665321b3665e1a538cdcf894dea99d15c10b18ccf8Glenn Kasten     * On platform versions that don't offer expanded notifications, methods that depend on
167262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * expanded notifications have no effect.
1684ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten     * </p>
1694ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten     * <p>
1704ce38604afa7e4f629d568f400b0634504e60a2eGlenn Kasten     * For example, action buttons won't appear on platforms prior to Android 4.1. Action
171262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * buttons depend on expanded notifications, which are only available in Android 4.1
172262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * and later.
173262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * <p>
174262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * For this reason, you should always ensure that UI controls in a notification are also
175262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * available in an {@link android.app.Activity} in your app, and you should always start that
176262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * {@link android.app.Activity} when users click the notification. To do this, use the
177262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * {@link NotificationCompat.Builder#setContentIntent setContentIntent()}
178262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * method.
179262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     * </p>
18027ff9b2ebcb70cf1b615a1040fb2ddd854f13cbfGlenn Kasten     *
181262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten     */
182262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten    public static class Builder {
183262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        Context mContext;
18439310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten
185ffea36e11b068d171549b64ee767eefd2637555aJeff Brown        CharSequence mContentTitle;
186ffea36e11b068d171549b64ee767eefd2637555aJeff Brown        CharSequence mContentText;
187262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        PendingIntent mContentIntent;
188f62485fd570f004d0e336e4c2624a935a4a284ccIliyan Malchev        PendingIntent mFullScreenIntent;
189262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        RemoteViews mTickerView;
190527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        Bitmap mLargeIcon;
191527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        CharSequence mContentInfo;
192262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        int mNumber;
193262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        int mPriority;
194262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        boolean mUseChronometer;
195262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        Style mStyle;
196262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        CharSequence mSubText;
197527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        int mProgressMax;
198262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        int mProgress;
199262059f71a68edc5e510427c63f5f1623d3672a8Glenn Kasten        boolean mProgressIndeterminate;
200527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        ArrayList<Action> mActions = new ArrayList<Action>();
2015cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten
202527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        Notification mNotification = new Notification();
2035321b3665e1a538cdcf894dea99d15c10b18ccf8Glenn Kasten
204e7b0c260194d155513f5e07105841597f7bb9ab8-b master-pdk-dev        /**
205e7b0c260194d155513f5e07105841597f7bb9ab8-b master-pdk-dev         * Constructor.
206cde9b8b8bd0c84c62de49e73c08d224274280bfaJames Dong         *
207527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten         * Automatically sets the when field to {@link System#currentTimeMillis()
208527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten         * System.currentTimeMillis()} and the audio stream to the
209527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten         * {@link Notification#STREAM_DEFAULT}.
2105cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten         *
2110e3b9fb27c3597dd4b32f2894f5d182ea4b86234Glenn Kasten         * @param context A {@link Context} that will be used to construct the
21284ed0307dcc468a925c8e779e804367345177ff3Andrew Hsieh         *      RemoteViews. The Context will not be held past the lifetime of this
213527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten         *      Builder object.
214527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten         */
215527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        public Builder(Context context) {
2165cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten            mContext = context;
217527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten
2185321b3665e1a538cdcf894dea99d15c10b18ccf8Glenn Kasten            // Set defaults to match the defaults of a Notification
219e7b0c260194d155513f5e07105841597f7bb9ab8-b master-pdk-dev            mNotification.when = System.currentTimeMillis();
220e7b0c260194d155513f5e07105841597f7bb9ab8-b master-pdk-dev            mNotification.audioStreamType = Notification.STREAM_DEFAULT;
221cde9b8b8bd0c84c62de49e73c08d224274280bfaJames Dong            mPriority = PRIORITY_DEFAULT;
222527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        }
223527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten
224527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        /**
2255cd605f62b687b22ff44a9de096b5f297eed74afGlenn Kasten         * Set the time that the event occurred.  Notifications in the panel are
2260e3b9fb27c3597dd4b32f2894f5d182ea4b86234Glenn Kasten         * sorted by this time.
22784ed0307dcc468a925c8e779e804367345177ff3Andrew Hsieh         */
228527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn Kasten        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