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