Service官方教程(3)Bound Services
Bound Services
1.In this document
Key classes
Samples
See also
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.
2.The Basics
2.1 简介
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.
2.2 Binding to a Started 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.
3.Creating a Bound Service
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:
3.1 Extending the Binder class
- 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
Binderclass and returning an instance of it fromonBind(). The client receives theBinderand can use it to directly access public methods available in either theBinderimplementation or even theService.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.
3.2 Using a Messenger
- If you need your interface to work across different processes, you can create an interface for the service with a
Messenger. In this manner, the service defines aHandlerthat responds to different types ofMessageobjects. ThisHandleris the basis for aMessengerthat can then share anIBinderwith the client, allowing the client to send commands to the service usingMessageobjects. Additionally, the client can define aMessengerof its own so the service can send messages back.This is the simplest way to perform interprocess communication (IPC), because the
Messengerqueues all requests into a single thread so that you don't have to design your service to be thread-safe.
3.3 Using AIDL
- 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
Messenger, is actually based on AIDL as its underlying structure. As mentioned above, theMessengercreates 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
.aidlfile 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.
3.4 Extending the Binder class
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:
- In your service, create an instance of
Binderthat either:- contains public methods that the client can call
- returns the current
Serviceinstance, which has public methods the client can call - or, returns an instance of another class hosted by the service with public methods the client can call
- Return this instance of
Binderfrom theonBind()callback method. - In the client, receive the
Binderfrom theonServiceConnected()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();
}
}
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: In the example above, the onStop() method unbinds the client from the service. Clients should unbind from services at appropriate times, as discussed in Additional Notes.
For more sample code, see the LocalService.java class and the LocalServiceActivities.java class in ApiDemos.
3.5 Using a Messenger
Compared to AIDL
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:
- The service implements a
Handlerthat receives a callback for each call from a client. - The
Handleris used to create aMessengerobject (which is a reference to theHandler). - The
Messengercreates anIBinderthat the service returns to clients fromonBind(). - Clients use the
IBinderto instantiate theMessenger(that references the service'sHandler), which the client uses to sendMessageobjects to the service. - The service receives each
Messagein itsHandler—specifically, in thehandleMessage()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 = ;
/**
* 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, , );
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.
4.Binding to a Service
4.1 简介
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:
- Implement
ServiceConnection.Your implementation must override two callback methods:
onServiceConnected()- The system calls this to deliver the
IBinderreturned by the service'sonBind()method. onServiceDisconnected()- 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 not called when the client unbinds.
- Call
bindService(), passing theServiceConnectionimplementation. - When the system calls your
onServiceConnected()callback method, you can begin making calls to the service, using the methods defined by the interface. - To disconnect from the service, call
unbindService().If your client is still bound to a service when your app destroys the client, destruction causes the client to unbind. It is better practice to unbind the client as soon as it is done interacting with the service. Doing so allows the idle service to shut down. For more information about appropriate times to bind and unbind, see Additional Notes.
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 it to bindService(). For example:
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- The first parameter of
bindService()is anIntentthat explicitly names the service to bind (thought the intent could be implicit). - The second parameter is the
ServiceConnectionobject. - The third parameter is a flag indicating options for the binding. It should usually be
BIND_AUTO_CREATEin order to create the service if its not already alive. Other possible values areBIND_DEBUG_UNBINDandBIND_NOT_FOREGROUND, or0for none.
4.2 Additional notes
Here are some important notes about binding to a service:
- You should always trap
DeadObjectExceptionexceptions, which are thrown when the connection has broken. This is the only exception thrown by remote methods. - Objects are reference counted across processes.
- You should usually pair the binding and unbinding during matching bring-up and tear-down moments of the client's lifecycle. For example:
- If you only need to interact with the service while your activity is visible, you should bind during
onStart()and unbind duringonStop(). - If you want your activity to receive responses even while it is stopped in the background, then you can bind during
onCreate()and unbind duringonDestroy(). 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()andonPause(), 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.) - If you only need to interact with the service while your activity is visible, you should bind during
For more sample code, showing how to bind to a service, see the RemoteService.java class in ApiDemos.
5.Managing the Lifecycle of a Bound Service
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. 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.

Figure 1. The lifecycle for a service that is started and also allows binding.
For more information about the lifecycle of a started service, see the Services document.
Service官方教程(3)Bound Services的更多相关文章
- Service官方教程(6)Bound Services主要用来实现通信服务,以及3种实现通信的方案简介。
1.Bound Services A bound service is the server in a client-server interface. A bound service allows ...
- Service官方教程(11)Bound Service示例之2-AIDL 定义跨进程接口并通信
Android Interface Definition Language (AIDL) 1.In this document Defining an AIDL Interface Create th ...
- Service官方教程(7)Bound Service示例之1-同进程下直接继承Service
Extending the Binder class If your service is used only by the local application and does not need t ...
- Service官方教程(10)Bound Service的生命周期函数
Managing the Lifecycle of a Bound Service When a service is unbound from all clients, the Android sy ...
- Service官方教程(8)Bound Service示例之2-跨进程使用Messenger
Compared to AIDL When you need to perform IPC, using a Messenger for your interface is simpler than ...
- Service官方教程(1)Started与Bound的区别、要实现的函数、声明service
Services 简介和分类 A Service is an application component that can perform long-running operations in the ...
- Service官方教程(9)绑定服务时的注意事项
Binding to a Service Application components (clients) can bind to a service by calling bindService() ...
- Service官方教程(4)两种Service的生命周期函数
Managing the Lifecycle of a Service The lifecycle of a service is much simpler than that of an activ ...
- Service官方教程(2)*IntentService与Service示例、onStartCommand()3个返回值的含义。
1.Creating a Started Service A started service is one that another component starts by calling start ...
随机推荐
- VC++中的int main(int argc, char argv[])是什么意思
这是C/C++的一重要函数,叫主函数.无论程序多复杂,代码中必须有这么一个函数,也只能有一个这样的函数:程序执行时就是从这个函数进入的.由于问得比较笼统,如果你想知道详细情况的话,发给你一个网友的求助 ...
- Find Minimum in Rotated Sorted Array 旋转数组中找最小值 @LeetCode
O(n)的算法就不说了,这题主要考查的是 O(logn)的算法. 有序数组easy想到使用二分查找解决.这题就是在二分基础上做一些调整.数组仅仅有一次翻转,能够知道原有序递增数组被分成两部分,这俩部分 ...
- MySQL基础笔记(三) 复杂查询
所谓复杂查询,指涉及多个表.具有嵌套等复杂结构的查询.这里简要介绍典型的几种复杂查询格式. 一.连接查询 连接是区别关系与非关系系统的最重要的标志.通过连接运算符可以实现多个表查询.连接查询主要包括内 ...
- 添加 XML内Rows数据
public static void addItemToXml(string method,string firstKey,string id,string checkName,string refV ...
- HDU 1824 Let's go home (2-SAT判定)
Let's go home Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 网络知识: 物理层PHY 和 网络层MAC
PHY模块简介 物理层位于OSI最底层,物理层协议定义电气信号.线的状态.时钟要求.数据编码和数据传输用的连接器. 物理层的器件称为PHY. 上图里的灰色方框图里的就是PHY芯片内部模块图. MAC器 ...
- 查看和改动MySQL数据库表存储引擎
要做一名合格的程序猿,除了把代码写的美丽外,熟知数据库方面的知识也是不可或缺的.以下总结一下怎样查看和改动MySQL数据库表存储引擎: 1.查看数据库所能支持的存储引擎: ...
- hdoj-2090-算菜价(水题)
算菜价 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- SVN下Update出现代码文件删除状态问题
有时候在SVN上更新了代码,发觉别人提交的东西,服务上明明就是有,但本机却空空如也.只好打开 "Repo-browser",从服务器上强拉下来.结果图标显示红叉,显示为删除状态. ...
- 2016/04/26 流程 数据库lcdb 四个表 1,用户表users 2,流程表(设定有哪些流程)liucheng 3,流程发起者表(记录谁发起到哪里) 4,流程经过的人员表 flowpath (order排序)
流程: 十一 个页面 1,denglu.php(登录) <!DOCTYPE html> <html lang="en"> <head> ...