Home | History | Annotate | Download | only in app
      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
     55     public void onCreate() {
     56         Log.i("IsolatedService", "Creating IsolatedService: " + this);
     57     }
     58 
     59     @Override
     60     public void onDestroy() {
     61         Log.i("IsolatedService", "Destroying IsolatedService: " + this);
     62         // Unregister all callbacks.
     63         mCallbacks.kill();
     64     }
     65 
     66     @Override
     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
     84     public void onTaskRemoved(Intent rootIntent) {
     85         Log.i("IsolatedService", "Task removed in " + this + ": " + rootIntent);
     86         stopSelf();
     87     }
     88 
     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 
    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 
    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
    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
    200         protected void onDestroy() {
    201             super.onDestroy();
    202             mService1.destroy();
    203             mService2.destroy();
    204         }
    205     }
    206 }
    207