1/*
2 * Copyright (C) 2007 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.app;
18
19import android.content.Context;
20import android.os.Handler;
21import android.os.IBinder;
22import android.os.RemoteException;
23import android.os.ServiceManager;
24import android.os.StrictMode;
25import android.os.UserHandle;
26import android.util.Log;
27
28/**
29 * Class to notify the user of events that happen.  This is how you tell
30 * the user that something has happened in the background. {@more}
31 *
32 * Notifications can take different forms:
33 * <ul>
34 *      <li>A persistent icon that goes in the status bar and is accessible
35 *          through the launcher, (when the user selects it, a designated Intent
36 *          can be launched),</li>
37 *      <li>Turning on or flashing LEDs on the device, or</li>
38 *      <li>Alerting the user by flashing the backlight, playing a sound,
39 *          or vibrating.</li>
40 * </ul>
41 *
42 * <p>
43 * Each of the notify methods takes an int id parameter and optionally a
44 * {@link String} tag parameter, which may be {@code null}.  These parameters
45 * are used to form a pair (tag, id), or ({@code null}, id) if tag is
46 * unspecified.  This pair identifies this notification from your app to the
47 * system, so that pair should be unique within your app.  If you call one
48 * of the notify methods with a (tag, id) pair that is currently active and
49 * a new set of notification parameters, it will be updated.  For example,
50 * if you pass a new status bar icon, the old icon in the status bar will
51 * be replaced with the new one.  This is also the same tag and id you pass
52 * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
53 * this notification.
54 *
55 * <p>
56 * You do not instantiate this class directly; instead, retrieve it through
57 * {@link android.content.Context#getSystemService}.
58 *
59 * <div class="special reference">
60 * <h3>Developer Guides</h3>
61 * <p>For a guide to creating notifications, read the
62 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
63 * developer guide.</p>
64 * </div>
65 *
66 * @see android.app.Notification
67 * @see android.content.Context#getSystemService
68 */
69public class NotificationManager
70{
71    private static String TAG = "NotificationManager";
72    private static boolean localLOGV = false;
73
74    private static INotificationManager sService;
75
76    /** @hide */
77    static public INotificationManager getService()
78    {
79        if (sService != null) {
80            return sService;
81        }
82        IBinder b = ServiceManager.getService("notification");
83        sService = INotificationManager.Stub.asInterface(b);
84        return sService;
85    }
86
87    /*package*/ NotificationManager(Context context, Handler handler)
88    {
89        mContext = context;
90    }
91
92    /** {@hide} */
93    public static NotificationManager from(Context context) {
94        return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
95    }
96
97    /**
98     * Post a notification to be shown in the status bar. If a notification with
99     * the same id has already been posted by your application and has not yet been canceled, it
100     * will be replaced by the updated information.
101     *
102     * @param id An identifier for this notification unique within your
103     *        application.
104     * @param notification A {@link Notification} object describing what to show the user. Must not
105     *        be null.
106     */
107    public void notify(int id, Notification notification)
108    {
109        notify(null, id, notification);
110    }
111
112    /**
113     * Post a notification to be shown in the status bar. If a notification with
114     * the same tag and id has already been posted by your application and has not yet been
115     * canceled, it will be replaced by the updated information.
116     *
117     * @param tag A string identifier for this notification.  May be {@code null}.
118     * @param id An identifier for this notification.  The pair (tag, id) must be unique
119     *        within your application.
120     * @param notification A {@link Notification} object describing what to
121     *        show the user. Must not be null.
122     */
123    public void notify(String tag, int id, Notification notification)
124    {
125        int[] idOut = new int[1];
126        INotificationManager service = getService();
127        String pkg = mContext.getPackageName();
128        if (notification.sound != null) {
129            notification.sound = notification.sound.getCanonicalUri();
130            if (StrictMode.vmFileUriExposureEnabled()) {
131                notification.sound.checkFileUriExposed("Notification.sound");
132            }
133        }
134        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
135        try {
136            service.enqueueNotificationWithTag(pkg, mContext.getBasePackageName(), tag, id,
137                    notification, idOut, UserHandle.myUserId());
138            if (id != idOut[0]) {
139                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
140            }
141        } catch (RemoteException e) {
142        }
143    }
144
145    /**
146     * @hide
147     */
148    public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
149    {
150        int[] idOut = new int[1];
151        INotificationManager service = getService();
152        String pkg = mContext.getPackageName();
153        if (notification.sound != null) {
154            notification.sound = notification.sound.getCanonicalUri();
155            if (StrictMode.vmFileUriExposureEnabled()) {
156                notification.sound.checkFileUriExposed("Notification.sound");
157            }
158        }
159        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
160        try {
161            service.enqueueNotificationWithTag(pkg, mContext.getBasePackageName(), tag, id,
162                    notification, idOut, user.getIdentifier());
163            if (id != idOut[0]) {
164                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
165            }
166        } catch (RemoteException e) {
167        }
168    }
169
170    /**
171     * Cancel a previously shown notification.  If it's transient, the view
172     * will be hidden.  If it's persistent, it will be removed from the status
173     * bar.
174     */
175    public void cancel(int id)
176    {
177        cancel(null, id);
178    }
179
180    /**
181     * Cancel a previously shown notification.  If it's transient, the view
182     * will be hidden.  If it's persistent, it will be removed from the status
183     * bar.
184     */
185    public void cancel(String tag, int id)
186    {
187        INotificationManager service = getService();
188        String pkg = mContext.getPackageName();
189        if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
190        try {
191            service.cancelNotificationWithTag(pkg, tag, id, UserHandle.myUserId());
192        } catch (RemoteException e) {
193        }
194    }
195
196    /**
197     * @hide
198     */
199    public void cancelAsUser(String tag, int id, UserHandle user)
200    {
201        INotificationManager service = getService();
202        String pkg = mContext.getPackageName();
203        if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
204        try {
205            service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
206        } catch (RemoteException e) {
207        }
208    }
209
210    /**
211     * Cancel all previously shown notifications. See {@link #cancel} for the
212     * detailed behavior.
213     */
214    public void cancelAll()
215    {
216        INotificationManager service = getService();
217        String pkg = mContext.getPackageName();
218        if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
219        try {
220            service.cancelAllNotifications(pkg, UserHandle.myUserId());
221        } catch (RemoteException e) {
222        }
223    }
224
225    private Context mContext;
226}
227