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