/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.app; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.RemoteException; import android.os.IBinder; import android.os.RemoteCallbackList; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; // Need the following import to get access to the app resources, since this // class is in a sub-package. import com.example.android.apis.R; /** * This is an example if implementing a Service that uses android:isolatedProcess. */ public class IsolatedService extends Service { /** * This is a list of callbacks that have been registered with the * service. Note that this is package scoped (instead of private) so * that it can be accessed more efficiently from inner classes. */ final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>(); int mValue = 0; @Override public void onCreate() { Log.i("IsolatedService", "Creating IsolatedService: " + this); } @Override public void onDestroy() { Log.i("IsolatedService", "Destroying IsolatedService: " + this); // Unregister all callbacks. mCallbacks.kill(); } @Override public IBinder onBind(Intent intent) { return mBinder; } /** * The IRemoteInterface is defined through IDL */ private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { public void registerCallback(IRemoteServiceCallback cb) { if (cb != null) mCallbacks.register(cb); } public void unregisterCallback(IRemoteServiceCallback cb) { if (cb != null) mCallbacks.unregister(cb); } }; @Override public void onTaskRemoved(Intent rootIntent) { Log.i("IsolatedService", "Task removed in " + this + ": " + rootIntent); stopSelf(); } private void broadcastValue(int value) { // Broadcast to all clients the new value. final int N = mCallbacks.beginBroadcast(); for (int i=0; i<N; i++) { try { mCallbacks.getBroadcastItem(i).valueChanged(value); } catch (RemoteException e) { // The RemoteCallbackList will take care of removing // the dead object for us. } } mCallbacks.finishBroadcast(); } // ---------------------------------------------------------------------- public static class Controller extends Activity { static class ServiceInfo { final Activity mActivity; final Class<?> mClz; final TextView mStatus; boolean mServiceBound; IRemoteService mService; ServiceInfo(Activity activity, Class<?> clz, int start, int stop, int bind, int status) { mActivity = activity; mClz = clz; Button button = (Button)mActivity.findViewById(start); button.setOnClickListener(mStartListener); button = (Button)mActivity.findViewById(stop); button.setOnClickListener(mStopListener); CheckBox cb = (CheckBox)mActivity.findViewById(bind); cb.setOnClickListener(mBindListener); mStatus = (TextView)mActivity.findViewById(status); } void destroy() { if (mServiceBound) { mActivity.unbindService(mConnection); } } private OnClickListener mStartListener = new OnClickListener() { public void onClick(View v) { mActivity.startService(new Intent(mActivity, mClz)); } }; private OnClickListener mStopListener = new OnClickListener() { public void onClick(View v) { mActivity.stopService(new Intent(mActivity, mClz)); } }; private OnClickListener mBindListener = new OnClickListener() { public void onClick(View v) { if (((CheckBox)v).isChecked()) { if (!mServiceBound) { if (mActivity.bindService(new Intent(mActivity, mClz), mConnection, Context.BIND_AUTO_CREATE)) { mServiceBound = true; mStatus.setText("BOUND"); } } } else { if (mServiceBound) { mActivity.unbindService(mConnection); mServiceBound = false; mStatus.setText(""); } } } }; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = IRemoteService.Stub.asInterface(service); if (mServiceBound) { mStatus.setText("CONNECTED"); } } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; if (mServiceBound) { mStatus.setText("DISCONNECTED"); } } }; } ServiceInfo mService1; ServiceInfo mService2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.isolated_service_controller); mService1 = new ServiceInfo(this, IsolatedService.class, R.id.start1, R.id.stop1, R.id.bind1, R.id.status1); mService2 = new ServiceInfo(this, IsolatedService2.class, R.id.start2, R.id.stop2, R.id.bind2, R.id.status2); } @Override protected void onDestroy() { super.onDestroy(); mService1.destroy(); mService2.destroy(); } } }