• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 com.googlecode.android_scripting;
18 
19 import android.app.Notification;
20 import android.app.NotificationManager;
21 import android.app.Service;
22 
23 import java.lang.reflect.Method;
24 
25 public abstract class ForegroundService extends Service {
26   private static final Class<?>[] mStartForegroundSignature =
27       new Class[] { int.class, Notification.class };
28   private static final Class<?>[] mStopForegroundSignature = new Class[] { boolean.class };
29 
30   private final int mNotificationId;
31 
32   private NotificationManager mNotificationManager;
33   private Method mStartForeground;
34   private Method mStopForeground;
35   private Object[] mStartForegroundArgs = new Object[2];
36   private Object[] mStopForegroundArgs = new Object[1];
37 
ForegroundService(int id)38   public ForegroundService(int id) {
39     mNotificationId = id;
40   }
41 
createNotification()42   protected abstract Notification createNotification();
43 
44   /**
45    * @return The NotificationManager for this Context.
46    */
getNotificationManager()47   protected NotificationManager getNotificationManager() {
48     if (mNotificationManager == null) {
49       mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
50     }
51     return mNotificationManager;
52   }
53 
54   /**
55    * This is a wrapper around the new startForeground method, using the older APIs if it is not
56    * available.
57    */
startForegroundCompat(Notification notification)58   private void startForegroundCompat(Notification notification) {
59     // If we have the new startForeground API, then use it.
60     if (mStartForeground != null) {
61       mStartForegroundArgs[0] = Integer.valueOf(mNotificationId);
62       mStartForegroundArgs[1] = notification;
63       try {
64         mStartForeground.invoke(this, mStartForegroundArgs);
65       } catch (Exception e) {
66         Log.e(e);
67       }
68       return;
69     }
70 
71     // Fall back on the old API.
72     setForeground(true);
73     if (notification != null) {
74       getNotificationManager().notify(mNotificationId, notification);
75     }
76   }
77 
78   /**
79    * This is a wrapper around the new stopForeground method, using the older APIs if it is not
80    * available.
81    */
stopForegroundCompat()82   private void stopForegroundCompat() {
83     // If we have the new stopForeground API, then use it.
84     if (mStopForeground != null) {
85       mStopForegroundArgs[0] = Boolean.TRUE;
86       try {
87         mStopForeground.invoke(this, mStopForegroundArgs);
88       } catch (Exception e) {
89         Log.e(e);
90       }
91       return;
92     }
93 
94     // Fall back on the old API. Note to cancel BEFORE changing the
95     // foreground state, since we could be killed at that point.
96     getNotificationManager().cancel(mNotificationId);
97     setForeground(false);
98   }
99 
100   @Override
onCreate()101   public void onCreate() {
102     try {
103       mStartForeground = getClass().getMethod("startForeground", mStartForegroundSignature);
104       mStopForeground = getClass().getMethod("stopForeground", mStopForegroundSignature);
105     } catch (NoSuchMethodException e) {
106       // Running on an older platform.
107       mStartForeground = mStopForeground = null;
108     }
109     startForegroundCompat(createNotification());
110   }
111 
112   @Override
onDestroy()113   public void onDestroy() {
114     // Make sure our notification is gone.
115     stopForegroundCompat();
116   }
117 }
118