绑定服务——Bound Service

本文详细解析了Android中的绑定服务,包括其基本概念、实现方式及生命周期管理。介绍了通过Binder类、Messenger和AIDL三种方法实现绑定服务接口的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇写了个AIDL,虽然最终做出来了,但个人感觉有点头重脚轻。其中 Bound Service 就不是很明白,今天再次回去看了看官方帮助文档,在这里记录一下自己对帮助文档的理解。(android 官方帮助文档连接:http://developer.android.com/guide/components/bound-services.html

Bound Service

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.

“绑定服务”是一个客户端-服务器的服务接口。”绑定服务“允许组件(例如:活动—activities)绑定到该服务,发送请求,接收相应,甚至执行进程间通信等操作。典型的绑定服务不是一直在后台运行,而是只在为某个应用程序组件服务时存在(运行)。

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. ThebindService() method returns immediately without a value, but when the Android system creates the connection between the client and service, it calls onServiceConnected() on theServiceConnection, to deliver the IBinder that the client can use to communicate with the service.

客户端可以通过调用bindService()绑定到服务。当客户端选择这样做时,它必须实现ServiceConnection——监控与服务器的连接。bindService()方法会立刻返回空值(没有任何值)。当android系统在客户端和服务器建立连接时会调用ServiceConnection的onServiceConnected()方法——该方法传递了客户端与服务器交互的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 bystartService()).

只要没有通过startService()方法启动服务,系统会在最后一个客户取消绑定的时候销毁该服务。

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 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 theService.

如果你的服务对应用程序来说是私有的并且在同一个进程中运行,那么你应该通过继承Binder类来创建接口并且从onBind()方法中返回该接口的一个实例。客户端获取该Binder对象后可以直接访问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来创建你的接口了。在这种方法中,服务定义了一个Handler去相应不同类型的Message对象。这个Handler可以和客户端共享一个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 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处理所有的将对象分解成操作系统能够理解的基本数据类型的操作,并且在进程间传递,完成进程间通信。实际上,前一种提及的技术在底层架构上也是使用的AIDL。和上面讲到的一样,Messenger在一个独立线程里创建了一个队列维护所有客户端的请求,所以,服务在同一时刻只能提取一个请求进行处理。如果你想让你的服务同时处理多个客户端的请求,那么你可以直接使用AIDL——因此,你的服务也必须兼容多线程并且是线程安全的。

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.

如果你的服务不需要跨进程使用而仅仅是在本地应用中使用,那么你可以实现自己的Binder用于提供客户端直接访问服务的公有方法。

注意:这种技术仅仅在客户端和服务在同一个应用中时才起作用。

Here's how to set it up:

In your service, create an instance of Binder that either:

contains public methods that the client can call

returns the current Service instance, 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 Binder from the onBind() callback method.

In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided.

下面是如何设置它:

1、在服务中创建一个Binder实例可以由以下三种方法:

* 包含 一个客户端可以调用的公有方法。

* 返回一个可以调用服务公有方法的当前Service实例。

* 返回一个客户端可以调用另一个类的一个实例托管的服务。

2、从onBind()回调方法返回Binder实例。

3、在客户端从onServiceConnecte()回调方法接收Binder对象,然后用该对象调用绑定服务提供的方法。

For example, here's a service that provides clients access to methods in the service through a Binder implementation:

下面就是一个通过是实现Binder来完成客户端访问服务的例子(该文所有源码来自android官方文档,有兴趣的童鞋可以去看看):

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 为客户端提供了getService()方法读取LocalService的实例。这样就允许了客户端调用服务的公有方法。例如:用户可以调用服务的getRandomNumber()方法。

Here's an activity that binds to LocalService and calls getRandomNumber() when a button is clicked:

下面是activity中到LocalService并在一个button被点击时调用getRandomNumber()方法的例子:

注意:上面的例子虽然给出了如何通过继承Binder实现绑定服务,但是没有调用unBindService()方法,请自己在适当的地方调用unBindService()方法。

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.

如果你ide服务需要和远程进程进行通信,那么你可以使用Messengerwinid的服务提供一个程序接口。这种技术可以在不使用AIDL的情况下完成进程间通信。

Here's a summary of how to use a Messenger:

The service implements a Handler that receives a callback for each call from a client.

The Handler is used to create a Messenger object (which is a reference to the Handler).

The Messenger creates an IBinder that the service returns to clients from 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.

The service receives each Message in its Handler—specifically, in the handleMessage() method.

下面是一些关于如何 使用Messenger的简单介绍:

1、服务实现一个Handler用于接收所有来自客户端的回调。

2、用Handler创建一个Messenger对象(该Messenger对象引用了Handler);

3、Messenger创建的IBinder用于从Service的onBind()方法返回。

4、客户端用IBinder实例化Messenger(该Messenger引用了服务的Handler),客户端使用该实例向服务发送Message对象。

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.

在这种方法中,客户端不是调用服务的方法而是通过传递Message对象与服务通信。

Here's a simple example service that uses a Messenger interface:

下面是使用Messager接口绑定服务的例子:

Notice that the handleMessage() method in the Handler is where the service receives the incomingMessage and decides what to do, based on the what member.

在handler的handleMessage()方法中是接收incomingMessage并且根据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 theMSG_SAY_HELLO message to the service:

所有客户端需要做的就是根据服务返回的IBinder创建Messenger对象,然后通过调用send()方法向服务发送消息。下面是一个activity绑定到服务并且传递MSG_SAY_HELLO消息给服务:

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 Messengerin the replyTo parameter of the send() method.

在该例子中没有展示服务如何响应客户端。如果你想要服务的响应,你就需要在客户建一个Messenger。然后在客户端的onServiceConnected()回调方法中读取数据时向服务发送一个Message——该Message包含了用户调用send()方法时传递的回应参数。


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 withonStartCommand()). 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系统会销毁该服务。所以如果是纯粹的绑定服务,你不必要去管理你的服务——android系统会为你管理该服务。

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.

另外,如果你的服务已经启动并且接受了绑定,则当系统调用unBindService()方法时,你可以选择返回  true 以便在下一次绑定到该服务时调用onRebind()方法而不是再次调用onBind()方法。onRebind()方法没有返回内容,单数客户端仍然可以从onServiceConnected()回调方法读取IBinder对象。下图说明了这种类型服务的生命周期:

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值