`

【翻译】(8)被绑定的服务

 
阅读更多

 

【翻译】(8)被绑定的服务

 

see

http://developer.android.com/guide/topics/fundamentals/bound-services.html

 

原文见

http://developer.android.com/guide/topics/fundamentals/bound-services.html

 

-------------------------------

 

Bound Services

 

被绑定的服务

 

-------------------------------

 

Quickview

 

快速概述

 

* A bound service allows other components to bind to it, in order to interact with it and perform interprocess communication

 

* 一个被绑定的服务允许其它组件绑定到它,为了与它交互并执行进程间通信

 

* A bound service is destroyed once all clients unbind, unless the service was also started

 

* 一旦所有客户端解除绑定,被绑定的服务会被销毁,除非服务同时也是被启动的。

 

In this document

 

本文目录

 

* The Basics 基础

* Creating a Bound Service 创建被绑定的服务

* Extending the Binder class 扩展Binder类

* Using a Messenger 使用信使

* Binding to a Service 绑定到服务

* Managing the Lifecycle of a Bound Service 管理被绑定服务的生命周期

 

Key classes

 

关键类

 

Service

ServiceConnection

IBinder

 

Samples

 

示例

 

RemoteService

LocalService

 

See also

 

另见

 

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)。一个被绑定服务通常存活在它服务于应用程序组件的时候,而非无限期地运行在后台。

 

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.

 

本文向你展示如何创建一个被绑定的服务,包括如何从其它应用组件绑定到服务。然而,你还应该参考服务文档以获取一般关于服务的额外信息,诸如如何传递来自服务的通知,设置服务运行于后台,等等。

 

-------------------------------

 

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对象,定义客户端可以用来与服务交互的编程接口。

 

-------------------------------

 

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().

 

正如服务文档中讨论的,你可以创建一个既是被启动又是被绑定的服务。就是说,服务可以通过调用startService()被启动,它允许服务无限期地运行,也允许一个客户端通过调用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().

 

如果你允许你的服务同时被启动和被绑定,那么当服务被启动时,系统不会在所有客户端解除绑定时销毁服务。相反,你必须通过调用stopSelf()或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.

 

虽然你通常应该实现onBind()或onStartCommand(),但有时有必要都实现它们。例如,一个音乐播放器可能发现允许它的服务无限期运行,而且还提供绑定是有用的。以这种方式,一个活动可以启动服务播放一些音乐,而音乐继续播放,即使用户离开应用程序。那么,当用户返回到应用程序时,活动可以绑定到服务并以恢复回放的控制权。

 

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.

 

一个客户端可以通过调用bindService()绑定到服务。当它这么做时,它必须提供一个ServiceConnection的实现,它监视与服务的连接。bindService()方法不带值(注:不带返回值?)地立刻返回,但是当Android系统在客户端和服务之间创建连接时,它调用ServiceConnection上的onServiceConnected(),以传递IBinder对象,客户端可以用这个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

 

* 扩展Binder类

 

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,并可以使用它直接访问在Binder的实现中或者甚至在Service中可用的public方法。

 

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对象。这个处理句柄是在之后与客户端共享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.

 

这是执行进程间通信(IPC)的最简单方式,因为Messenger队列化所有请求到单一线程中,使你不必把你的服务设计为线程安全。

 

* Using AIDL

 

* 使用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(Android接口定义语言)执行把对象分解成操作系统可以理解的基本元素,并跨进程编集(注:正式的写法是marshal,类似于序列化,但一般用于通信方面)它们以执行IPC(注:进程间通信)的所有工作。前面提到的使用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类,它向你的客户端提供对服务的public方法的直接访问。

 

-------------------------------

 

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:

 

这里叙述如何配置它

 

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

 

1. 在你的服务中,创建一个Binder接口,它或者:

 

* contains public methods that the client can call

 

* 包含客户端可以调用的public方法

 

* returns the current Service instance, which has public methods the client can call

 

* 返回当前的Service实例,它拥有客户端可以调用的public方法

 

* or, returns an instance of another class hosted by the service with public methods the client can call

 

* 或者,返回另一个类的实例,它由服务持有,带有客户端可以访问的public方法

 

2. Return this instance of Binder from the onBind() callback method.

 

2. 从onBind()回调方法中返回这个Binder实例。

 

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

 

3. 在客户端中,从onServiceConnected()回调方法中接收Binder对象,并使用它提供的方法执行对被绑定服务的调用。

 

-------------------------------

 

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.

 

注意:服务和客户端必须在同一个应用程序的理由是,客户端可以转换返回的对象并可以调用它的API。服务和客户端还必须在同一个进程中,因为这种技术不会跨进程地执行任意编集。

 

-------------------------------

 

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

 

例如,这里有一个服务,通过一个Binder实现为客户端提供对服务内方法的访问。

 

-------------------------------

 

public class LocalService extends Service {

    // Binder given to clients

    // 传给客户端的Binder

    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.

     * 用于客户端Binder的类。因为我们知道这个服务

     * 总是和它的客户端运行在相同进程,所以我们

     * 不需要处理IPC(注:进程间通信)。

     */

    public class LocalBinder extends Binder {

        LocalService getService() {

            // Return this instance of LocalService so clients can call public methods

            // 返回这个LocalService实例,所以客户端可以调用public方法

            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为客户端提供getService()方法以取得当前的LocalService示例。这允许客户端调用服务中的public方法。例如,客户端可以从服务中调用getRandomNumber()。

 

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

 

这里有一个活动,绑定到LocalService,并在按钮被点击时调用getRandomNumber()。

 

-------------------------------

 

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

        // 绑定到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.

            // 调用来自LocalService的方法。

            // 然而,如果这个调用有时可能被挂起,

            // 那么这个请求应该发生在单独的线程,

            // 以避免减慢活动的性能。

            int num = mService.getRandomNumber();

            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();

        }

    }

 

    /** Defines callbacks for service binding, passed to bindService() */

    /** 定义服务绑定的回调,传递给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.

 

上面的示例展示客户端如何使用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类和LocalServiceActivities.java类。

 

Using a Messenger

 

使用信使

 

-------------------------------

 

Compared to AIDL

 

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

 

当你需要执行IPC时,为你的接口使用一个Messenger,比用AIDL实现它要简单,因为Messenger队列化所有对服务的调用,然而,一个纯AIDL接口发送同步请求给服务,它必须在稍后处理多线程。

 

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.

 

对于大多数应用程序,服务不需要执行多线程,所以使用一个Messenger允许服务在同一时间只处理一个调用。如果你的服务是多线程很重要,那么你应该使用AIDL去定义你的接口。

 

-------------------------------

 

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提供接口给你的服务。这种技术允许你执行进程间通信(IPC)而不需要使用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对象),客户端使用这个Messenger发送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.

 

在这种方式中,没有“方法”供客户端调用在服务上。相反,客户端传递messages(Message对象),服务在它的Handler中接收它们。

 

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

 

这里有一个简单示例服务,它使用Messenger接口:

 

-------------------------------

 

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.

     * 用于处理来自客户端的传入消息的Handler。

     */

    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.

     * 我们发布的目标是让客户端发送消息到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.

 

注意在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:

 

客户端需要做的所有事情是,创建一个Messenger对象,基于由服务返回的IBinder,并使用send()发送消息。例如,这里有一个简单活动,绑定到服务并传递MSG_SAY_HELLO消息给服务:

 

-------------------------------

 

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.

            // 当与服务的连接已经被建立时调用,传给为我们一个对象,我们可以用它

            // 与服务交互。我们使用一个Messenger与服务通信,所以这里

            // 我们从原始的IBinder对象中获取它的客户端方表现。

            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.

 

注意,这个示例并未展示服务如何可以响应客户端。如果你想让服务响应,那么你还需要在客户端中创建一个Messenger对象。然后当客户端接收onServiceConnected()回调时,它发送一个Message对象给服务,在send()方法的replyTo参数中包含客户端的Messenger。

 

You can see an example of how to provide two-way messaging in the MessengerService.java (service) and MessengerServiceActivities.java (client) samples.

 

你可以参见一个关于如何提供双向消息的示例,MessengerService.java(服务)和MessengerServiceActivities.java(客户端)示例。

 

-------------------------------

 

Binding to a Service

 

绑定到服务

 

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,客户端必须创建一个ServiceConnection实例并把它传递给bindService()。ServiceConnection包含系统为了传递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:

 

所以,为了从你的客户端绑定到服务,你必须:

 

1. Implement ServiceConnection.

 

1. 实现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.

 

当与服务的连接意外丢失时,诸如当服务已经崩溃或被杀死,则Android系统调用此方法。当客户端解除绑定时它不会被调用。

 

2. Call bindService(), passing the ServiceConnection implementation.

 

2. 调用bindService(),传递ServiceConnection实现。

 

3. When the system calls your onServiceConnected() callback method, you can begin making calls to the service, using the methods defined by the interface.

 

3. 当系统调用你的onServiceConnected()回调方法时,你可以使用接口定义的方法,开始调用服务。

 

4. To disconnect from the service, call unbindService().

 

4. 为了断开与服务的连接,调用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:

 

例如,以下代码片段通过扩展Binder类,把客户端连接到上面创建的服务,所以它必须做的所有事情是把返回的IBinder转换为LocalService并请求LocalService实例。

 

-------------------------------

 

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:

 

使用这个ServiceConnection,客户端可以通过传递this给bindService()把它绑定到服务。例如:

 

-------------------------------

 

Intent intent = new Intent(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()的第一个参数是意图,它显式地指出要绑定服务的名称(认为意图可以是隐式的)

 

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

 

* 你应该总是捕获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().

 

* 如果你只需要在活动可见时与服务交互,那么你应该在onStart()期间绑定,而在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.

 

* 如果你希望你的活动接收响应,甚至当它在后台中被停止时,那么你可以在onCreate()期间绑定,并且在onDestroy()期间解除绑定。请意识到这暗示着你的活动需要在活动的整个运行时间内使用它(甚至在后台中),所以如果服务在另一个进程里,那么你会增加进程的重量(注:负荷),它会变得更有可能将要被系统杀死。

 

-------------------------------

 

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()期间绑定和解除绑定,因为这些回调发生在任意生命周期过渡,而你应该保持发生在这些过渡时的处理为最小。同时,如果你的应用程序中的多个活动绑定到相同的活动,在这些活动中有两个活动之间存在过渡,那么服务应该在当前活动解除绑定(在暂停期间)之后,下一个活动绑定(在恢复期间)之前,销毁并重新创建。(活动过渡如何让活动协调它们的生命周期,在活动文档中描述。)

 

-------------------------------

 

For more sample code, showing how to bind to a service, see the RemoteService.java class in ApiDemos.

 

想获取更多展示如何绑定到服务的示例代码,请参见ApiDemos里的RemoteService.java类。

 

-------------------------------

 

Managing the Lifecycle of a Bound Service

 

管理被绑定服务的生命周期

 

-------------------------------

 

(图略:

1. 不按特定顺序,onStartCommand()和onBind()被调用

2. 服务正在运行而客户端被绑定到它

3. 所有客户端通过调用unbindService解除绑定

4. onUnbind() -> 6

5. 服务是否还通过stopSelf()或stopService()停止?是->6,否->8

6. onDestry()

7. 服务关闭->(结束)

8. 服务正在运行

9. 客户端调用bindService()

10. onUnbind()是否返回true?是->11,否->12

11. onRebind()->2

12. onBind()->2

 

Figure 1. The lifecycle for a service that is started and also allows binding.

 

图1. 被启动同时还允许绑定的服务的生命周期。

 

-------------------------------

 

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()被启动)。因此,如果它单纯是一个被绑定的服务,你不必管理你的服务的生命周期——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.

 

另外,如果你的服务是被启动的并接受绑定,那么当系统调用你的onUnbind()方法时,如果你喜欢在下一次客户端绑定服务时接收对onRebind()的调用,你可以可选地返回true。onRebind()返回void,但客户端仍会在它的onServiceConnected()中接收IBinder。下面,图1描绘此类生命周期的逻辑。

 

For more information about the lifecycle of an started service, see the Services document.

 

更多关于被启动服务的生命周期,请参见服务文档。

 

Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.

 

除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。

 

Android 4.0 r1 - 04 Nov 2011 0:15

 

-------------------------------

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)

 

分享到:
评论

相关推荐

    ZigBee四种绑定方式在TI Z-Stack中的应用

    发送时使用的目标地址将由应用支持子层(APS)从绑定表中自动获得,从而能使消息顺利被目标节点的一个或多个应用服务,乃至分组接收。 Binding Table 1.Defined in RAM,but can be saved in Flash if the NV_...

    Spring Security-3.0.1中文官方文档(翻译版)

    19.3.2. 使用绑定认证 19.3.3. 读取授权 19.4. 实现类 19.4.1. LdapAuthenticator 实现 19.4.1.1. 常用功能 19.4.1.2. BindAuthenticator 19.4.1.3. PasswordComparisonAuthenticator 19.4.1.4. 活动...

    计算机网络管理(雷振甲)(第二版)

    网络地址翻译属于将客户机配置的私有IP地址转换为物理机的可用上网IP地址,速率上会低点,且为配置好的话容易被防火墙拦截。 HOST-only应该是像组建局域网一样使客户机和物理机之间进行通讯,这样效率会更低,且限制...

    精通AngularJS part1

    编写会被安全压缩的JavaScript代码319 数组风格依赖注入的缺陷322 模板预加载323 使用指令预加载模板324 填充$templateCache服务325 组合使用不同的预加载技术327 122优化首页327 避免显示未经处理的模板328 ...

    java开源包8

    google-api-translate-java(Java 语言对Google翻译引擎的封装类库) 语音识别程序 SpeechLion.tar SpeechLion 是一个语音识别程序,主要用来处理桌面命令,基于 Sphinx-4 语音识别引擎开发。用户可以通过该软件来...

    Linux FTP服务配置

    由于端口22被ssh服务器占用,所以需要关闭ssh服务并重启vsftp服务。 客户端用Flashfxp测试:新建站点"VsftpTest",输入Vsftp服务器的IP地址,端口填22,用户名填ftp1,密码填你设置的密码,然后点击"连接"按钮: 由于...

    LINQ 实战 8/11

    12.4 查询Web服务:LINQ to Amazon 343 12.4.1 LINQ to Amazon介绍 344 12.4.2 需求 345 12.4.3 实现 346 12.5 IQueryable和IQueryProvider:LINQ to Amazon高级版本 352 12.5.1 IQueryable和...

Global site tag (gtag.js) - Google Analytics