blob: bfea9cadef89205345711fe76f0f9ea400ca0dad [file] [log] [blame]
Daniel Sandler5feceeb2013-03-22 18:29:23 -07001/*
2 * Copyright (C) 2013 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.service.notification;
18
19import android.annotation.SdkConstant;
20import android.app.INotificationManager;
21import android.app.Service;
22import android.content.Context;
23import android.content.Intent;
24import android.os.IBinder;
25import android.os.ServiceManager;
26import android.util.Log;
27
Scott Main04667da2013-04-25 16:57:16 -070028/**
29 * A service that receives calls from the system when new notifications are posted or removed.
30 * <p>To extend this class, you must declare the service in your manifest file with
31 * the {@link android.Manifest.permission#BIND_NOTIFICATION_LISTENER_SERVICE} permission
32 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
33 * <pre>
34 * &lt;service android:name=".NotificationListener"
35 * android:label="&#64;string/service_name"
36 * android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
37 * &lt;intent-filter>
38 * &lt;action android:name="android.service.notification.NotificationListenerService" />
39 * &lt;/intent-filter>
40 * &lt;/service></pre>
41 */
Daniel Sandler5feceeb2013-03-22 18:29:23 -070042public abstract class NotificationListenerService extends Service {
43 // TAG = "NotificationListenerService[MySubclass]"
44 private final String TAG = NotificationListenerService.class.getSimpleName()
45 + "[" + getClass().getSimpleName() + "]";
46
47 private INotificationListenerWrapper mWrapper = null;
48
49 private INotificationManager mNoMan;
50
51 /**
52 * The {@link Intent} that must be declared as handled by the service.
53 */
54 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
55 public static final String SERVICE_INTERFACE
56 = "android.service.notification.NotificationListenerService";
57
58 /**
59 * Implement this method to learn about new notifications as they are posted by apps.
60 *
61 * @param sbn A data structure encapsulating the original {@link android.app.Notification}
62 * object as well as its identifying information (tag and id) and source
63 * (package name).
64 */
65 public abstract void onNotificationPosted(StatusBarNotification sbn);
66
67 /**
68 * Implement this method to learn when notifications are removed.
69 * <P>
70 * This might occur because the user has dismissed the notification using system UI (or another
71 * notification listener) or because the app has withdrawn the notification.
Daniel Sandler1a497d32013-04-18 14:52:45 -040072 * <P>
73 * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
Scott Main04667da2013-04-25 16:57:16 -070074 * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
Daniel Sandler1a497d32013-04-18 14:52:45 -040075 * fields such as {@link android.app.Notification#contentView} and
76 * {@link android.app.Notification#largeIcon}. However, all other fields on
77 * {@link StatusBarNotification}, sufficient to match this call with a prior call to
78 * {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
Daniel Sandler5feceeb2013-03-22 18:29:23 -070079 *
Daniel Sandler1a497d32013-04-18 14:52:45 -040080 * @param sbn A data structure encapsulating at least the original information (tag and id)
81 * and source (package name) used to post the {@link android.app.Notification} that
82 * was just removed.
Daniel Sandler5feceeb2013-03-22 18:29:23 -070083 */
84 public abstract void onNotificationRemoved(StatusBarNotification sbn);
85
86 private final INotificationManager getNotificationInterface() {
87 if (mNoMan == null) {
88 mNoMan = INotificationManager.Stub.asInterface(
89 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
90 }
91 return mNoMan;
92 }
93
94 /**
95 * Inform the notification manager about dismissal of a single notification.
96 * <p>
97 * Use this if your listener has a user interface that allows the user to dismiss individual
98 * notifications, similar to the behavior of Android's status bar and notification panel.
99 * It should be called after the user dismisses a single notification using your UI;
100 * upon being informed, the notification manager will actually remove the notification
101 * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
102 * <P>
103 * <b>Note:</b> If your listener allows the user to fire a notification's
104 * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
105 * this method at that time <i>if</i> the Notification in question has the
106 * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
107 *
108 * @param pkg Package of the notifying app.
109 * @param tag Tag of the notification as specified by the notifying app in
110 * {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
111 * @param id ID of the notification as specified by the notifying app in
112 * {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
113 */
Daniel Sandlere6f7f2e2013-04-25 15:44:16 -0400114 public final void cancelNotification(String pkg, String tag, int id) {
Daniel Sandler5feceeb2013-03-22 18:29:23 -0700115 try {
Daniel Sandlere6f7f2e2013-04-25 15:44:16 -0400116 getNotificationInterface().cancelNotificationFromListener(mWrapper, pkg, tag, id);
Daniel Sandler5feceeb2013-03-22 18:29:23 -0700117 } catch (android.os.RemoteException ex) {
118 Log.v(TAG, "Unable to contact notification manager", ex);
119 }
120 }
121
122 /**
123 * Inform the notification manager about dismissal of all notifications.
124 * <p>
125 * Use this if your listener has a user interface that allows the user to dismiss all
126 * notifications, similar to the behavior of Android's status bar and notification panel.
127 * It should be called after the user invokes the "dismiss all" function of your UI;
128 * upon being informed, the notification manager will actually remove all active notifications
129 * and you will get multiple {@link #onNotificationRemoved(StatusBarNotification)} callbacks.
130 *
Daniel Sandlere6f7f2e2013-04-25 15:44:16 -0400131 * {@see #cancelNotification(String, String, int)}
Daniel Sandler5feceeb2013-03-22 18:29:23 -0700132 */
Daniel Sandlere6f7f2e2013-04-25 15:44:16 -0400133 public final void cancelAllNotifications() {
Daniel Sandler5feceeb2013-03-22 18:29:23 -0700134 try {
Daniel Sandlere6f7f2e2013-04-25 15:44:16 -0400135 getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
Daniel Sandler5feceeb2013-03-22 18:29:23 -0700136 } catch (android.os.RemoteException ex) {
137 Log.v(TAG, "Unable to contact notification manager", ex);
138 }
139 }
140
Daniel Sandler25cf8ce2013-04-24 15:34:57 -0400141 /**
142 * Request the list of outstanding notifications (that is, those that are visible to the
143 * current user). Useful when starting up and you don't know what's already been posted.
144 *
145 * @return An array of active notifications.
146 */
147 public StatusBarNotification[] getActiveNotifications() {
148 try {
149 return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
150 } catch (android.os.RemoteException ex) {
151 Log.v(TAG, "Unable to contact notification manager", ex);
152 }
153 return null;
154 }
155
Daniel Sandler5feceeb2013-03-22 18:29:23 -0700156 @Override
157 public IBinder onBind(Intent intent) {
158 if (mWrapper == null) {
159 mWrapper = new INotificationListenerWrapper();
160 }
161 return mWrapper;
162 }
163
164 private class INotificationListenerWrapper extends INotificationListener.Stub {
165 @Override
166 public void onNotificationPosted(StatusBarNotification sbn) {
167 NotificationListenerService.this.onNotificationPosted(sbn);
168 }
169 @Override
170 public void onNotificationRemoved(StatusBarNotification sbn) {
171 NotificationListenerService.this.onNotificationRemoved(sbn);
172 }
173 }
174}