Bound Services邦定服务html
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.
邦定服务是一个在客户端服务接口的服务.一个邦定的服务容许组件邦定到服务,发送请求,接收响应,和事件执行进程间通讯(IPC).一个邦定的服务只有当他服务于其余组件时才存在(live),而且不会无限在后台运行。
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.
这个文档告诉你怎样建立一个邦定的服务,包括怎么把其余应用组件邦定到服务。可是关于服务的其余信息,好比怎么从服务传送一个通知器,将服务设置在前台运行等等,你应该参考
Services文档.
The Basics基础
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.
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.
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:
当建立一个带有邦定的服务时,你必须提供一个
IBinder
,
它是一个编程接口,客户端用它来与服务通讯。定义该接口的方法有三种:
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
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.
当你的服务仅仅只用于作为你的应用的后台工做者,这将是首先选择的技术。你不这样建立你的接口的惟一缘由是:你的服务用于其余应用或者要跨进程通讯
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 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队列的全部请求,都在一个单一的线程中,因此你没必要去为你的服务设置线程安全.
Using AIDL使用AIDL(Android接口定义语言)
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, 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.
AIDL执行全部的工做,把对象分解成操做系统能理解的原语,并把它们编组以跨进程通讯。前面提到的使用
Messenger的技术,其实是基于AIDL作为它的底层架构的。就上面所提到的,
Messenger在一个线程中,为他的客户端全部的请求建立一个队列,因此服务一次只能接收一个请求。然而,若是你想要你的服务同时处理多个服务,那么你能够直接使用AIDL.这样的话,你的服务必须能同时处理多线程而且被设计成多线程安全的。
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.
要直接使用AIDL,你必须建立一个.aidl的文件,这个文件定义了编程接口。Android SDK使用这个文件产生一个实现此接口的抽象类,而且处理IPC,而后在你的服务中继承这个类.
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.
注意:大多数应用应该不要使用AIDL建立邦定服务,由于它可能须要多线程能力,而且致使更多复杂的实现。所以,AIDL不适合大多数应用,而且这个文档不讨论为你的服务怎样使用它。若是你肯定你须要直接使用AIDL,请看AIDL文档.
Extending the Binder class继承Binder类
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.
若是你的服务只用于局部的应用,而且不须要跨进程工做,那么你能够实现本身的Binder类,它为你的客户端提供直接访问服务的公共方法
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.
注意:继承Binder类,只工做于:假设你的客户端和服务端都在同一个应用和进程中,这也是最多见的状况.好比,一个音乐应用须要邦定一个活动到它本身的后台音乐播放服务,它将工做得很好。
Here's how to set it up:这里是如何设置它:
- In your service, create an instance of Binder that either: 在你的服务里,建立下面之一的Binder实例:
- contains public methods that the client can call包括一个客户端调用的公共方法
- returns the current Service instance, which has public methods the client can call返回当前Service实例,它有客户端能够调用的公共方法
- or, returns an instance of another class hosted by the service with public methods the client can call返回一个service持有的类的实例,它带有一个客户端可调用的公共方法
- Return this instance of Binder from the onBind() callback method.从onBind()回调方法返回Binder的this实例.
- In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided.在客户端,接收来自onServiceConnected()回调的Binder,而且用它提供的方法产生对service的调用.
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.
注意:客户端和服务必须在同一个应用的缘由是,客户端能够对返回的对象进行类型转换而且适当的调用它的APIs.这个服务和客户端也必须在同一个进程,缘由是这个技术不能执行任何编组跨进程.
For example, here's a service that provides clients access to methods in the service through a
Binder implementation:
好比,这个服务,它经过实现
Binder,为客户端提供了访问服务中的方法。
publicclassLocalServiceextendsService{
// Binder given to clients给客户端的Binders
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.用于客户端的类,由于咱们知道这个服务老是与它的客户端运行在同一个进程中的,因此咱们不须要处理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.
LocalBinder提供一个方法,给用户取回LocalService的实例.这容许全部的客户调用这个服务的公共方法。好比,客户端能够调用服务的getRandomNumber()
Here's an activity that binds to
LocalService
and calls
getRandomNumber()
when a button is clicked:下面是一个邦定到
LocalService的活动,而且当按一个按钮时,调用getRandomNumber()方法
publicclassBindingActivityextendsActivity{
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)
*当一个按钮被点击时,被调用这个按钮在布局文件用经过android:onClick属性加入进来的
*/
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()
定义一service binding的回调方法,传递给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咱们已经邦定到LocalService,转换IBinder而且,获取LocalService实例
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).
注意.上面的例子没有显示的从服务解除邦定,可是全部的客户端应在适当的时候解除邦定(好比活动中止)
Using a Messenger使用信使
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.
若是你的服务要与远程过程进行通讯,那你能够为你的服务提供一个
Messenger接口。这一技术能让你在没有AIDL的状况下执行进程间通讯.
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.
经过这种方式,在服务端不须要调用客户端的”方法methods”,而是,而客户端传递”消息”,服务端在它的
Handler中接收该消息.
publicclassMessengerServiceextendsService{
/** 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
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.当邦定到服务,咱们返回一个接口到咱们的messenger.用于发送消息到服务
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
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:
publicclassActivityMessengerextendsActivity{
/** Messenger for communicating with the service. 与服务通讯的Messenger*/
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. 标志,表示是否咱们对Service调用bind*/
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.
//当与服务创建了联接,给予咱们与服务进行交互的对象时,这个方法被调用,咱们使用一个Messenger与服务通讯,因此这里咱们获得一个来自raw IBinder对象的客户端的reprentation
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使用支持的’what’值,建立并发送一个消息给服务
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.
Binding to a Service邦定到服务s
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.应用组件能够调用
bindService()方法邦定到服务,Android系统而后调用服务的
onBind()方法,该方法返回一个用于与服务交互的
IBinder
Note: Only activities, services, and content providers can bind to a service—you
cannot注意只有活动,服务和内容提供者能邦定到一个服务,一个broadcast接收者,不能邦一到服务 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:实现中必需要复写的两个方法
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 the ServiceConnection implementation. 调用bindService()方法,传递ServiceConnection的实现
- When the system calls your onServiceConnected() callback method, you can begin making calls to the service, using the methods defined by the interface.当系统调用你的onServiceConnected()回访方法时,你可使用由接口定义的方法,对服务发起一个调用.
- To disconnect from the service, call unbindService(). 要从服务解除联接,调用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;
}
};
Intent intent =newIntent(this,LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Additional notes附加注意事项
Here are some important notes about binding to a service:下面是邦定到一个服务的一些重要注意的事项.
- You should always trap DeadObjectException exceptions, which are thrown when the connection has broken. This is the only exception thrown by remote methods.你应该老是处理(trap)DeadObjectException异常.当联接崩溃时,惟一由远程方法抛出的异常
- 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 during onStop().若是只有当你的活动可见时才须要与服务交互,那么你应该在方法中邦定,在方法中解除邦定
- If you want your activity to receive responses even while it is stopped in the background, then you can bind during 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.若是你但愿你的活动,即便中止在后台,也能接收响应,那么你能够在方法中邦定,在方法中销毁。注意,这意味着,在你的活动的整个运行时间都要使用服务(即便是活动在后台),因此若是服务在其余的进程中,那么你可能增长你服务的比重(weight),而且它可能变得极有可能被杀掉.
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.)
注意:你不该常常在
onResume()方法和
onPause()方法中邦定和解除邦定.所以这些回调方法常常在活动的生命周期转换时调用,而且你应保持这些转换使用的时间最少化.还有,若是在你的应用中有多个活动,邦定到这一个服务上,并在某两个活动之间有转换,该服务可能在当前活动解除邦定,下一个邦定前,销毁并重建立了。(活动是怎样在转换中定位生命周期,在
Activities文档中描述)
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.
当一个服务从全部客户端解除邦定,Android系统销毁它(除非它也是用
onStartCommand()方法启动的)。所以,若是你的服务纯粹是一个邦定服务,你不须要管理它的生命周期---系统根据它是否邦定到任何客户端来管理它的生命周期.
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.关于启动服务的生命周期更多信息,看
Services文档