1 /*
2  * Copyright (C) 2009 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.example.android.apis.app;
18 
19 import android.app.Activity;
20 import android.app.AlarmManager;
21 import android.app.Notification;
22 import android.app.NotificationManager;
23 import android.app.PendingIntent;
24 import android.app.Service;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.IBinder;
30 import android.os.PowerManager;
31 import android.os.SystemClock;
32 import android.util.Log;
33 import android.view.View;
34 import android.view.View.OnClickListener;
35 import android.widget.Button;
36 
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
39 
40 
41 
42 
43 // Need the following import to get access to the app resources, since this
44 // class is in a sub-package.
45 import com.example.android.apis.R;
46 
47 /**
48  * This is an example of implementing an application service that can
49  * run in the "foreground".  It shows how to code this to work well by using
50  * the improved Android 2.0 APIs when available and otherwise falling back
51  * to the original APIs.  Yes: you can take this exact code, compile it
52  * against the Android 2.0 SDK, and it will run against everything down to
53  * Android 1.0.
54  */
55 public class ForegroundService extends Service {
56     static final String ACTION_FOREGROUND = "com.example.android.apis.FOREGROUND";
57     static final String ACTION_FOREGROUND_WAKELOCK = "com.example.android.apis.FOREGROUND_WAKELOCK";
58     static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND";
59     static final String ACTION_BACKGROUND_WAKELOCK = "com.example.android.apis.BACKGROUND_WAKELOCK";
60 
61     private NotificationManager mNM;
62 
63     private PowerManager.WakeLock mWakeLock;
64     private Handler mHandler = new Handler();
65     private Runnable mPulser = new Runnable() {
66         @Override public void run() {
67             Log.i("ForegroundService", "PULSE!");
68             mHandler.postDelayed(this, 5*1000);
69         }
70     };
71 
72     @Override
onCreate()73     public void onCreate() {
74         mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
75     }
76 
77     @Override
onDestroy()78     public void onDestroy() {
79         handleDestroy();
80         // Make sure our notification is gone.
81         stopForeground(R.string.foreground_service_started);
82     }
83 
84     @Override
onStartCommand(Intent intent, int flags, int startId)85     public int onStartCommand(Intent intent, int flags, int startId) {
86         if (ACTION_FOREGROUND.equals(intent.getAction())
87                 || ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction())) {
88             // In this sample, we'll use the same text for the ticker and the expanded notification
89             CharSequence text = getText(R.string.foreground_service_started);
90 
91             PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
92                     new Intent(this, Controller.class), 0);
93 
94             // Set the info for the views that show in the notification panel.
95             Notification notification = new Notification.Builder(this)
96                     .setSmallIcon(R.drawable.stat_sample)  // the status icon
97                     .setTicker(text)  // the status text
98                     .setWhen(System.currentTimeMillis())  // the time stamp
99                     .setContentTitle(getText(R.string.alarm_service_label))  // the label
100                     .setContentText(text)  // the contents of the entry
101                     .setContentIntent(contentIntent)  // The intent to send when clicked
102                     .build();
103 
104             startForeground(R.string.foreground_service_started, notification);
105 
106         } else if (ACTION_BACKGROUND.equals(intent.getAction())
107                 || ACTION_BACKGROUND_WAKELOCK.equals(intent.getAction())) {
108             stopForeground(R.string.foreground_service_started);
109         }
110 
111         if (ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction())
112                 || ACTION_BACKGROUND_WAKELOCK.equals(intent.getAction())) {
113             if (mWakeLock == null) {
114                 mWakeLock = getSystemService(PowerManager.class).newWakeLock(
115                         PowerManager.PARTIAL_WAKE_LOCK, "wake-service");
116                 mWakeLock.acquire();
117             } else {
118                 releaseWakeLock();
119             }
120         }
121 
122         mHandler.removeCallbacks(mPulser);
123         mPulser.run();
124 
125         // We want this service to continue running until it is explicitly
126         // stopped, so return sticky.
127         return START_STICKY;
128     }
129 
releaseWakeLock()130     void releaseWakeLock() {
131         if (mWakeLock != null) {
132             mWakeLock.release();
133             mWakeLock = null;
134         }
135     }
136 
handleDestroy()137     void handleDestroy() {
138         releaseWakeLock();
139         mHandler.removeCallbacks(mPulser);
140     }
141 
142     @Override
onBind(Intent intent)143     public IBinder onBind(Intent intent) {
144         return null;
145     }
146 
147     // ----------------------------------------------------------------------
148 
149     /**
150      * <p>Example of explicitly starting and stopping the {@link ForegroundService}.
151      *
152      * <p>Note that this is implemented as an inner class only keep the sample
153      * all together; typically this code would appear in some separate class.
154      */
155     public static class Controller extends Activity {
156         @Override
onCreate(Bundle savedInstanceState)157         protected void onCreate(Bundle savedInstanceState) {
158             super.onCreate(savedInstanceState);
159 
160             setContentView(R.layout.foreground_service_controller);
161 
162             // Watch for button clicks.
163             Button button = (Button)findViewById(R.id.start_foreground);
164             button.setOnClickListener(mForegroundListener);
165             button = (Button)findViewById(R.id.start_foreground_wakelock);
166             button.setOnClickListener(mForegroundWakelockListener);
167             button = (Button)findViewById(R.id.start_background);
168             button.setOnClickListener(mBackgroundListener);
169             button = (Button)findViewById(R.id.start_background_wakelock);
170             button.setOnClickListener(mBackgroundWakelockListener);
171             button = (Button)findViewById(R.id.stop);
172             button.setOnClickListener(mStopListener);
173             button = (Button)findViewById(R.id.start_foreground_2);
174             button.setOnClickListener(mForegroundListener2);
175             button = (Button)findViewById(R.id.stop_2);
176             button.setOnClickListener(mStopListener2);
177             button = (Button)findViewById(R.id.start_foreground_2_alarm);
178             button.setOnClickListener(mForegroundAlarmListener);
179         }
180 
181         private OnClickListener mForegroundListener = new OnClickListener() {
182             public void onClick(View v) {
183                 Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND);
184                 intent.setClass(Controller.this, ForegroundService.class);
185                 startService(intent);
186             }
187         };
188 
189         private OnClickListener mForegroundWakelockListener = new OnClickListener() {
190             public void onClick(View v) {
191                 Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND_WAKELOCK);
192                 intent.setClass(Controller.this, ForegroundService.class);
193                 startService(intent);
194             }
195         };
196 
197         private OnClickListener mBackgroundListener = new OnClickListener() {
198             public void onClick(View v) {
199                 Intent intent = new Intent(ForegroundService.ACTION_BACKGROUND);
200                 intent.setClass(Controller.this, ForegroundService.class);
201                 startService(intent);
202             }
203         };
204 
205         private OnClickListener mBackgroundWakelockListener = new OnClickListener() {
206             public void onClick(View v) {
207                 Intent intent = new Intent(ForegroundService.ACTION_BACKGROUND_WAKELOCK);
208                 intent.setClass(Controller.this, ForegroundService.class);
209                 startService(intent);
210             }
211         };
212 
213         private OnClickListener mStopListener = new OnClickListener() {
214             public void onClick(View v) {
215                 stopService(new Intent(Controller.this,
216                         ForegroundService.class));
217             }
218         };
219 
220         private OnClickListener mForegroundListener2 = new OnClickListener() {
221             public void onClick(View v) {
222                 Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND);
223                 intent.setClass(Controller.this, ForegroundService2.class);
224                 startService(intent);
225             }
226         };
227 
228         private OnClickListener mForegroundAlarmListener = new OnClickListener() {
229             public void onClick(View v) {
230                 final Context ctx = Controller.this;
231 
232                 final Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND);
233                 intent.setClass(ctx, ForegroundService2.class);
234 
235                 PendingIntent pi = PendingIntent.getForegroundService(ctx, 0, intent, 0);
236                 AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
237                 am.setExact(AlarmManager.ELAPSED_REALTIME,
238                         SystemClock.elapsedRealtime() + 15_000,
239                         pi);
240                 Log.i("ForegroundService", "Starting service in 15 seconds");
241             }
242         };
243 
244         private OnClickListener mStopListener2 = new OnClickListener() {
245             public void onClick(View v) {
246                 stopService(new Intent(Controller.this,
247                         ForegroundService2.class));
248             }
249         };
250 
251     }
252 }
253