最終更新:2016-01-19 (火) 17:46:07 (3012d)
Android/バインドされたサービス
http://developer.android.com/intl/ja/guide/components/bound-services.html
実装
サービス側
クライアント(アクティビティ)側
- [サービスとの接続を監視するServiceConnectionを実装
IBinderの定義方法
Binderクラスを拡張する
サービス側
public class LocalService extends Service { // Binder given to clients private final IBinder mBinder = new LocalBinder(); // Random number generator private final Random mGenerator = new Random(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { // Return this instance of LocalService so clients can call public methods return LocalService.this; } } @Override public IBinder onBind(Intent intent) { //return new LocalBinder(); return mBinder; } /** method for clients */ public int getRandomNumber() { return mGenerator.nextInt(100); } }
- サービスで次のいずれかに該当する Binder のインスタンスを作成
- クライアントが呼び出せる public メソッドを含んでいる
- クライアントが呼び出せる public メソッドで現在の Service インスタンスを返す
- クライアントが呼び出せる public メソッドのあるサービスでホストされた他のクラスのインスタンスを返す
- Binder のインスタンスを onBind() コールバック メソッドから返す
- クライアントで、Binder を onServiceConnected?() コールバック メソッドから受け取り、提供されたメソッドを使用してバインドされたサービスを呼び出す
クライアント側
public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute) */ public void onButtonClick(View v) { if (mBound) { // Call a method from the LocalService. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } ...
メッセンジャーを使用する
- android.os.Messenger
- 最も簡単にプロセス間通信(IPC)を実行する方法
- 実際にはAIDLを基本構造としています
AIDLを使用する
- ほとんどのアプリケーションにおいて、マルチスレッド化が必要な点や、結果的により複雑な実装となってしまうことから、AIDLを使ったバインドされたサービスの作成はお勧めしません。
- AIDL はほとんどのアプリケーションに適していないため、このドキュメントではサービスでの AIDL の使用方法については取り上げません。
- どうしても AIDL の直接使用が必要な場合は、「AIDL」のドキュメントをご覧ください。
呼び出し順
boolean Context.bindService(Intent service, ServiceConnection conn, int flags)
- バインド(bind)という仕組みを使い、ActvitiyとServiceでコネクションを確立する
IBinder Service.onBind(Intent intent)
- クライアントがサービスと通信するために使用する、インターフェイスIBinderを実装したクラスを返す必要がある
- 以下のいずれかのを行う Binder のインスタンスを作成します。
- クライアントが呼び出せる public メソッドを含める
- クライアントが呼び出せる public メソッドを持つ、現在の Service インスタンスを返す
- または、クライアントが呼び出せる public メソッドを持つサービスによりホストされた別のクラスのインスタンスを返す
void ServiceConnection.onServiceConnected(ComponentName name, IBinder service)
- サービスに接続したときに呼び出されるコールバックメソッド
boundService = ((サービス.バインダ)service),getService();
...
Service.onDestroy
メモ
- 1つ目のクライアントのバインドの際にのみ、システムはサービスのonBind() メソッドを呼び出してIBinderを取得します
- その後システムはonBind()を呼び出すことなく、同じIBinderをバインドしたすべてのクライアントに配信します