Android Service をバインドして Serviceのメソッドを呼び出すのは、、
・bindService の実行と実際に Service メソッドを call 可能になるのは非同期であること。
・バインドして呼びだすクラスの記述量が大きくなりやすい。
これらを解決したくて、まずはAIDL使用しないケースで考えてみました。
Service実装側の Binder に1つインターフェースを被せる
import android.app.Service;
import android.os.IBinder;
/**
* ITransitBinder
*/
public interface ITransitBinder extends IBinder{
public Service getService();
}
このインタフェースは、Serviceをバインド取得する時に使う。
Service 側は、以下のように、Binderから、自身のServiceを取得できるように用意する。
public class SampleService extends Service {
private final IBinder mBinder = new MyServiceBinder();
class MyServiceBinder extends Binder implements ITransitBinder{
@Override
public SampleService getService(){
return SampleService.this;
}
}
@Override
public IBinder onBind(Intent intent){
return mBinder;
}
// 他は省略
}
Serviceをバインドする側のためのインターフェース、これが鍵である。
public interface IServiceProcessor<T extends android.app.Service>{
public void process(T service);
}
これは、例として、、
呼び出す Activity で以下のようにするだけで呼び出す目的のインターフェースである。
ServiceClient serviceClient = new ServiceClient(this, SampleService.class);
serviceClient.execute(new IServiceProcessor<SampleService>(){
@Override
public void process(SampleService service){
// 総称型で指定する Service 継承クラスのメソッドを実行する
}
});
この ServiceClient の正体は、、、
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
/**
* ServiceClient
*/
public final class ServiceClient{
Context mContext;
private Class<? extends Service> mServiceClass;
Service mBoundService;
IServiceProcessor mProcessor;
public ServiceClient(Context context, Class<? extends Service> serviceClass){
mContext = context;
mServiceClass = serviceClass;
}
public void execute(IServiceProcessor processor){
mProcessor = processor;
mContext.bindService(new Intent(mContext,mServiceClass), mConnection, Context.BIND_AUTO_CREATE);
}
ServiceConnection mConnection = new ServiceConnection(){
@SuppressWarnings("unchecked")
@Override
public void onServiceConnected(ComponentName name,IBinder binder){
mBoundService = ((ITransitBinder)binder).getService();
mProcessor.process(mBoundService);
mContext.unbindService(mConnection);
}
@Override
public void onServiceDisconnected(ComponentName name){
mBoundService = null;
}
};
}