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.
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 Services 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.
A bound service is an implementation of the Service
class that allows
other applications to bind to it and interact with it. To provide binding for a
service, you must implement the onBind()
callback method. This
method returns an IBinder
object that defines the programming interface that
clients can use to interact with the service.
As discussed in the Services
document, you can create a service that is both started and bound. That is, the service can be
started by calling startService()
, which allows the
service to run indefinitely, and also allow a client to bind to the service by calling bindService()
.
If you do allow your service to be started and bound, then when the service has been
started, the system does not destroy the service when all clients unbind. Instead, you must
explicitly stop the service, by calling stopSelf()
or stopService()
.
Although you should usually implement either onBind()
or 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.
Be sure to read the section about Managing the Lifecycle of a Bound Service, for more information about the service lifecycle when adding binding to a started service.
A client can bind to the service by calling bindService()
. When it does, it must provide an implementation of ServiceConnection
, which monitors the connection with the service. The bindService()
method returns immediately without a value, but
when the Android system creates the connection between the
client and service, it calls onServiceConnected()
on the ServiceConnection
, to deliver the IBinder
that
the client can use to communicate with the service.
Multiple clients can connect to the service at once. However, the system calls your service's
onBind()
method to retrieve the IBinder
only
when the first client binds. The system then delivers the same IBinder
to any
additional clients that bind, without calling onBind()
again.
When the last client unbinds from the service, the system destroys the service (unless the
service was also started by startService()
).
When you implement your bound service, the most important part is defining the interface
that your onBind()
callback method returns. There are a few
different ways you can define your service's IBinder
interface and the following
section discusses each technique.
When creating a service that provides binding, you must provide an IBinder
that provides the programming interface that clients can use to interact with the service. There
are three ways you can define the interface:
Binder
class
and returning an instance of it from
onBind()
. The client receives the Binder
and
can use it to directly access public methods available in either the Binder
implementation or even the Service
.
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.
Messenger
. In this manner, the service
defines a Handler
that responds to different types of Message
objects. This Handler
is the basis for a Messenger
that can then share an IBinder
with the client, allowing the client to send commands to the service using Message
objects. Additionally, the client can define a Messenger
of
its own so the service can send messages back.
This is the simplest way to perform interprocess communication (IPC), because the Messenger
queues all requests into a single thread so that you don't have to design
your service to be thread-safe.
Messenger
, is actually based on AIDL as
its underlying structure. As mentioned above, the 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.
To use AIDL directly, you must
create an .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.
Note: Most applications should not 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 AIDL document.
If your service is used only by the local application and does not need to work across processes,
then you can implement your own Binder
class that provides your client direct
access to public methods in the service.
Note: 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.
Here's how to set it up:
Binder
that either:
Service
instance, which has public methods the
client can callBinder
from the onBind()
callback method.Binder
from the onServiceConnected()
callback method and
make calls to the bound service using the methods provided.Note: 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.
For example, here's a service that provides clients access to methods in the service through
a Binder
implementation:
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); } }
The LocalBinder
provides the getService()
method for clients to retrieve the
current instance of LocalService
. This allows clients to call public methods in the
service. For example, clients can call getRandomNumber()
from the service.
Here's an activity that binds to LocalService
and calls getRandomNumber()
when a button is clicked:
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; } }; }
The above sample shows how the client binds to the service using an implementation of
ServiceConnection
and the onServiceConnected()
callback. The next
section provides more information about this process of binding to the service.
Note: 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).
For more sample code, see the LocalService.java
class and the LocalServiceActivities.java
class in ApiDemos.
When you need to perform IPC, using a Messenger
for your interface is
simpler than implementing it with AIDL, because Messenger
queues
all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the
service, which must then handle multi-threading.
For most applications, the service doesn't need to perform multi-threading, so using a 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 AIDL to define your interface.
If you need your service to communicate with remote processes, then you can use a
Messenger
to provide the interface for your service. This technique allows
you to perform interprocess communication (IPC) without the need to use AIDL.
Here's a summary of how to use a Messenger
:
Handler
that receives a callback for each
call from a client.Handler
is used to create a Messenger
object
(which is a reference to the Handler
).Messenger
creates an IBinder
that the service
returns to clients from onBind()
.IBinder
to instantiate the Messenger
(that references the service's Handler
), which the client uses to send
Message
objects to the service.Message
in its Handler
—specifically, in the handleMessage()
method.In this way, there are no "methods" for the client to call on the service. Instead, the
client delivers "messages" (Message
objects) that the service receives in
its Handler
.
Here's a simple example service that uses a Messenger
interface:
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(); } }
Notice that the handleMessage()
method in the
Handler
is where the service receives the incoming Message
and decides what to do, based on the what
member.
All that a client needs to do is create a Messenger
based on the IBinder
returned by the service and send a message using send()
. For example, here's a simple activity that binds to the
service and delivers the MSG_SAY_HELLO
message to the service:
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; } } }
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 Messenger
in the client. Then
when the client receives the onServiceConnected()
callback, it sends a Message
to the service that includes
the client's Messenger
in the replyTo
parameter
of the send()
method.
You can see an example of how to provide two-way messaging in the MessengerService.java
(service) and MessengerServiceActivities.java
(client) samples.
Application components (clients) can bind to a service by calling
bindService()
. The Android
system then calls the service's onBind()
method, which returns an IBinder
for interacting with the service.
The binding is asynchronous. bindService()
returns immediately and does not return the IBinder
to
the client. To receive the IBinder
, the client must create an instance of ServiceConnection
and pass it to bindService()
. The ServiceConnection
includes a callback method that the
system calls to deliver the IBinder
.
Note: Only activities, services, and content providers can bind to a service—you cannot bind to a service from a broadcast receiver.
So, to bind to a service from your client, you must:
ServiceConnection
.
Your implementation must override two callback methods:
onServiceConnected()
IBinder
returned by
the service's onBind()
method.onServiceDisconnected()
bindService()
, passing the ServiceConnection
implementation. onServiceConnected()
callback method, you can begin making calls to the service, using
the methods defined by the interface.unbindService()
.
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.)
For example, the following snippet connects the client to the service created above by
extending the Binder class, so all it must do is cast the returned
IBinder
to the LocalService
class and request the LocalService
instance:
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; } };
With this ServiceConnection
, the client can bind to a service by passing
this it to bindService()
. For example:
Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
bindService()
is an
Intent
that explicitly names the service to bind (thought the intent
could be implicit).ServiceConnection
object.BIND_AUTO_CREATE
in order to create the service if its not already alive.
Other possible values are BIND_DEBUG_UNBIND
and BIND_NOT_FOREGROUND
, or 0
for none.Here are some important notes about binding to a service:
DeadObjectException
exceptions, which are thrown
when the connection has broken. This is the only exception thrown by remote methods.onStart()
and unbind during onStop()
.onCreate()
and unbind
during 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.Note: You should usually not bind and unbind
during your activity's onResume()
and 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 Activities
document.)
For more sample code, showing how to bind to a service, see the RemoteService.java
class in ApiDemos.
When a service is unbound from all clients, the Android system destroys it (unless it was also
started with 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.
However, if you choose to implement the onStartCommand()
callback method, then you must explicitly stop the service, because the
service is now considered to be started. In this case, the service runs until the service
stops itself with stopSelf()
or another component calls stopService()
, regardless of whether it is bound to any
clients.
Additionally, if your service is started and accepts binding, then when the system calls
your onUnbind()
method, you can optionally return
true
if you would like to receive a call to onRebind()
the next time a client binds to the service (instead of receiving a call to onBind()
). onRebind()
returns void, but the client still receives the IBinder
in its
onServiceConnected()
callback.
Below, figure 1 illustrates the logic for this kind of lifecycle.
For more information about the lifecycle of an started service, see the Services document.