cb0b2df114
Change-Id: I11b1d524dd2159b58c65d3ef7a76af15624ae365
676 lines
31 KiB
Plaintext
676 lines
31 KiB
Plaintext
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}guide/components/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}guide/components/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>
|
|
|
|
<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>
|
|
|
|
|
|
<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>
|
|
|
|
|
|
<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>
|
|
|
|
|
|
|
|
|