バインドされたサービスは、クライアント サーバー インターフェースにあるサーバーです。これにより、アクティビティなどのコンポーネントがサービスへのバインド、リクエストの送信、レスポンスの受信、プロセス間通信(IPC)の実行を行えるようになります。通常、バインドされたサービスは他のアプリ コンポーネントにサービスを提供している間だけ機能し、バックグラウンドで無期限に動作することはありません。
このドキュメントでは、バインドされたサービスの作成方法や、他のアプリ コンポーネントからサービスにバインドする方法について説明します。サービスから通知を配信する方法や、サービスをフォアグラウンドで実行する方法など、サービスの一般的な詳細については、 サービスの概要をご覧ください。
基本情報
バインドされたサービスは Service
クラスの実装であり、他のアプリがこのサービスにバインドしてやり取りできるようにします。サービスのバインディングを提供するには、onBind()
コールバック メソッドを実装します。このメソッドでは IBinder
オブジェクトが返されます。このオブジェクトは、クライアントがサービスとのやり取りに使用できるプログラミング インターフェースを定義します。
開始されたサービスにバインドする
サービスの概要で説明したように、開始されるサービスとバインドされるサービスの両方を作成できます。つまり、startService()
を呼び出してサービスを開始すると、サービスを無期限に実行できます。bindService()
を呼び出すことで、クライアントがサービスにバインドすることもできます。
サービスを開始してバインドした場合、サービスの開始時にすべてのクライアントのバインド解除が行われても、システムはサービスを破棄しません。サービスを停止するには、stopSelf()
または stopService()
を呼び出して明示的に停止する必要があります。
通常、onBind()
か onStartCommand()
のいずれかを実装しますが、両方の実装が必要な場合もあります。たとえば、音楽プレーヤーでは、サービスを無期限に実行し、バインディングも提供すると便利な場合があります。これにより、アクティビティがサービスを開始して音楽を再生し、ユーザーがアプリを離れても音楽の再生を継続できます。その後、ユーザーがアプリに戻ると、アクティビティがサービスにバインドして再生の制御を取り戻すことができます。
開始されたサービスにバインドを追加する際のサービスのライフサイクルの詳細については、バインドされたサービスのライフサイクルを管理するをご覧ください。
クライアントがサービスにバインドするには、bindService()
を呼び出します。バインド時は、ServiceConnection
を実装してサービスとの接続を監視する必要があります。bindService()
の戻り値は、リクエストされたサービスが存在するかどうかと、クライアントがそのサービスへのアクセスを許可されているかどうかを示します。
Android システムは、クライアントとサービス間の接続を作成すると、ServiceConnection
で onServiceConnected()
を呼び出します。onServiceConnected()
メソッドには IBinder
引数が含まれます。クライアントはこの引数を使用して、バインドされたサービスと通信します。
複数のクライアントを 1 つのサービスに同時に接続できます。ただし、システムは IBinder
サービス通信チャネルをキャッシュに保存します。つまり、最初のクライアントがバインドされるときにのみ、サービスの onBind()
メソッドを呼び出して IBinder
が生成されます。その後、onBind()
を再度呼び出すことなく、同じサービスにバインドする他のクライアントすべてに同じ IBinder
を配信します。
最後のクライアントがサービスからバインド解除されると、システムはサービスを破棄します(startService()
を使用してサービスが開始された場合を除きます)。
バインドされたサービスの実装で最も重要なのは、onBind()
コールバック メソッドが返すインターフェースを定義することです。次のセクションでは、サービスの IBinder
インターフェースを定義する方法について説明します。
バインドされたサービスを作成する
バインドを提供するサービスを作成する際は、IBinder
を提供し、クライアントがサービスとのやり取りに使用できるプログラミング インターフェースを提供する必要があります。インターフェースを定義するには、次の 3 つの方法があります。
- Binder クラスを拡張する
- サービスが独自のアプリに非公開で、クライアントと同じプロセスで実行される場合は(よくあることです)、
Binder
クラスを拡張してonBind()
からそのインスタンスを返すことにより、インターフェースを作成します。クライアントはBinder
を受け取り、それを使用してBinder
の実装やService
で利用できるパブリック メソッドに直接アクセスできます。サービスが単にアプリのバックグラウンド ワーカーである場合は、この方法が適しています。この方法がインターフェース作成の推奨方法ではない唯一のユースケースは、そのサービスが他のアプリや個別のプロセスで使用されている場合です。
- メッセンジャーを使用する
- 異なるプロセス間で動作するインターフェースが必要な場合は、
Messenger
を使用してサービスのインターフェースを作成できます。このようにして、サービスは異なるタイプのMessage
オブジェクトに応答するHandler
を定義します。この
Handler
は、IBinder
をクライアントと共有し、クライアントがMessage
オブジェクトを使用してサービスにコマンドを送信できるようにするMessenger
の基礎となります。また、クライアントは独自のMessenger
を定義して、サービスがメッセージを返送することもできます。これは、最も簡単にプロセス間通信(IPC)を行う方法であり、
Messenger
がすべてのリクエストを 1 つのスレッドにキューイングするため、サービスをスレッドセーフに設計する必要がありません。 - AIDL を使用する
- Android インターフェース定義言語(AIDL)は、オペレーティング システムが理解可能なプリミティブにオブジェクトを分解し、プロセス間でそれらをマーシャリングして IPC を実行します。
Messenger
を使用する前述の手法は、実際には AIDL を基本構造としてベースとしています。前のセクションで説明したように、
Messenger
はすべてのクライアント リクエストのキューを 1 つのスレッドに作成するため、サービスは一度に 1 つずつリクエストを受信します。ただし、サービスで複数のリクエストを同時に処理する場合は、AIDL を直接使用できます。この場合、サービスはスレッドセーフで、マルチスレッド処理に対応する必要があります。AIDL を直接使用するには、プログラミング インターフェースを定義する
.aidl
ファイルを作成します。Android SDK ツールはこのファイルを使用して、インターフェースを実装して IPC を処理する抽象クラスを生成します。その後、それをサービス内で拡張できます。
注: ほとんどのアプリにおいて、AIDL はバインドされたサービスの作成に最適ではありません。これは、マルチスレッド機能が必要になることがあり、実装がより複雑になる可能性があるためです。このため、このドキュメントでは、サービスをサービスで使用する方法については説明しません。AIDL を直接使用する必要がある場合は、AIDL のドキュメントをご覧ください。
Binder クラスを拡張する
ローカル アプリケーションのみがサービスを使用し、プロセス間で動作する必要がない場合は、独自の Binder
クラスを実装して、サービスのパブリック メソッドへのクライアント アクセスを直接提供できます。
注: この方法は、クライアントとサービスが同じアプリとプロセスにある場合(最も一般的なケース)にのみ有効です。たとえば、バックグラウンドで音楽を再生する独自のサービスにアクティビティをバインドする必要がある音楽アプリに適しています。
設定手順は次のとおりです。
- サービスで、次のいずれかを行う
Binder
のインスタンスを作成します。- クライアントが呼び出せるパブリック メソッドを格納する。
- クライアントが呼び出せるパブリック メソッドがある、現在の
Service
インスタンスを返す。 - クライアントが呼び出せるパブリック メソッドを含む、サービスでホストされた他のクラスのインスタンスを返す。
Binder
のインスタンスをonBind()
コールバック メソッドから返します。- クライアントで
Binder
をonServiceConnected()
コールバック メソッドから受け取り、提供されたメソッドを使用して、バインドされたサービスを呼び出します。
注: クライアントが返されたオブジェクトをキャストし、その API を適切に呼び出すことができるように、サービスとクライアントは同じアプリ内にある必要があります。また、この手法ではプロセス間でのマーシャリングが行われないため、サービスとクライアントは同じプロセスに存在する必要があります。
Binder
の実装を介してサービスのメソッドへのアクセスをクライアントに提供するサービスの例を次に示します。
Kotlin
class LocalService : Service() { // Binder given to clients. private val binder = LocalBinder() // Random number generator. private val mGenerator = Random() /** Method for clients. */ val randomNumber: Int get() = mGenerator.nextInt(100) /** * 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. */ inner class LocalBinder : Binder() { // Return this instance of LocalService so clients can call public methods. fun getService(): LocalService = this@LocalService } override fun onBind(intent: Intent): IBinder { return binder } }
Java
public class LocalService extends Service { // Binder given to clients. private final IBinder binder = 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 binder; } /** Method for clients. */ public int getRandomNumber() { return mGenerator.nextInt(100); } }
LocalBinder
が LocalService
の現在のインスタンスを取得するための getService()
メソッドをクライアントに提供します。これにより、クライアントはサービス内のパブリック メソッドを呼び出すことができます。たとえば、クライアントはサービスから getRandomNumber()
を呼び出せます。
ボタンがクリックされたときに LocalService
にバインドして、getRandomNumber()
を呼び出すアクティビティの例を次に示します。
Kotlin
class BindingActivity : Activity() { private lateinit var mService: LocalService private var mBound: Boolean = false /** Defines callbacks for service binding, passed to bindService(). */ private val connection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { // We've bound to LocalService, cast the IBinder and get LocalService instance. val binder = service as LocalService.LocalBinder mService = binder.getService() mBound = true } override fun onServiceDisconnected(arg0: ComponentName) { mBound = false } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) } override fun onStart() { super.onStart() // Bind to LocalService. Intent(this, LocalService::class.java).also { intent -> bindService(intent, connection, Context.BIND_AUTO_CREATE) } } override fun onStop() { super.onStop() unbindService(connection) mBound = false } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute). */ fun onButtonClick(v: View) { if (mBound) { // Call a method from the LocalService. // However, if this call is something that might hang, then put this request // in a separate thread to avoid slowing down the activity performance. val num: Int = mService.randomNumber Toast.makeText(this, "number: $num", Toast.LENGTH_SHORT).show() } } }
Java
public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to LocalService. Intent intent = new Intent(this, LocalService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); unbindService(connection); mBound = false; } /** 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 is something that might hang, then put this request // in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService(). */ private ServiceConnection connection = 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; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
上記のサンプルは、ServiceConnection
の実装と onServiceConnected()
コールバックを使用してクライアントがサービスにバインドする方法を示しています。次のセクションでは、サービスへのバインドのプロセスについて詳しく説明します。
注: 上記の例では、onStop()
メソッドはクライアントをサービスからバインド解除しています。その他の情報セクションの説明に沿って、適切なタイミングでクライアントをサービスからバインド解除します。
他のサンプルコードについては、ApiDemos の LocalService.java
クラスと、LocalServiceActivities.java
クラスをご覧ください。
メッセンジャーを使用する
リモート プロセスと通信するサービスが必要な場合は、Messenger
を使用してサービスのインターフェースを提供できます。この方法では、AIDL を使用することなくプロセス間通信(IPC)を実行できます。
Messenger
はサービスに対するすべての呼び出しをキューイングするため、インターフェースに Messenger
を使用する方が、AIDL を使用するよりも簡単です。純粋な AIDL インターフェースがサービスに同時リクエストを送信し、サービスはマルチスレッド処理を処理する必要があります。
ほとんどのアプリケーションでは、サービスでマルチスレッド処理を実行する必要がないため、Messenger
を使用することで、一度に 1 つの呼び出しを処理できます。サービスをマルチスレッド化することが重要な場合は、AIDL を使用してインターフェースを定義します。
Messenger
の使用方法の概要は次のとおりです。
- サービスが、クライアントからの呼び出しごとにコールバックを受け取る
Handler
を実装します。 - サービスが、
Handler
を使用してMessenger
オブジェクト(Handler
への参照)を作成します。 Messenger
は、サービスがonBind()
からクライアントに返すIBinder
を作成します。- クライアントが
IBinder
を使用して、サービスのHandler
を参照するMessenger
をインスタンス化します。クライアントはこれを使用してMessage
オブジェクトをサービスに送信します。 - サービスが、その
Handler
(具体的にはhandleMessage()
メソッド)でそれぞれのMessage
を受け取ります。
この方法には、クライアントがサービスで呼び出すメソッドはありません。代わりに、クライアントは、サービスがその Handler
で受け取るメッセージ(Message
オブジェクト)を配信します。
Messenger
インターフェースを使用するサービスの簡単な例を次に示します。
Kotlin
/** Command to the service to display a message. */ private const val MSG_SAY_HELLO = 1 class MessengerService : Service() { /** * Target we publish for clients to send messages to IncomingHandler. */ private lateinit var mMessenger: Messenger /** * Handler of incoming messages from clients. */ internal class IncomingHandler( context: Context, private val applicationContext: Context = context.applicationContext ) : Handler() { override fun handleMessage(msg: Message) { when (msg.what) { MSG_SAY_HELLO -> Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show() else -> super.handleMessage(msg) } } } /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ override fun onBind(intent: Intent): IBinder? { Toast.makeText(applicationContext, "binding", Toast.LENGTH_SHORT).show() mMessenger = Messenger(IncomingHandler(this)) return mMessenger.binder } }
Java
public class MessengerService extends Service { /** * Command to the service to display a message. */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients. */ static class IncomingHandler extends Handler { private Context applicationContext; IncomingHandler(Context context) { applicationContext = context.getApplicationContext(); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ Messenger mMessenger; /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); mMessenger = new Messenger(new IncomingHandler(this)); return mMessenger.getBinder(); } }
Handler
の handleMessage()
メソッドでは、サービスが着信した Message
を受け取り、what
メンバーに基づいて処理を決定します。
クライアントで必要な操作は、サービスから返された IBinder
に基づいて Messenger
を作成し、send()
を使用してメッセージを送信することだけです。サービスにバインドして MSG_SAY_HELLO
メッセージをサービスに配信するアクティビティの例を次に示します。
Kotlin
class ActivityMessenger : Activity() { /** Messenger for communicating with the service. */ private var mService: Messenger? = null /** Flag indicating whether we have called bind on the service. */ private var bound: Boolean = false /** * Class for interacting with the main interface of the service. */ private val mConnection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = Messenger(service) bound = true } override fun onServiceDisconnected(className: ComponentName) { // This is called when the connection with the service has been // unexpectedly disconnected—that is, its process crashed. mService = null bound = false } } fun sayHello(v: View) { if (!bound) return // Create and send a message to the service, using a supported 'what' value. val msg: Message = Message.obtain(null, MSG_SAY_HELLO, 0, 0) try { mService?.send(msg) } catch (e: RemoteException) { e.printStackTrace() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) } override fun onStart() { super.onStart() // Bind to the service. Intent(this, MessengerService::class.java).also { intent -> bindService(intent, mConnection, Context.BIND_AUTO_CREATE) } } override fun onStop() { super.onStop() // Unbind from the service. if (bound) { unbindService(mConnection) bound = false } } }
Java
public class ActivityMessenger extends Activity { /** Messenger for communicating with the service. */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean bound; /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = new Messenger(service); bound = true; } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected—that is, its process crashed. mService = null; bound = false; } }; public void sayHello(View v) { if (!bound) return; // Create and send a message to the service, using a supported 'what' value. Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to the service. bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service. if (bound) { unbindService(mConnection); bound = false; } } }
この例では、サービスがどのようにクライアントに応答するかは示していません。サービスに応答させるには、クライアントで Messenger
も作成する必要があります。クライアントは onServiceConnected()
コールバックを受け取ると、send()
メソッドの replyTo
パラメータにクライアントの Messenger
を含めた Message
をサービスに送信します。
双方向メッセージを提供する方法の例については、MessengerService.java
(サービス)と MessengerServiceActivities.java
(クライアント)のサンプルをご覧ください。
サービスにバインドする
アプリ コンポーネント(クライアント)がサービスにバインドする際は、bindService()
を呼び出します。Android システムがサービスの onBind()
メソッドを呼び出し、そこからサービスとのやり取りに必要な IBinder
が返されます。
バインドは非同期的に行われます。bindService()
は IBinder
をクライアントに返すことなく、すぐに戻ります。IBinder
を受け取るには、クライアントが ServiceConnection
のインスタンスを作成し、それを bindService()
に渡す必要があります。ServiceConnection
には、システムが IBinder
を配信するために呼び出すコールバック メソッドが含まれています。
注: サービスにバインドできるのは、アクティビティ、サービス、コンテンツ プロバイダのみです。ブロードキャスト レシーバからサービスにバインドすることはできません。
クライアントからサービスにバインドする手順は、次のとおりです。
ServiceConnection
を実装します。実装では次の 2 つのコールバック メソッドをオーバーライドする必要があります。
onServiceConnected()
- システムがこのメソッドを呼び出して、サービスの
onBind()
メソッドから返されたIBinder
を配信します。 onServiceDisconnected()
- サービスがクラッシュまたは強制終了されたときなど、サービスへの接続が予期せず失われたときに、Android システムがこれを呼び出します。このメソッドは、クライアントのアンバインドの際には呼び出されません。
bindService()
を呼び出して、ServiceConnection
の実装を渡します。注: このメソッドから false が返された場合、クライアントにはサービスへの有効な接続がありません。ただし、クライアントで
unbindService()
を呼び出してください。そうしないと、クライアントはサービスがアイドル状態のときにシャットダウンしないようにします。- システムが
onServiceConnected()
コールバック メソッドを呼び出すと、インターフェースで定義されたメソッドを使用してサービスへの呼び出しを開始できます。 - サービスとの接続を切断するには、
unbindService()
を呼び出します。アプリによってクライアントが破棄されたときに、クライアントが引き続きサービスにバインドされている場合は、この破棄によりクライアントがアンバインドされます。サービスとのやり取りが完了したら、すぐにクライアントをバインド解除することをおすすめします。これにより、アイドル状態のサービスをシャットダウンできます。バインドとバインド解除の適切なタイミングについては、その他の情報セクションをご覧ください。
次の例では、Binder クラスを拡張して、以前に作成したサービスにクライアントを接続するため、必要なのは、返された IBinder
を LocalBinder
クラスにキャストして、LocalService
インスタンスをリクエストすることだけです。
Kotlin
var mService: LocalService val mConnection = object : ServiceConnection { // Called when the connection with the service is established. override fun onServiceConnected(className: ComponentName, service: IBinder) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. val binder = service as LocalService.LocalBinder mService = binder.getService() mBound = true } // Called when the connection with the service disconnects unexpectedly. override fun onServiceDisconnected(className: ComponentName) { Log.e(TAG, "onServiceDisconnected") mBound = false } }
Java
LocalService mService; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established. public void onServiceConnected(ComponentName className, IBinder service) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } // Called when the connection with the service disconnects unexpectedly. public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "onServiceDisconnected"); mBound = false; } };
この ServiceConnection
を使用して、次の例のように、クライアントはそれを bindService()
に渡すことでサービスにバインドできます。
Kotlin
Intent(this, LocalService::class.java).also { intent -> bindService(intent, connection, Context.BIND_AUTO_CREATE) }
Java
Intent intent = new Intent(this, LocalService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE);
bindService()
の最初のパラメータは、バインドするサービス名を明示的に指定するIntent
です。注意: インテントを使用して
Service
にバインドする場合は、明示的インテントを使用して、アプリが安全であることを確認してください。暗黙的インテントを使用してサービスを開始すると、どのサービスがインテントに応答するのかを判断できず、ユーザーはどのサービスが開始するのかがわからないため、セキュリティ上の危険が発生します。Android 5.0(API レベル 21)以降では、暗黙的インテントを使用してbindService()
を呼び出すと、システムから例外がスローされます。- 2 つ目のパラメータは、
ServiceConnection
オブジェクトです。 - 3 つ目のパラメータは、バインディングのオプションを示すフラグです。通常は
BIND_AUTO_CREATE
で、サービスがまだ有効になっていない場合に作成します。他に指定可能な値はBIND_DEBUG_UNBIND
、BIND_NOT_FOREGROUND
、なしの場合は0
です。
その他の注意事項
サービスへのバインドに関する重要な注意点は次のとおりです。
- 接続が切断されたときにスローされる
DeadObjectException
例外を常にトラップします。リモート メソッドからスローされる例外はこれのみです。 - オブジェクトはプロセス間で有効な参照です。
- 通常、次の例に示すように、クライアントのライフサイクルの立ち上げと破棄が一致するタイミングで、バインディングとバインド解除をペア設定します。
- アクティビティが表示されている間だけサービスを操作する必要がある場合は、
onStart()
の間にバインドし、onStop()
の間にバインドを解除します。 - アクティビティがバックグラウンドで停止している場合でもレスポンスを受け取るようにするには、
onCreate()
中にバインドし、onDestroy()
中にバインドを解除します。これは、アクティビティの実行中に(バックグラウンドであっても)サービスがサービスを使用する必要があることを意味するため、サービスが別のプロセスにある場合はプロセスの重みが増加し、システムによって強制終了される可能性が高くなります。
注: 通常、アクティビティの
onResume()
コールバックとonPause()
コールバックは、バインドとアンバインドを行いません。これは、これらのコールバックはライフサイクルの遷移のたびに発生するためです。これらの移行で発生する処理は最小限に抑えます。また、アプリの複数のアクティビティが同じサービスにバインドしていて、2 つのアクティビティ間で遷移が発生する場合、次のアクティビティがバインドされる前に(再開時)現在のアクティビティがバインド解除されるときに(一時停止時に)サービスが破棄され、再作成される可能性があります。アクティビティがライフサイクルを調整する仕組みに関するこのアクティビティの遷移については、アクティビティのライフサイクルで説明しています。
- アクティビティが表示されている間だけサービスを操作する必要がある場合は、
サービスにバインドする方法を示すサンプルコードについては、ApiDemos の
RemoteService.java
クラスをご覧ください。
バインドされたサービスのライフサイクルを管理する
サービスがすべてのクライアントからバインド解除されると、Android システムはそのサービスを破棄します(startService()
を使用して開始された場合を除く)。したがって、純粋にバインドされたサービスであれば、サービスのライフサイクルを管理する必要はありません。Android システムは、クライアントにバインドされているかどうかに基づいて管理します。
ただし、onStartCommand()
コールバック メソッドを実装する場合は、サービスが開始されたとみなされるため、サービスを明示的に停止する必要があります。この場合、クライアントにバインドされているかどうかにかかわらず、サービスが stopSelf()
で自ら停止するか、他のコンポーネントが stopService()
を呼び出すまで、サービスは動作し続けます。
また、サービスが起動してバインディングを受け入れた場合、次回クライアントがサービスにバインドしたときに onRebind()
の呼び出しを受け取れるように、システムが onUnbind()
メソッドを呼び出すときに必要に応じて true
を返すことができます。onRebind()
からは void が返されますが、クライアントは onServiceConnected()
コールバックで IBinder
を受け取ります。次の図は、この種類のライフサイクルのロジックを示しています。
開始されたサービスのライフサイクルの詳細については、サービスの概要をご覧ください。