diff options
Diffstat (limited to 'docs/html/guide/components/bound-services.jd')
-rw-r--r-- | docs/html/guide/components/bound-services.jd | 675 |
1 files changed, 675 insertions, 0 deletions
diff --git a/docs/html/guide/components/bound-services.jd b/docs/html/guide/components/bound-services.jd new file mode 100644 index 0000000..b6a2512 --- /dev/null +++ b/docs/html/guide/components/bound-services.jd @@ -0,0 +1,675 @@ +page.title=Bound Services +parent.title=Services +parent.link=services.html +@jd:body + + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>Quickview</h2> +<ul> + <li>A bound service allows other components to bind to it, in order to interact with it and +perform interprocess communication</li> + <li>A bound service is destroyed once all clients unbind, unless the service was also started</li> +</ul> +<h2>In this document</h2> +<ol> + <li><a href="#Basics">The Basics</a></li> + <li><a href="#Creating">Creating a Bound Service</a> + <ol> + <li><a href="#Binder">Extending the Binder class</a></li> + <li><a href="#Messenger">Using a Messenger</a></li> + </ol> + </li> + <li><a href="#Binding">Binding to a Service</a></li> + <li><a href="#Lifecycle">Managing the Lifecycle of a Bound Service</a></li> +</ol> + +<h2>Key classes</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.content.ServiceConnection}</li> + <li>{@link android.os.IBinder}</li> +</ol> + +<h2>Samples</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code + RemoteService}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>See also</h2> +<ol> + <li><a href="{@docRoot}guide/components/services.html">Services</a></li> +</ol> +</div> + + +<p>A bound service is the server in a client-server interface. A bound service allows components +(such as activities) to bind to the service, send requests, receive responses, and even perform +interprocess communication (IPC). A bound service typically lives only while it serves another +application component and does not run in the background indefinitely.</p> + +<p>This document shows you how to create a bound service, including how to bind +to the service from other application components. However, you should also refer to the <a +href="{@docRoot}guide/components/services.html">Services</a> document for additional +information about services in general, such as how to deliver notifications from a service, set +the service to run in the foreground, and more.</p> + + +<h2 id="Basics">The Basics</h2> + +<p>A bound service is an implementation of the {@link android.app.Service} class that allows +other applications to bind to it and interact with it. To provide binding for a +service, you must implement the {@link android.app.Service#onBind onBind()} callback method. This +method returns an {@link android.os.IBinder} object that defines the programming interface that +clients can use to interact with the service.</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Binding to a Started Service</h3> + +<p>As discussed in the <a href="{@docRoot}guide/components/services.html">Services</a> +document, you can create a service that is both started and bound. That is, the service can be +started by calling {@link android.content.Context#startService startService()}, which allows the +service to run indefinitely, and also allow a client to bind to the service by calling {@link +android.content.Context#bindService bindService()}. + <p>If you do allow your service to be started and bound, then when the service has been +started, the system does <em>not</em> destroy the service when all clients unbind. Instead, you must +explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}.</p> + +<p>Although you should usually implement either {@link android.app.Service#onBind onBind()} +<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to +implement both. For example, a music player might find it useful to allow its service to run +indefinitely and also provide binding. This way, an activity can start the service to play some +music and the music continues to play even if the user leaves the application. Then, when the user +returns to the application, the activity can bind to the service to regain control of playback.</p> + +<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound +Service</a>, for more information about the service lifecycle when adding binding to a +started service.</p> +</div> +</div> + +<p>A client can bind to the service by calling {@link android.content.Context#bindService +bindService()}. When it does, it must provide an implementation of {@link +android.content.ServiceConnection}, which monitors the connection with the service. The {@link +android.content.Context#bindService bindService()} method returns immediately without a value, but +when the Android system creates the connection between the +client and service, it calls {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link +android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that +the client can use to communicate with the service.</p> + +<p>Multiple clients can connect to the service at once. However, the system calls your service's +{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only +when the first client binds. The system then delivers the same {@link android.os.IBinder} to any +additional clients that bind, without calling {@link android.app.Service#onBind onBind()} again.</p> + +<p>When the last client unbinds from the service, the system destroys the service (unless the +service was also started by {@link android.content.Context#startService startService()}).</p> + +<p>When you implement your bound service, the most important part is defining the interface +that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few +different ways you can define your service's {@link android.os.IBinder} interface and the following +section discusses each technique.</p> + + + +<h2 id="Creating">Creating a Bound Service</h2> + +<p>When creating a service that provides binding, you must provide an {@link android.os.IBinder} +that provides the programming interface that clients can use to interact with the service. There +are three ways you can define the interface:</p> + +<dl> + <dt><a href="#Binder">Extending the Binder class</a></dt> + <dd>If your service is private to your own application and runs in the same process as the client +(which is common), you should create your interface by extending the {@link android.os.Binder} class +and returning an instance of it from +{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and +can use it to directly access public methods available in either the {@link android.os.Binder} +implementation or even the {@link android.app.Service}. + <p>This is the preferred technique when your service is merely a background worker for your own +application. The only reason you would not create your interface this way is because +your service is used by other applications or across separate processes.</dd> + + <dt><a href="#Messenger">Using a Messenger</a></dt> + <dd>If you need your interface to work across different processes, you can create +an interface for the service with a {@link android.os.Messenger}. In this manner, the service +defines a {@link android.os.Handler} that responds to different types of {@link +android.os.Message} objects. This {@link android.os.Handler} +is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder} +with the client, allowing the client to send commands to the service using {@link +android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of +its own so the service can send messages back. + <p>This is the simplest way to perform interprocess communication (IPC), because the {@link +android.os.Messenger} queues all requests into a single thread so that you don't have to design +your service to be thread-safe.</p> + </dd> + + <dt>Using AIDL</dt> + <dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into +primitives that the operating system can understand and marshall them across processes to perform +IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as +its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of +all the client requests in a single thread, so the service receives requests one at a time. If, +however, you want your service to handle multiple requests simultaneously, then you can use AIDL +directly. In this case, your service must be capable of multi-threading and be built thread-safe. + <p>To use AIDL directly, you must +create an {@code .aidl} file that defines the programming interface. The Android SDK tools use +this file to generate an abstract class that implements the interface and handles IPC, which you +can then extend within your service.</p> + </dd> +</dl> + + <p class="note"><strong>Note:</strong> Most applications <strong>should not</strong> use AIDL to +create a bound service, because it may require multithreading capabilities and +can result in a more complicated implementation. As such, AIDL is not suitable for most applications +and this document does not discuss how to use it for your service. If you're certain that you need +to use AIDL directly, see the <a href="{@docRoot}tools/aidl.html">AIDL</a> +document.</p> + + + + +<h3 id="Binder">Extending the Binder class</h3> + +<p>If your service is used only by the local application and does not need to work across processes, +then you can implement your own {@link android.os.Binder} class that provides your client direct +access to public methods in the service.</p> + +<p class="note"><strong>Note:</strong> This works only if the client and service are in the same +application and process, which is most common. For example, this would work well for a music +application that needs to bind an activity to its own service that's playing music in the +background.</p> + +<p>Here's how to set it up:</p> +<ol> + <li>In your service, create an instance of {@link android.os.Binder} that either: + <ul> + <li>contains public methods that the client can call</li> + <li>returns the current {@link android.app.Service} instance, which has public methods the +client can call</li> + <li>or, returns an instance of another class hosted by the service with public methods the +client can call</li> + </ul> + <li>Return this instance of {@link android.os.Binder} from the {@link +android.app.Service#onBind onBind()} callback method.</li> + <li>In the client, receive the {@link android.os.Binder} from the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method and +make calls to the bound service using the methods provided.</li> +</ol> + +<p class="note"><strong>Note:</strong> The reason the service and client must be in the same +application is so the client can cast the returned object and properly call its APIs. The service +and client must also be in the same process, because this technique does not perform any +marshalling across processes.</p> + +<p>For example, here's a service that provides clients access to methods in the service through +a {@link android.os.Binder} implementation:</p> + +<pre> +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 mBinder; + } + + /** method for clients */ + public int getRandomNumber() { + return mGenerator.nextInt(100); + } +} +</pre> + +<p>The {@code LocalBinder} provides the {@code getService()} method for clients to retrieve the +current instance of {@code LocalService}. This allows clients to call public methods in the +service. For example, clients can call {@code getRandomNumber()} from the service.</p> + +<p>Here's an activity that binds to {@code LocalService} and calls {@code getRandomNumber()} +when a button is clicked:</p> + +<pre> +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, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + 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 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(); + } + } + + /** Defines callbacks for service binding, passed to bindService() */ + 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; + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mBound = false; + } + }; +} +</pre> + +<p>The above sample shows how the client binds to the service using an implementation of +{@link android.content.ServiceConnection} and the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. The next +section provides more information about this process of binding to the service.</p> + +<p class="note"><strong>Note:</strong> The example above doesn't explicitly unbind from the service, +but all clients should unbind at an appropriate time (such as when the activity pauses).</p> + +<p>For more sample code, see the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code +LocalService.java}</a> class and the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code +LocalServiceActivities.java}</a> class in <a +href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> + + + + + +<h3 id="Messenger">Using a Messenger</h3> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h4>Compared to AIDL</h4> + <p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is +simpler than implementing it with AIDL, because {@link android.os.Messenger} queues +all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the +service, which must then handle multi-threading.</p> + <p>For most applications, the service doesn't need to perform multi-threading, so using a {@link +android.os.Messenger} allows the service to handle one call at a time. If it's important +that your service be multi-threaded, then you should use <a +href="{@docRoot}tools/aidl.html">AIDL</a> to define your interface.</p> +</div> +</div> + +<p>If you need your service to communicate with remote processes, then you can use a +{@link android.os.Messenger} to provide the interface for your service. This technique allows +you to perform interprocess communication (IPC) without the need to use AIDL.</p> + +<p>Here's a summary of how to use a {@link android.os.Messenger}:</p> + +<ul> + <li>The service implements a {@link android.os.Handler} that receives a callback for each +call from a client.</li> + <li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object +(which is a reference to the {@link android.os.Handler}).</li> + <li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service +returns to clients from {@link android.app.Service#onBind onBind()}.</li> + <li>Clients use the {@link android.os.IBinder} to instantiate the {@link android.os.Messenger} +(that references the service's {@link android.os.Handler}), which the client uses to send +{@link android.os.Message} objects to the service.</li> + <li>The service receives each {@link android.os.Message} in its {@link +android.os.Handler}—specifically, in the {@link android.os.Handler#handleMessage +handleMessage()} method.</li> +</ul> + + +<p>In this way, there are no "methods" for the client to call on the service. Instead, the +client delivers "messages" ({@link android.os.Message} objects) that the service receives in +its {@link android.os.Handler}.</p> + +<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p> + +<pre> +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. + */ + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SAY_HELLO: + Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Target we publish for clients to send messages to IncomingHandler. + */ + final Messenger mMessenger = new Messenger(new IncomingHandler()); + + /** + * 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(); + return mMessenger.getBinder(); + } +} +</pre> + +<p>Notice that the {@link android.os.Handler#handleMessage handleMessage()} method in the +{@link android.os.Handler} is where the service receives the incoming {@link android.os.Message} +and decides what to do, based on the {@link android.os.Message#what} member.</p> + +<p>All that a client needs to do is create a {@link android.os.Messenger} based on the {@link +android.os.IBinder} returned by the service and send a message using {@link +android.os.Messenger#send send()}. For example, here's a simple activity that binds to the +service and delivers the {@code MSG_SAY_HELLO} message to the service:</p> + +<pre> +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 mBound; + + /** + * 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); + mBound = 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; + mBound = false; + } + }; + + public void sayHello(View v) { + if (!mBound) 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 (mBound) { + unbindService(mConnection); + mBound = false; + } + } +} +</pre> + +<p>Notice that this example does not show how the service can respond to the client. If you want the +service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then +when the client receives the {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes +the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter +of the {@link android.os.Messenger#send send()} method.</p> + +<p>You can see an example of how to provide two-way messaging in the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code +MessengerService.java}</a> (service) and <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code +MessengerServiceActivities.java}</a> (client) samples.</p> + + + + + +<h2 id="Binding">Binding to a Service</h2> + +<p>Application components (clients) can bind to a service by calling +{@link android.content.Context#bindService bindService()}. The Android +system then calls the service's {@link android.app.Service#onBind +onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.</p> + +<p>The binding is asynchronous. {@link android.content.Context#bindService +bindService()} returns immediately and does <em>not</em> return the {@link android.os.IBinder} to +the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link +android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService +bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the +system calls to deliver the {@link android.os.IBinder}.</p> + +<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind +to a service—you <strong>cannot</strong> bind to a service from a broadcast receiver.</p> + +<p>So, to bind to a service from your client, you must: </p> +<ol> + <li>Implement {@link android.content.ServiceConnection}. + <p>Your implementation must override two callback methods:</p> + <dl> + <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt> + <dd>The system calls this to deliver the {@link android.os.IBinder} returned by +the service's {@link android.app.Service#onBind onBind()} method.</dd> + <dt>{@link android.content.ServiceConnection#onServiceDisconnected +onServiceDisconnected()}</dt> + <dd>The Android system calls this when the connection to the service is unexpectedly +lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the +client unbinds.</dd> + </dl> + </li> + <li>Call {@link +android.content.Context#bindService bindService()}, passing the {@link +android.content.ServiceConnection} implementation. </li> + <li>When the system calls your {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} callback method, you can begin making calls to the service, using +the methods defined by the interface.</li> + <li>To disconnect from the service, call {@link +android.content.Context#unbindService unbindService()}. + <p>When your client is destroyed, it will unbind from the service, but you should always unbind +when you're done interacting with the service or when your activity pauses so that the service can +shutdown while its not being used. (Appropriate times to bind and unbind is discussed +more below.)</p> + </li> +</ol> + +<p>For example, the following snippet connects the client to the service created above by +<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned +{@link android.os.IBinder} to the {@code LocalService} class and request the {@code +LocalService} instance:</p> + +<pre> +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; + } +}; +</pre> + +<p>With this {@link android.content.ServiceConnection}, the client can bind to a service by passing +this it to {@link android.content.Context#bindService bindService()}. For example:</p> + +<pre> +Intent intent = new Intent(this, LocalService.class); +bindService(intent, mConnection, Context.BIND_AUTO_CREATE); +</pre> + +<ul> + <li>The first parameter of {@link android.content.Context#bindService bindService()} is an +{@link android.content.Intent} that explicitly names the service to bind (thought the intent +could be implicit).</li> +<li>The second parameter is the {@link android.content.ServiceConnection} object.</li> +<li>The third parameter is a flag indicating options for the binding. It should usually be {@link +android.content.Context#BIND_AUTO_CREATE} in order to create the service if its not already alive. +Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND} +and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li> +</ul> + + +<h3>Additional notes</h3> + +<p>Here are some important notes about binding to a service:</p> +<ul> + <li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown +when the connection has broken. This is the only exception thrown by remote methods.</li> + <li>Objects are reference counted across processes. </li> + <li>You should usually pair the binding and unbinding during +matching bring-up and tear-down moments of the client's lifecycle. For example: + <ul> + <li>If you only need to interact with the service while your activity is visible, you +should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link +android.app.Activity#onStop onStop()}.</li> + <li>If you want your activity to receive responses even while it is stopped in the +background, then you can bind during {@link android.app.Activity#onCreate onCreate()} and unbind +during {@link android.app.Activity#onDestroy onDestroy()}. Beware that this implies that your +activity needs to use the service the entire time it's running (even in the background), so if +the service is in another process, then you increase the weight of the process and it becomes +more likely that the system will kill it.</li> + </ul> + <p class="note"><strong>Note:</strong> You should usually <strong>not</strong> bind and unbind +during your activity's {@link android.app.Activity#onResume onResume()} and {@link +android.app.Activity#onPause onPause()}, because these callbacks occur at every lifecycle transition +and you should keep the processing that occurs at these transitions to a minimum. Also, if +multiple activities in your application bind to the same service and there is a transition between +two of those activities, the service may be destroyed and recreated as the current activity unbinds +(during pause) before the next one binds (during resume). (This activity transition for how +activities coordinate their lifecycles is described in the <a +href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Activities</a> +document.)</p> +</ul> + +<p>For more sample code, showing how to bind to a service, see the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code +RemoteService.java}</a> class in <a +href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> + + + + + +<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2> + +<div class="figure" style="width:588px"> +<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started +and also allows binding.</p> +</div> + +<p>When a service is unbound from all clients, the Android system destroys it (unless it was also +started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have +to manage the lifecycle of your service if it's purely a bound +service—the Android system manages it for you based on whether it is bound to any clients.</p> + +<p>However, if you choose to implement the {@link android.app.Service#onStartCommand +onStartCommand()} callback method, then you must explicitly stop the service, because the +service is now considered to be <em>started</em>. In this case, the service runs until the service +stops itself with {@link android.app.Service#stopSelf()} or another component calls {@link +android.content.Context#stopService stopService()}, regardless of whether it is bound to any +clients.</p> + +<p>Additionally, if your service is started and accepts binding, then when the system calls +your {@link android.app.Service#onUnbind onUnbind()} method, you can optionally return +{@code true} if you would like to receive a call to {@link android.app.Service#onRebind +onRebind()} the next time a client binds to the service (instead of receiving a call to {@link +android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind +onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its +{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. +Below, figure 1 illustrates the logic for this kind of lifecycle.</p> + +<p>For more information about the lifecycle of an started service, see the <a +href="{@docRoot}guide/components/services.html#Lifecycle">Services</a> document.</p> + + + + |