• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.example.android.apis.app;
18 
19 import android.app.Notification;
20 import android.app.NotificationManager;
21 import android.app.PendingIntent;
22 import android.app.Service;
23 import android.content.Intent;
24 import android.os.RemoteException;
25 import android.os.Handler;
26 import android.os.IBinder;
27 import android.os.Message;
28 import android.os.Process;
29 import android.os.RemoteCallbackList;
30 import android.widget.Toast;
31 
32 import java.util.HashMap;
33 
34 // Need the following import to get access to the app resources, since this
35 // class is in a sub-package.
36 import com.example.android.apis.R;
37 
38 /**
39  * This is an example of implementing an application service that runs in a
40  * different process than the application.  Because it can be in another
41  * process, we must use IPC to interact with it.  The
42  * {@link RemoteServiceController} and {@link RemoteServiceBinding} classes
43  * show how to interact with the service.
44  */
45 public class RemoteService extends Service {
46     /**
47      * This is a list of callbacks that have been registered with the
48      * service.  Note that this is package scoped (instead of private) so
49      * that it can be accessed more efficiently from inner classes.
50      */
51     final RemoteCallbackList<IRemoteServiceCallback> mCallbacks
52             = new RemoteCallbackList<IRemoteServiceCallback>();
53 
54     int mValue = 0;
55     NotificationManager mNM;
56 
57     @Override
onCreate()58     public void onCreate() {
59         mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
60 
61         // Display a notification about us starting.
62         showNotification();
63 
64         // While this service is running, it will continually increment a
65         // number.  Send the first message that is used to perform the
66         // increment.
67         mHandler.sendEmptyMessage(REPORT_MSG);
68     }
69 
70     @Override
onDestroy()71     public void onDestroy() {
72         // Cancel the persistent notification.
73         mNM.cancel(R.string.remote_service_started);
74 
75         // Tell the user we stopped.
76         Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
77 
78         // Unregister all callbacks.
79         mCallbacks.kill();
80 
81         // Remove the next pending message to increment the counter, stopping
82         // the increment loop.
83         mHandler.removeMessages(REPORT_MSG);
84     }
85 
86 // BEGIN_INCLUDE(exposing_a_service)
87     @Override
onBind(Intent intent)88     public IBinder onBind(Intent intent) {
89         // Select the interface to return.  If your service only implements
90         // a single interface, you can just return it here without checking
91         // the Intent.
92         if (IRemoteService.class.getName().equals(intent.getAction())) {
93             return mBinder;
94         }
95         if (ISecondary.class.getName().equals(intent.getAction())) {
96             return mSecondaryBinder;
97         }
98         return null;
99     }
100 
101     /**
102      * The IRemoteInterface is defined through IDL
103      */
104     private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
105         public void registerCallback(IRemoteServiceCallback cb) {
106             if (cb != null) mCallbacks.register(cb);
107         }
108         public void unregisterCallback(IRemoteServiceCallback cb) {
109             if (cb != null) mCallbacks.unregister(cb);
110         }
111     };
112 
113     /**
114      * A secondary interface to the service.
115      */
116     private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
117         public int getPid() {
118             return Process.myPid();
119         }
120         public void basicTypes(int anInt, long aLong, boolean aBoolean,
121                 float aFloat, double aDouble, String aString) {
122         }
123     };
124 // END_INCLUDE(exposing_a_service)
125 
126     private static final int REPORT_MSG = 1;
127 
128     /**
129      * Our Handler used to execute operations on the main thread.  This is used
130      * to schedule increments of our value.
131      */
132     private final Handler mHandler = new Handler() {
133         @Override public void handleMessage(Message msg) {
134             switch (msg.what) {
135 
136                 // It is time to bump the value!
137                 case REPORT_MSG: {
138                     // Up it goes.
139                     int value = ++mValue;
140 
141                     // Broadcast to all clients the new value.
142                     final int N = mCallbacks.beginBroadcast();
143                     for (int i=0; i<N; i++) {
144                         try {
145                             mCallbacks.getBroadcastItem(i).valueChanged(value);
146                         } catch (RemoteException e) {
147                             // The RemoteCallbackList will take care of removing
148                             // the dead object for us.
149                         }
150                     }
151                     mCallbacks.finishBroadcast();
152 
153                     // Repeat every 1 second.
154                     sendMessageDelayed(obtainMessage(REPORT_MSG), 1*1000);
155                 } break;
156                 default:
157                     super.handleMessage(msg);
158             }
159         }
160     };
161 
162     /**
163      * Show a notification while this service is running.
164      */
showNotification()165     private void showNotification() {
166         // In this sample, we'll use the same text for the ticker and the expanded notification
167         CharSequence text = getText(R.string.remote_service_started);
168 
169         // Set the icon, scrolling text and timestamp
170         Notification notification = new Notification(R.drawable.stat_sample, text,
171                 System.currentTimeMillis());
172 
173         // The PendingIntent to launch our activity if the user selects this notification
174         PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
175                 new Intent(this, LocalServiceController.class), 0);
176 
177         // Set the info for the views that show in the notification panel.
178         notification.setLatestEventInfo(this, getText(R.string.remote_service_label),
179                        text, contentIntent);
180 
181         // Send the notification.
182         // We use a string id because it is a unique number.  We use it later to cancel.
183         mNM.notify(R.string.remote_service_started, notification);
184     }
185 }
186