前回に引き続き、今回もサービス(Service)に関する記事です。
Serviceは常駐型のアプリケーションを作る時に使うバックグラウンド処理をしてくれる奴です。
今回はバインド(bind)という仕組みを使ってやり方を紹介してみます(^ω^)
バインド(Bind)を利用したサービス
前回(【Android】サービス(Service)を使ってバックグラウンド処理をする(1))前回のstartService、stopServiceで利用するサービスの場合、
一度サービスを動かした場合、呼び出し元からは制御ができません、stopServiceで止めるくらいです。
加えて、呼び出し元が終了した場合でもサービスは動き続けます。
バインド(Bind)という仕組みを利用したサービスの場合、
呼び出し時に接続を行い、呼び出し元のActivityから関数を呼び出したり制御ができます。
また、呼び出し元が終了した場合、接続が切れサービスも一緒に終了してくれます、
バインド(束縛)をしているので一緒に引きずられて落ちるようなイメージですね
ライフサイクルが違ったり、内部クラスを使ったりとこっちのほうは若干メンドクサイです(´・ω・`)
AndroidManifest.xmlにServiceを追加
忘れずに追加です。
これから作るサービスのクラス名と同じにしておきます。
今回は TestBindService としました。
</activity>
<service android:name="TestBindService" />
</application>
</manifest>
Serviceクラスの派生クラスを作成する
クラスファイルを追加してServiceクラスの派生クラスを作成します。
ライフサイクルは以下のような感じ。
onCreateとonDestroyはバインドを利用しない場合と同じですね。
onStartCommandの代わりに、
- onBind
- onUnbind
- ServiceConnectionクラスのonServiceConnected
【実装例】
・TestBindeSerive.java
public class TestBindService extends Service {
// Binderクラスを継承した内部クラス
public class BindServiceBinder extends Binder{
TestBindService getService(){
return TestBindService.this;
}
}
// Binderの作成
private final IBinder mBinder = new BindServiceBinder();
@Override
public void onCreate() {
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent){
return true;
}
@Override
public void onDestroy(){
}
}
Binderクラスを継承した内部クラスBindServiceBinderが定義されています。
このクラスではTestBindService自身を返す関数だけ持っています。
次に、BindServiceBinderをインスタンスを生成。
onBindメソッドの返り値でそれを渡しています。
「あれ?ライフサイクルの中にあるonServiceConnectedはどこ?」
と思われる方もいるかもしれませんが、
その部分はサービスの起動側に書きます、ややこしい(´ω`)
Activityからサービスの起動をする
今度は呼び出し元のActivityです。
前回はstartServiceで開始、stopServiceで終了だったのに対し、
今回は
- bindService
- unbindService
両方の関数の引数には以下の2つの関数を持つ、
ServiceConnectionインターフェイスを実装したクラスのインスタンスを渡します。
- onServiceConnectedメソッド
- onServiceDisconnectedメソッド
名前を見てなんとなくわかると思いますが、接続が成功するとonServiceConnectedメソッドが呼び出されます。
このメソッドの引数には先ほどTestBindeSeriveクラスで作成したBinderが渡されるので、
getServiceメソッドでサービスのインスタンスが取得できます。
サンプルプログラム
■GitHub
ouka-tenshi/Android-Sample/tree/master/ServicBindSample
サービスを呼び出して各メソッド内ログを吐き出します。
適当な関数をサービス側に作成して、Activity側のボタンを押して呼び出します。
・MainActivity
public class MainActivity extends Activity {
private final int WC = ViewGroup.LayoutParams.WRAP_CONTENT;
// レイアウト
LinearLayout ll;
Button btnBind;
Button btnUnBind;
Button btnFunc;
// Service
TestBindService mService;
boolean connectionStatus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("MainActivity", "onCreate");
ll = new LinearLayout(this);
ll.setGravity( Gravity.CENTER_VERTICAL);
ll.setOrientation( LinearLayout.VERTICAL );
btnBind = new Button(this);
btnUnBind = new Button(this);
btnFunc = new Button(this);
btnBind.setOnClickListener( new ServiceOnClickListener() );
btnUnBind.setOnClickListener( new ServiceOnClickListener() );
btnFunc.setOnClickListener( new ServiceOnClickListener() );
btnBind.setText("Service Onbind");
btnUnBind.setText("Service Unbind");
btnFunc.setText("Service 適当な関数");
ll.addView( btnBind , WC );
ll.addView( btnUnBind, WC );
ll.addView( btnFunc , WC );
setContentView(ll);
}
// コネクション作成
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// サービス接続時に呼ばれる
Log.i("ServiceConnection", "onServiceConnected");
// BinderからServiceのインスタンスを取得
mService = ((TestBindService.BindServiceBinder)service).getService();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// サービス切断時に呼ばれる
Log.i("ServiceConnection", "onServiceDisconnected");
mService = null;
}
};
// リスナー
class ServiceOnClickListener implements OnClickListener{
@Override
public void onClick(View view) {
if( view == btnBind ){
// バインド開始
bindService( new Intent( MainActivity.this, TestBindService.class ) ,
connection,
Context.BIND_AUTO_CREATE
);
connectionStatus = true;
}else if( view == btnUnBind ){
if( connectionStatus ){
// バインドされている場合、バインドを解除
unbindService( connection );
connectionStatus = false;
}
}else if( view == btnFunc ){
if( connectionStatus ){
// 適当な関数を呼び出し
mService.TestFunction();
}
}
}
}
}
・TestBindService
public class TestBindService extends Service {
public class BindServiceBinder extends Binder{
// TestBindService自身を返す
TestBindService getService(){
return TestBindService.this;
}
}
// Binderの作成
private final IBinder mBinder = new BindServiceBinder();
@Override
public void onCreate() {
Log.i("BindService", "onCreate");
}
@Override
public IBinder onBind(Intent intent) {
Log.i("BindService", "onBind");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent){
Log.i("BindService", "onUnbind");
return true;
}
@Override
public void onDestroy(){
Log.i("BindService", "onDestroy");
}
public void TestFunction(){
Log.i("BindService", "適当に作った関数が呼ばれました(^ω^)");
}
}
【実行結果】


ライフサイクル通りのログが確認できますね。
アプリを終了させるとBindServiceでonUnbind、onDestroyが呼び出されるのが確認できます。

