• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.system.helpers;
18 
19 import android.app.IntentService;
20 import android.app.Notification;
21 import android.app.NotificationChannel;
22 import android.app.NotificationManager;
23 import android.app.PendingIntent;
24 import android.app.RemoteInput;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.os.Handler;
28 import android.service.notification.StatusBarNotification;
29 import android.support.test.InstrumentationRegistry;
30 import android.support.test.uiautomator.UiDevice;
31 import android.util.Log;
32 import android.widget.Toast;
33 
34 import java.util.List;
35 
36 /**
37  * Implement common helper methods for Notification.
38  */
39 public class NotificationHelper {
40     private static final String LOG_TAG = NotificationHelper.class.getSimpleName();
41     public static final int SHORT_TIMEOUT = 200;
42     public static final int LONG_TIMEOUT = 2000;
43     private static NotificationHelper sInstance = null;
44     private Context mContext = null;
45     private UiDevice mDevice = null;
46     private String mCurrentChannelId = NotificationChannel.DEFAULT_CHANNEL_ID;
47 
NotificationHelper()48     public NotificationHelper() {
49         mContext = InstrumentationRegistry.getTargetContext();
50         mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
51     }
52 
getInstance()53     public static NotificationHelper getInstance() {
54         if (sInstance == null) {
55             sInstance = new NotificationHelper();
56         }
57         return sInstance;
58     }
59 
60     /**
61      * Creates a notification channel if none exists.
62      * @param id channel id, must be unique
63      * @param name channel name
64      * @param importance channel importance
65      * @param vibrate vibrate on notification
66      * @param manager the {@link NotificationManager}
67      * @throws IllegalArgumentException if the channel id is already in use.
68      */
createChannel(String id, String name, int importance, boolean vibrate, NotificationManager manager)69     public void createChannel(String id, String name, int importance, boolean vibrate,
70             NotificationManager manager) {
71         if (manager.getNotificationChannel(id) != null) {
72             throw new IllegalArgumentException("Channel already exists.");
73         }
74         NotificationChannel channel = new NotificationChannel(id, name, importance);
75         channel.enableVibration(vibrate);
76         channel.setSound(null, null);
77         manager.createNotificationChannel(channel);
78     }
79 
80     /**
81      * Uses this notification channel when using this helper.
82      * @param id the channel id to use
83      */
useChannel(String id)84     public void useChannel(String id) {
85         mCurrentChannelId = id;
86     }
87 
88     /**
89      * Check if a list of notifications exist.
90      * @param ids list of notification ids
91      * @param manager the {@link NotificationManager}
92      * @return true if all notifications exist, false otherwise
93      * @throws InterruptedException if the running thread is interrupted.
94      */
checkNotificationExistence(List<Integer> ids, NotificationManager manager)95     public boolean checkNotificationExistence(List<Integer> ids, NotificationManager manager)
96             throws InterruptedException {
97         boolean result = true;
98         for (int id : ids) {
99             result = result && checkNotificationExistence(id, manager);
100         }
101         return result;
102     }
103 
104     /**
105      * Check if a notification exists.
106      * @param id notification id
107      * @param manager the {@link NotificationManager}
108      * @return true if all notifications exist, false otherwise
109      * @throws InterruptedException if the running thread is interrupted.
110      */
checkNotificationExistence(int id, NotificationManager manager)111     public boolean checkNotificationExistence(int id, NotificationManager manager)
112             throws InterruptedException {
113         boolean isFound = false;
114         for (int tries = 3; tries-- > 0;) {
115             isFound = false;
116             StatusBarNotification[] sbns = manager.getActiveNotifications();
117             for (StatusBarNotification sbn : sbns) {
118                 if (sbn.getId() == id) {
119                     isFound = true;
120                     break;
121                 }
122             }
123             if (isFound) {
124                 break;
125             }
126             Thread.sleep(SHORT_TIMEOUT);
127         }
128         Log.i(LOG_TAG, String.format("Notification (id=%d) existence = %b", id, isFound));
129         return isFound;
130     }
131 
132     /**
133      * send out a group of notifications
134      * @param lists notification list for a group of notifications which includes two child
135      *            notifications and one summary notification
136      * @param groupKey the group key of group notification
137      * @param mNotificationManager NotificationManager
138      * @throws Exception
139      */
sendBundlingNotifications(List<Integer> lists, String groupKey, NotificationManager mNotificationManager)140     public void sendBundlingNotifications(List<Integer> lists, String groupKey,
141             NotificationManager mNotificationManager) throws Exception {
142         Notification childNotification = new Notification.Builder(mContext)
143                 .setChannelId(mCurrentChannelId)
144                 .setContentTitle(lists.get(1).toString())
145                 .setSmallIcon(android.R.drawable.stat_notify_chat)
146                 .setContentText("test1")
147                 .setWhen(System.currentTimeMillis())
148                 .setGroup(groupKey)
149                 .build();
150         mNotificationManager.notify(lists.get(1),
151                 childNotification);
152         childNotification = new Notification.Builder(mContext)
153                 .setChannelId(mCurrentChannelId)
154                 .setContentTitle(lists.get(2).toString())
155                 .setContentText("test2")
156                 .setSmallIcon(android.R.drawable.stat_notify_chat)
157                 .setWhen(System.currentTimeMillis())
158                 .setGroup(groupKey)
159                 .build();
160         mNotificationManager.notify(lists.get(2),
161                 childNotification);
162         Notification notification = new Notification.Builder(mContext)
163                 .setChannelId(mCurrentChannelId)
164                 .setContentTitle(lists.get(0).toString())
165                 .setSubText(groupKey)
166                 .setSmallIcon(android.R.drawable.stat_notify_chat)
167                 .setGroup(groupKey)
168                 .setGroupSummary(true)
169                 .build();
170         mNotificationManager.notify(lists.get(0),
171                 notification);
172     }
173 
174     /**
175      * send out a notification with inline reply
176      * @param notificationId An identifier for this notification
177      * @param title notification title
178      * @param inLineReply inline reply text
179      * @param mNotificationManager NotificationManager
180      */
sendNotificationsWithInLineReply( int notificationId, String title, String inLineReply, PendingIntent pendingIntent, NotificationManager mNotificationManager)181     public void sendNotificationsWithInLineReply(
182             int notificationId, String title, String inLineReply, PendingIntent pendingIntent,
183             NotificationManager mNotificationManager) {
184         Notification.Action action = new Notification.Action.Builder(
185                 android.R.drawable.stat_notify_chat, "Reply",
186                 pendingIntent).addRemoteInput(new RemoteInput.Builder(inLineReply)
187                         .setLabel("Quick reply").build())
188                         .build();
189         Notification.Builder n = new Notification.Builder(mContext)
190                 .setChannelId(mCurrentChannelId)
191                 .setContentTitle(Integer.toString(notificationId))
192                 .setContentText(title)
193                 .setWhen(System.currentTimeMillis())
194                 .setSmallIcon(android.R.drawable.stat_notify_chat)
195                 .addAction(action)
196                 .setDefaults(Notification.DEFAULT_VIBRATE);
197         mNotificationManager.notify(notificationId, n.build());
198     }
199 
200     /**
201      * dismiss notification
202      * @param mNotificationManager NotificationManager
203      */
dismissNotifications(NotificationManager mNotificationManager)204     public void dismissNotifications(NotificationManager mNotificationManager){
205         mNotificationManager.cancelAll();
206     }
207 
208     /**
209      * open notification shade
210      */
openNotification()211     public void openNotification(){
212         mDevice.openNotification();
213     }
214 
215     /**
216      * An {@link IntentService} for creating pending intents that can be used with to send
217      * notifications with inline reply text content.
218      */
219     public static class ToastService extends IntentService {
220         private Handler mHandler;
221 
ToastService()222         public ToastService() {
223             super("Toast Service");
224         }
225 
226         @Override
onStartCommand(Intent intent, int flags, int startId)227         public int onStartCommand(Intent intent, int flags, int startId) {
228             return super.onStartCommand(intent, flags, startId);
229         }
230 
231         @Override
onHandleIntent(Intent intent)232         protected void onHandleIntent(Intent intent) {
233             if (mHandler == null) {
234                 mHandler = new Handler();
235             }
236             if (intent.hasExtra("text")) {
237                 mHandler.post(new Runnable() {
238                     @Override
239                     public void run() {
240                         Toast.makeText(
241                                 ToastService.this, intent.getStringExtra("text"), Toast.LENGTH_LONG)
242                             .show();
243                     }
244                 });
245             }
246         }
247 
248         /**
249          * Returns a {@link PendingIntent} for a Toast message.
250          */
getPendingIntent(Context context, String text)251         public static PendingIntent getPendingIntent(Context context, String text) {
252             Intent toastIntent = new Intent(context, ToastService.class);
253             toastIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
254             toastIntent.setAction("toast:" + text);
255             toastIntent.putExtra("text", text);
256             PendingIntent pi = PendingIntent.getService(
257                     context, 58, toastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
258             return pi;
259         }
260     }
261 }
262