Bound Services邦定服务

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.
一个邦定的服务是Service类的实现,允许其他应用邦定到它,并与他交互。给服务提供邦定,你必须实现onBind()回调方法。这个方法返回一个IBinder对象,它定义了编程接口,客户端使用这个接口来与服务交互。
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.
一个客户端可以调用bindService()方法邦定到服务。当调用此方法时,它需要提供一个ServiceConnection的实现,这个实现监视它与服务的联接。这个bindService()方法立即返回,不带返回值,但是当Android系统在客户端与服务之间创建联接时,它调用onServiceConnected()方法(on the ServiceConnection),传递IBinder,客户端可以用它与服务通信.
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.
多个客户端可以同时联接到该服务。但时,只有当第一个客户邦定时,系统调用你的服务的onBind()方法,取回IBinder.系统然后传递同一个IBinder给任何其他邦定到它的客户端,不再调用onBind()方法。
When the last client unbinds from the service, the system destroys the service (unless the service was also started by startService()).
当最后一个客户端松邦后,系统销毁该服务(除非该服务也由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.
当你实现你的邦定服务时,最重要的一部分是实现onBind()方法返回的接口.定义服务的IBinder接口的方法有好几种,下面将讨论每一种技术.
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,它是一个编程接口,客户端用它来与服务通信。定义该接口的方法有三种:
Extending the Binder class继续Bider类
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.
如果你的服务是属于你应用私有的并且与客户端运行在同一个进程(通常是这样的),你应该继承Binder类来创建你的接口,并从onBind()方法返回一个实例。客户端接收到,并用它来直接访问Binder实现的公共方法或者该服务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.
当你的服务仅仅只用于做为你的应用的后台工作者,这将是首先选择的技术。你不这样创建你的接口的唯一原因是:你的服务用于其他应用或者要跨进程通信
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 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.
如果你的接口,需要工作于不同的进程,你可以为你的服务创建一个带信Messenger使的接口。通过这种方式,服务可以定义一个响应不同Message对象的处理器Handler.这个Handler是Messenger的基础,它可以与客户端共享一个IBinder,允许用户用Message对象向服务发送命令。另外,客户端可以定义它自己的Messenger,这样服务可以把消息发回给客户端。
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:这里是如何设置它:
  1. 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持有的类的实例,它带有一个客户端可调用的公共方法
  2. Return this instance of Binder from the onBind() callback method.从onBind()回调方法返回Binder的this实例.
  3. 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
随机数产生器
用于客户端的类,因为我们知道这个服务总是与它的客户端运行在同一个进程中的,所以我们不需要处理IPC
返回这个实例的本地服务,以便客户端可以调用本地方法

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{

 

      *当一个按钮被点击时,被调用这个按钮在布局文件用通过android:onClick属性加入进来的

 

*/
从本地服务调用一个方法
但是,若这个调用被挂起,那么 为了避免降低活动的性能,应该在一个单独的线程中调用

 

 

 

定义一service binding的回调方法,传递给bindService()*/
我们已经邦定到LocalService,转换IBinder并且,获取LocalService实例

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.
上面的例子,已经展示了客户端通过实现ServiceConnection的实例和onServiceConnected()方法的回调.,邦定到服务的。下面将给出更多关于这个邦定到服务过程的详细信息
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.
更多的样例代码,请看在ApiDemos中的LocalService.java和
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的情况下执行进程间通信.
Here's a summary of how to use a Messenger:下面是使用Messenger的总结.
  • The service implements a Handler that receives a callback for each call from a client.服务实现一个Handler,用于接收来自某个客户端的每个回调
  • The Handler is used to create a Messenger object (which is a reference to the Handler).该Handler常用于创建一个Messenger对象(它是Handler的引用)
  • The Messenger creates an IBinder that the service returns to clients from onBind().该Messenger创建一个IBinder,服务从onBind().方法返回它给客户端.
  • Clients use the IBinder to instantiate the Messenger (that references the service's Handler), which the client uses to send Message objects to the service.客户端用IBinder实例化Messenger(它是服务的Handler引用),客户端用它来发送Message对象给服务.
  • The service receives each Message in its Handler—specifically, in the handleMessage() method.服务在Handler接收它的每个Message—具体是在handleMessage()方法中.
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中接收该消息.
Here's a simple example service that uses a Messenger interface:这里是一个使用Messenger接口的简单例子.

 

publicclassMessengerServiceextendsService{
/** Command to the service to display a message给服务显示一个消息的命令 */
处理来自客户端的信息
接到这个消息,显示一个Toast
当邦定到服务,我们返回一个接口到我们的messenger.用于发送消息到服务

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.
注意,在Handler中的handleMessage()方法,是服务接收发来的Message的地方,并根据what成员,决定做什么.
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:
客户端所要做的是创建一个由服务返回的,基于IBinder的Messenger.并使用send()发送消息,比如,这是一个简单的活动,它邦定到服务,并传MSG_SAY_HELLO递消息到服务.

 

publicclassActivityMessengerextendsActivity{
/** Messenger for communicating with the service. 与服务通信的Messenger*/
标志,表示是否我们对Service调用bind*/
与服务主接口通信的类

 

            //当与服务建立了联接,给予我们与服务进行交互的对象时,这个方法被调用,我们使用一个Messenger与服务通信,所以这里我们得到一个来自raw IBinder对象的客户端的reprentation
当与服务的联接,出现意外的断联—意思,它的进程崩溃。.
使用支持的’what’值,创建并发送一个消息给服务

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.
注意,这个例子没有展示服务是怎样响应客户端。如果你想要服务响应客户端,那你还需要在客户端创建一个Messenger,然后当客户端接收到onServiceConnected()调用时,它发送一个Message给服务端,它包括客户端的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) (service) and MessengerServiceActivities.java (client) samples.
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
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.
该邦定是异步的,bindService()方法立即返回,并不返回IBinder给客户端.为了接收IBinder,客户端必须创建成一个IBinder的实例,并把它传给bindService()方法.这个ServiceConnection包括一个回调方法,系统调用它传递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: 所以从你的客户端邦定到服务必须是:
  1. Implement ServiceConnection. 实现服务联接
Your implementation must override two callback methods:实现中必须要复写的两个方法
onServiceConnected()
The system calls this to deliver the IBinder returned by the service's onBind() method.系统调用它,传递由服务onBind()方法返回的IBinder
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.
  1. Call bindService(), passing the ServiceConnection implementation. 调用bindService()方法,传递ServiceConnection的实现
  2. When the system calls your onServiceConnected() callback method, you can begin making calls to the service, using the methods defined by the interface.当系统调用你的onServiceConnected()回访方法时,你可以使用由接口定义的方法,对服务发起一个调用.
  3. 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:
比如,下面的小片断是通过继承上面的extending the Binder class类,联接一个客户端到服务。所以它所必须要做的是转换返回的IBinder类型,为LocalService类,并请求一个LocalService实例.

 

LocalService mService;

With this ServiceConnection, the client can bind to a service by passing this it to bindService(). For example:通过这个ServiceConnection,客户端可以传递它到bindService(),邦定到服务.

 

Intent intent =newIntent(this,LocalService.class);

bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

  • The first parameter of bindService() is an Intent that explicitly names the service to bind (thought the intent could be implicit). bindService()方法的第一个参数,是一个Intent,它是邦定到服务的显式名字(但这个意图也可以是隐式的)
  • The second parameter is the ServiceConnection object.第二个参数是ServiceConnection对象.
  • The third parameter is a flag indicating options for the binding. It should usually be 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.第三个参数是邦定标记选项,BIND_AUTO_CREATE它通常指示如果它的服务不存活时,可以创建服务.其它可以的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,或0没有参数.
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文档中描述)
For more sample code, showing how to bind to a service, see the RemoteService.java class in ApiDemos.
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.
但是,如果你实现了onStartCommand()回调方法,那么你必须显式的停止服务,因为该服务是经过考虑被开启的。在这种情况下,服务一直运行,除非它调用stopSelf()停止自己,或者其他组件调用stopService()停止它,而不管它是否邦定到客户端无关
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.
另外,如果你的服务已开启并且接收了邦定,如你想客户下次邦定到服务时,接收到onRebind()调用,那么当系统调用你的onUnbind()方法时,你可以选择返回true.(而不是从onBind()接收一个调用)onRebind()方法返回void.但客户端仍在它的回调中onServiceConnected()接收IBinder。下图展示了这种生命周期的逻辑

For more information about the lifecycle of an started service, see the Services document.关于启动服务的生命周期更多信息,看Services文档