IBind によるアクティビティとサービスの接続
ここではアクティビティとサービスの接続を行う方法をしめします。
この方法を使うとサービス内に実装したメソッドをアクティビティから呼ぶことができます。
バインダーの実装
次のようにして Binder から派生したクラスを、このサービスクラスのバインダーとして作成します。
アクティビティ側でサービスをバインドしたときに、Binder の IBind インターフェイスを取得でき、それをもとにサービスのインスタンスにアクセスできるようになります。
package com.keicode.android.test;
import android.app.IntentService;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyIntentService extends IntentService {
final static String TAG = "ServiceTest6";
final IBinder binder = new MyBinder();
String message;
public class MyBinder extends Binder {
MyIntentService getService(){
return MyIntentService.this;
}
}
public MyIntentService() {
super(TAG);
}
public void setMessage(String message){
this.message = message;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return binder;
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
Log.d(TAG, "message = [" + message + "]");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
サービスの起動側は、次のようになります。
package com.keicode.android.test;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ServiceTest6 extends Activity {
final static String TAG = "ServiceTest6";
Button startButton;
MyIntentService myService;
Intent serviceIntent;
ServiceConnection serviceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected");
myService = ((MyIntentService.MyBinder)service).getService();
myService.setMessage("Hello, IBinder!");
startService(serviceIntent);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected");
myService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startButton = (Button)findViewById(R.id.start_button);
startButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
serviceIntent = new Intent(
getBaseContext(), MyIntentService.class);
bindService(
serviceIntent, serviceConnection,
Context.BIND_AUTO_CREATE);
}
});
}
}
直ちに startService せずに、先に bindService を呼び出し ServiceConnection の onServiceConnected メソッドを呼び出させておき、 そこで startService します。
実行結果は次の通り。
別プロセスで実行する場合は・・・ AIDL
尚ここの方法では、サービスを別プロセスで実行すると、onServiceConnected で MyIntentService.MyBinder にキャストするところで失敗します。 別プロセスの場合この IBinder は android.os.BinderProxy のものになるためです。従って別プロセスで実行する場合は AIDL による IPC を検討すると良いです。