1 /* 2 * Copyright (C) 2012 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.Service; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.ServiceConnection; 25 import android.os.Bundle; 26 import android.os.RemoteException; 27 import android.os.IBinder; 28 import android.os.RemoteCallbackList; 29 import android.util.Log; 30 import android.view.View; 31 import android.view.View.OnClickListener; 32 import android.widget.Button; 33 import android.widget.CheckBox; 34 import android.widget.TextView; 35 36 // Need the following import to get access to the app resources, since this 37 // class is in a sub-package. 38 import com.example.android.apis.R; 39 40 /** 41 * This is an example if implementing a Service that uses android:isolatedProcess. 42 */ 43 public class IsolatedService extends Service { 44 /** 45 * This is a list of callbacks that have been registered with the 46 * service. Note that this is package scoped (instead of private) so 47 * that it can be accessed more efficiently from inner classes. 48 */ 49 final RemoteCallbackList<IRemoteServiceCallback> mCallbacks 50 = new RemoteCallbackList<IRemoteServiceCallback>(); 51 52 int mValue = 0; 53 54 @Override onCreate()55 public void onCreate() { 56 Log.i("IsolatedService", "Creating IsolatedService: " + this); 57 } 58 59 @Override onDestroy()60 public void onDestroy() { 61 Log.i("IsolatedService", "Destroying IsolatedService: " + this); 62 // Unregister all callbacks. 63 mCallbacks.kill(); 64 } 65 66 @Override onBind(Intent intent)67 public IBinder onBind(Intent intent) { 68 return mBinder; 69 } 70 71 /** 72 * The IRemoteInterface is defined through IDL 73 */ 74 private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { 75 public void registerCallback(IRemoteServiceCallback cb) { 76 if (cb != null) mCallbacks.register(cb); 77 } 78 public void unregisterCallback(IRemoteServiceCallback cb) { 79 if (cb != null) mCallbacks.unregister(cb); 80 } 81 }; 82 83 @Override onTaskRemoved(Intent rootIntent)84 public void onTaskRemoved(Intent rootIntent) { 85 Log.i("IsolatedService", "Task removed in " + this + ": " + rootIntent); 86 stopSelf(); 87 } 88 broadcastValue(int value)89 private void broadcastValue(int value) { 90 // Broadcast to all clients the new value. 91 final int N = mCallbacks.beginBroadcast(); 92 for (int i=0; i<N; i++) { 93 try { 94 mCallbacks.getBroadcastItem(i).valueChanged(value); 95 } catch (RemoteException e) { 96 // The RemoteCallbackList will take care of removing 97 // the dead object for us. 98 } 99 } 100 mCallbacks.finishBroadcast(); 101 } 102 103 // ---------------------------------------------------------------------- 104 105 public static class Controller extends Activity { 106 static class ServiceInfo { 107 final Activity mActivity; 108 final Class<?> mClz; 109 final TextView mStatus; 110 boolean mServiceBound; 111 IRemoteService mService; 112 ServiceInfo(Activity activity, Class<?> clz, int start, int stop, int bind, int status)113 ServiceInfo(Activity activity, Class<?> clz, 114 int start, int stop, int bind, int status) { 115 mActivity = activity; 116 mClz = clz; 117 Button button = (Button)mActivity.findViewById(start); 118 button.setOnClickListener(mStartListener); 119 button = (Button)mActivity.findViewById(stop); 120 button.setOnClickListener(mStopListener); 121 CheckBox cb = (CheckBox)mActivity.findViewById(bind); 122 cb.setOnClickListener(mBindListener); 123 mStatus = (TextView)mActivity.findViewById(status); 124 } 125 destroy()126 void destroy() { 127 if (mServiceBound) { 128 mActivity.unbindService(mConnection); 129 } 130 } 131 132 private OnClickListener mStartListener = new OnClickListener() { 133 public void onClick(View v) { 134 mActivity.startService(new Intent(mActivity, mClz)); 135 } 136 }; 137 138 private OnClickListener mStopListener = new OnClickListener() { 139 public void onClick(View v) { 140 mActivity.stopService(new Intent(mActivity, mClz)); 141 } 142 }; 143 144 private OnClickListener mBindListener = new OnClickListener() { 145 public void onClick(View v) { 146 if (((CheckBox)v).isChecked()) { 147 if (!mServiceBound) { 148 if (mActivity.bindService(new Intent(mActivity, mClz), 149 mConnection, Context.BIND_AUTO_CREATE)) { 150 mServiceBound = true; 151 mStatus.setText("BOUND"); 152 } 153 } 154 } else { 155 if (mServiceBound) { 156 mActivity.unbindService(mConnection); 157 mServiceBound = false; 158 mStatus.setText(""); 159 } 160 } 161 } 162 }; 163 164 private ServiceConnection mConnection = new ServiceConnection() { 165 public void onServiceConnected(ComponentName className, 166 IBinder service) { 167 mService = IRemoteService.Stub.asInterface(service); 168 if (mServiceBound) { 169 mStatus.setText("CONNECTED"); 170 } 171 } 172 173 public void onServiceDisconnected(ComponentName className) { 174 // This is called when the connection with the service has been 175 // unexpectedly disconnected -- that is, its process crashed. 176 mService = null; 177 if (mServiceBound) { 178 mStatus.setText("DISCONNECTED"); 179 } 180 } 181 }; 182 } 183 184 ServiceInfo mService1; 185 ServiceInfo mService2; 186 187 @Override onCreate(Bundle savedInstanceState)188 protected void onCreate(Bundle savedInstanceState) { 189 super.onCreate(savedInstanceState); 190 191 setContentView(R.layout.isolated_service_controller); 192 193 mService1 = new ServiceInfo(this, IsolatedService.class, R.id.start1, R.id.stop1, 194 R.id.bind1, R.id.status1); 195 mService2 = new ServiceInfo(this, IsolatedService2.class, R.id.start2, R.id.stop2, 196 R.id.bind2, R.id.status2); 197 } 198 199 @Override onDestroy()200 protected void onDestroy() { 201 super.onDestroy(); 202 mService1.destroy(); 203 mService2.destroy(); 204 } 205 } 206 } 207