您的位置:首页 > 移动开发 > Android开发

Bound Services绑定服务

2016-04-03 19:24 513 查看
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 Servicesdocument
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.

Binding to a Started Service

As discussed in the Servicesdocument,
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 aboutManaging
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.


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:

Extending the Binder classIf 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.
Using a MessengerIf 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.
Using AIDLAIDL (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.
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.

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.


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

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

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


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

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 = 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.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, 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.

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


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.

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
IBinder
returned
by the service's
onBind()
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 the
ServiceConnection
implementation.
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, seeAdditional
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
an
Intent
that explicitly names the service to bind (thought the intent could be implicit).
The second parameter is the
ServiceConnection
object.
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.


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

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

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.

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.

绑定的服务是在客户端 - 服务器接口的服务器。绑定的服务允许组件(如活动)绑定到该服务,发送请求,接收响应,甚至进行进程间通信(IPC)。同时它还有另一个应用程序组件并不会在后台运行下去一个绑定服务通常只生活。

本文将向您展示如何创建绑定服务,包括如何绑定到其他应用程序组件的服务。但是,你也应该参考服务文档,对一般的服务,比如如何从服务交付通知,设置服务在前台运行,以及更多其他信息。


基础

绑定的服务是一个实现
服务
类,允许其他应用程序绑定到它,并与它进行交互。为了提供一个服务绑定,则必须实现
onBind()
回调方法。此方法返回
的IBinder
对象,定义编程接口,客户端可以使用与服务进行交互。

绑定到一个启动的服务

随着讨论的服务 文档,您可以创建一个服务,既开始和束缚。也就是说,该服务可以通过调用启动
startService() 
,它允许服务无限期运行,并且还允许客户机通过调用绑定到服务
bindService() 

如果你允许你的服务要启动和约束,那么当该服务已启动,系统就不会在所有客户端解除销毁服务。相反,你必须明确停止服务,通过调用
stopSelf()
stopService() 

虽然你通常应该要么实现
onBind()
onStartCommand() 
,有时需要同时实现。例如,音乐播放器可能会发现它很有用,允许其服务无限期地运行,同时提供绑定。通过这种方式,一个活动可以启动服务来播放音乐和音乐继续即使用户离开该应用程序播放。然后,当用户返回到应用程序,该活动可以绑定到服务恢复重放的控制。
请务必阅读关于部分管理一个绑定的服务生命周期中,大约添加时绑定到一个启动的服务的服务生命周期的更多信息。

客户端可以通过调用绑定到服务
bindService() 
。当它,它必须提供的实现
ServiceConnection
,负责监测与服务的连接。该
bindService()
方法立即返回没有价值,但是当Android系统创建客户端和服务之间的连接,它调用
onServiceConnected()
ServiceConnection
,为客户提供
的IBinder
客户端可以使用的服务进行通信。

多个客户端可以连接到服务一次。但是,系统调用服务的
onBind()
方法来检索
的IBinder
当第一个客户端仅绑定。然后,系统会提供相同
的IBinder
来结合任何额外的客户端,无需调用
onBind()
一次。

当最后一个客户端从服务解除绑定,系统破坏服务(除非该服务也被启动
startService() 
)。

当你实现你的绑定服务,最重要的部分是定义你的界面
onBind()
回调方法返回。有几种不同的方法可以定义服务的
的IBinder
接口和以下部分讨论每种技术。


创建绑定服务

当创建一个提供绑定服务,你必须提供
的IBinder
,提供了编程接口,客户端可以用来与服务进行交互。有三种方法可以定义界面:

扩展类粘结剂如果您的服务是专用于自己的应用程序,并在同一个进程中的客户端(这是常见的)运行时,你应该通过扩展创建界面
粘结剂
类,并从返回它的一个实例
onBind() 
。客户端接收
活页夹
,并可以使用它来
​​直接访问任何可用的公共方法
宾德
实施甚至
服务

这是当你的服务仅仅是自己的应用程序后台工作的首选技术。唯一的原因,你会不会创建界面这种方式是因为你的服务被其他应用程序或通过单独的进程。
使用信使如果您需要的接口在不同的流程工作,你可以创建一个服务的界面
使者
。以这种方式,该服务定义了一个
处理程序
来响应不同类型的
消息
对象。该
处理器
是一个基础
使者
,然后可以共享
的IBinder
与客户,允许客户使用发送指令到服
​​务
信息
的对象。此外,客户端可以定义
信使
自身这样的服务可以将消息发送回。
这是执行进程间通信(IPC)最简单的方法,因为
Messenger的
队列中的所有请求到一个单一的线程,这样你就不必来设计你的服务是线程安全的。
使用AIDLAIDL(Android界面定义语言)执行所有工作分解物进入原语操作系统能够理解和马歇尔他们整个进程来执行IPC。以前的技 ​​术,采用了
信使
,实际上是基于AIDL作为其基础结构。如上所述,在
信使
中创建单个线程的所有客户机请求的队列,因此,服务接收一次请求之一。但是,如果你希望你的服务能够同时处理多个请求,那么你可以直接使用AIDL。在这种情况下,服务必须能够多线程和建立线程安全。
直接使用AIDL,你必须创建一个
.aidl
定义编程接口文件。在Android SDK工具使用这个文件来生成实现该接口并处理IPC,然后你就可以你的服务中扩展的抽象类。

注意:大多数应用程序不应该使用AIDL创建绑定的服务,因为它可能需要多线程功能,可以导致更复杂的实现。因此,AIDL是不适合大多数的应用程序和本文档不讨论如何使用它为你服务。如果你确信你需要直接使用AIDL,看到AIDL 文件。


扩展类粘结剂

如果您的服务只能由本地应用程序,也不需要工作跨进程,那么你就可以实现自己的
活页夹
类,提供了对服务的公共方法您的客户端直接访问。

注意:这只有在客户端和服务都在相同的应用程序和过程,这是最常见的。例如,这将为需要的活性绑定到其自己的服务正在播放音乐的背景音乐应用工作得很好。

以下是如何设置它:

在服务中,创建一个实例
粘结剂
,要么:

包含公共方法,客户端可以调用
返回当前
服务
的实例,它具有公共方法的客户端可以调用
或者,返回由服务与公共方法的客户端可以调用托管于其他类的实例

返回的这个实例
粘结剂
onBind()
回调方法。
在客户端,接收
活页夹
onServiceConnected()
回调方法,并使用所提供的方法来绑定服务电话。

注意:在服务和客户端必须在同一应用程序的原因是这样的客户机可投返回的对象和正确地调用它的API。服务和客户端也必须是在相同的过程中,由于该技术不跨进程执行任何编组。

例如,下面是为客户提供接触到通过服务方法服务
粘结剂
实现:
公共 类 本地服务 延伸 服务 {
//活页夹给客户
私人 最终 的IBinder mBinder =  新 LocalBinder ();
//随机数发生器
私人 最终 随机mGenerator =  新的 随机();

/ **
*用于客户端粘合剂类。因为我们总是知道该服务
*运行在同一进程作为其客户,我们不需要处理IPC。
* /
公共 类 LocalBinder  扩展 宾德 {
本地服务的getService () {
//返回本地服务的这个实例,因此客户可以调用公共方法
返回 本地服务。此;
}
}

@覆盖
公共 的IBinder onBind (意向意图) {
返回mBinder ;
}

/ **客户端的方法* /
公共 INT getRandomNumber的() {
返回mGenerator 。nextInt (100 );
}
}


LocalBinder
提供
的getService()
方法,为客户获取的当前实例
本地服务
。这使得客户端来调用服务的公共方法。例如,客户端可以调用
getRandomNumber的()
从服务。

下面是结合活动
本地服务
,并调用
getRandomNumber的()
点击一个按钮时:
绑定到

从服务解除绑定
,如果 (mBound ) {
unbindService (mConnection );
mBound =  假;
}
}

/ **当单击一个按钮调用(在布局文件中的按钮高度重视
*这个方法用android:onclick属性)* /
公共 无效onButtonClick (查看v ) {
如果 (mBound ) {
//调用来自本地服务的方法。
//但是,如果这一呼吁是一些可能会挂起,那么这个请求应该
//发生在一个单独的线程,以避免放缓该活动的表现。
INT NUM = MSERVICE 。getRandomNumber的();
吐司。makeText (此, “数字”  + NUM , 吐司。LENGTH_SHORT )显示();
}
}

/ **定义为回调服务绑定,传递给bindService( )

我们势必本地服务,铸就的IBinder并获得本地服务


上面的示例显示了客户端使用的实现如何绑定到服务
ServiceConnection
onServiceConnected()
回调。下一节提供有关绑定到服务这一过程的详细信息。

注:在上面的例子中,
的onStop()
方法从服务解除绑定的客户端。客户应服务在适当的时候取消绑定,在讨论 其他注意事项

欲了解更多示例代码,请参见
LocalService.java
类和
LocalServiceActivities.java
ApiDemos


使用信使

相比AIDL

当您需要执行IPC,使用
信使
为你的界面比AIDL实现更简单,因为
信使
队列服务的所有电话,而一个纯粹的AIDL接口发送到服务,则必须处理多线程同时请求。
对于大多数应用,该服务并不需要执行多线程,因此使用
信使
允许服务一次处理一个呼叫。如果您的服务是多线程是很重要的,那么你应该使用AIDL来定义你的界面。

如果您需要的服务与远程进程进行通信,那么你可以使用一个
使者
提供的接口为您服务。这种技术可以让您无需使用AIDL进行进程间通信(IPC)。

下面是如何使用的总结
使者


的服务实现了一个
处理程序
,其接收来自客户端每次调用的回调。
处理程序
是用于创建一个
信使
对象(这是对一个参照
处理程序
)。
信使
创建
的IBinder
该服务从返回到客户
onBind() 

客户端使用
的IBinder
来实例化
使者
(引用该
​​服务的
处理程序
),客户端用来发送
邮件
对象的服务。
该服务接收的每个
消息
在它的
处理器
-特别在
handleMessage()函数
方法。

以这种方式,不存在“的方法”为客户端上的服务调用。相反,客户端提供“信息”(
信息
对象),该服务在其接收
处理程序


下面是一个使用一个简单的例子服务
Messenger的
界面:
公共 类 MessengerService  扩展 服务 {
/ **命令到服 ​​务显示一条消息* /
静态 最终 INT MSG_SAY_HELLO =  1 ;

/ **
从*传入消息处理程序

目标我们发布的客户端发送消息到IncomingHandler。
* /
最后的 使者mMessenger =  新 信使(新 IncomingHandler ());

/ **
*当绑定到服务,我们返回一个接口,我们的信使
*将消息发送到了


注意,
handleMessage()函数
中的方法
处理程序
是其中服务接收传入的
消息
,并决定做什么,基于上
什么
构件。

所有的客户需要做的是建立一个
Messenger的
基础上
的IBinder
服务返回和使用发送邮件
发送() 
。例如,这里有一个简单的活动结合服务,并提供了
MSG_SAY_HELLO
消息服务:
公共 类 ActivityMessenger  延伸 活动 {
/ **信使与服务进行通信。* /
斜挎MSERVICE =  空;

/ **标志表明我们是否已经呼吁服务绑定。* /
布尔mBound ;

/ **
*与的主界面交互类

这与该服务的连接已被调用时
//建立,使我们可以利用的对象
//与服务交互。我们正与通信
使用信使服务//,所以在这里我们得到一个客户端
的那//表示从原始的IBinder

这就是所谓的当与服务的连接已经
//意外断开-也就是说,它的进程崩溃。
MSERVICE =  零;
mBound =  假;
}
};

公共 无效的sayHello (查看v ) {
如果 (!mBound ) 的回报;
//创建并发送消息到服务,使用支持“是什么”

绑定到

从服务解除绑定
如果 (mBound ) {
unbindService (mConnection )
mBound =  假;
}
}
}


请注意,这个例子没有说明如何服务可以响应客户端。如果你想在服务响应,那么你还需要创建一个
信使
的客户端。然后,当客户端接收
onServiceConnected()
回调,它发送一个
消息
到包含客户端的服务
使者
的replyTo
的参数
的send()
方法。

你可以看到如何提供一种在双向消息 ​​传送的示例
MessengerService.java
(服务)和
MessengerServiceActivities.java
(客户端)的样品。


绑定到一个服务

应用程序组件(客户端)可通过调用绑定到服务
bindService() 
。然后,Android系统调用服务的
onBind()
方法,该方法返回
的IBinder
与服务交互。

的结合是异步的。
bindService()
立即返回,并没有在返回
的IBinder
给客户端。要接收
的IBinder
,客户端必须创建一个实例
ServiceConnection
并将其传递给
bindService() 
。该
ServiceConnection
包括系统调用来传递一个回调方法
的IBinder


注意:只有活动,服务和内容提供商可以绑定到一个服务,你不能绑定到从广播接收机的服务。

因此,从客户端绑定到一个服务,你必须:

实施
ServiceConnection

你的实现必须重写两个回调方法:
onServiceConnected()
该系统调用它来 ​​传递
的IBinder
由服务的返回
onBind()
方法。
onServiceDisconnected()
Android系统调用这个时候到服务的连接意外失去,如当服务崩溃或已被打死。这是不当客户端解除绑定调用。

调用
bindService() 
,传递
ServiceConnection
实施。
当系统调用你的
onServiceConnected()
回调方法,你就可以开始打电话到服务,使用该接口定义的方法。
从服务断开连接,调用
unbindService() 

如果你的客户仍难免,当你的应用程序破坏了客户服务,破坏导致客户端解除绑定。它更好的做法是,只要它完成与服务进行交互解除客户端。这样做可以让闲置的服务关闭。有关适当的时候更多的信息,绑定和取消绑定,请参阅其他注意事项

例如,下面的代码片段客户端连接到由上面创建的服务 扩展粘合剂类,因此,所有必须做的是转换返回
的IBinder
本地服务
类,并要求
本地服务
的实例:
本地服务MSERVICE ;
私人 ServiceConnection mConnection =  新 ServiceConnection () {
//当建立与服务的连接调用
公共 无效onServiceConnected (组件名的className , 的IBinder 服务) {
//因为我们已经绑定到一个明确
的在运行//服务我们自己的过程中,我们可以
//铸就了它的IBinder到具体的类,并直接访问它。
LocalBinder 粘结剂=  (LocalBinder )服务;
MSERVICE = 粘结剂。的getService ();
mBound =  真;
}

//调用时与服务的连接断开unexpectedly
public  void onServiceDisconnected ( ComponentName className )  {
Log . e ( TAG ,  "onServiceDisconnected" );
mBound =  false ;
}
};


与此
ServiceConnection
,客户端可以通过它传递给绑定到服务
bindService() 
。例如:
Intent intent =  new  Intent ( this ,  LocalService . class );
bindService ( intent , mConnection ,  Context . BIND_AUTO_CREATE );


第一个参数
bindService()
是一个
意图
是明确指定的服务绑定(认为的意图可能是隐含的)。
第二个参数是
ServiceConnection
对象。
第三个参数是指示用于结合选择的标志。它通常应该是
BIND_AUTO_CREATE
为了如果尚未活着创建服务。其他可能的值是
BIND_DEBUG_UNBIND
BIND_NOT_FOREGROUND
,或
0
表示无。


补充笔记

以下是关于绑定服务的一些重要事项:

你应该总是陷阱
DeadObjectException
例外,这是当连接已经打破抛出。这是通过远程方法抛出的唯一例外。
对象引用跨进程计数。
通常你应该配对绑定和解除绑定匹配调高客户的生命周期和拆除过程中的瞬间。例如:

如果你只需要与服务进行交互,而你的活动是可见的,你应该在绑定
在onStart() 
,并在解除绑定
的onStop() 

如果你希望你的活动来接收响应即使它是在后台停止了,那么你就可以在绑定
的onCreate() 
,并在解除绑定
的onDestroy() 
。要注意的是这意味着你的活动需要使用服务它的运行(即使在背景中)的整个时间,因此,如果该服务是在另一个过程中,则提高该方法的重量和它变得更可能的是,系统将杀了它。

注意:您通常应该绑定,你的活动的过程中解除
onResume()
的onPause() 
,因为这些回调发生在每一个生命周期的过渡和你应该保持发生在这些过渡到最低限度的处理。另外,如果您的应用程序绑定到同一服务的多个活动,并有其中的两个活动之间的过渡,服务可能成为下一个绑定之前破坏并重新创建作为当前活动的解除绑定(暂停期间)(恢复过程中)。(此为活动如何协调它们的生命周期活动的过渡中描述活动 的文件。)

欲了解更多示例代码,展示如何绑定到服务,请参阅
RemoteService.java
ApiDemos


管理绑定服务生命周期

当服务是所有客户端绑定,Android系统破坏它(除非它也与启动
onStartCommand() 
)。因此,你不必来管理服务的生命周期,如果它是一个纯粹的绑定服务的Android系统基于它是否绑定到任何客户端管理它。

但是,如果您选择实现
onStartCommand()
回调方法,那么你必须明确停止服务,因为该服务已经被认为是开始。在这种情况下,服务运行,直到该服务停止本身与
stopSelf()
或另一组件调用
stopService() 
,不管它是否被绑定到任何客户端。

此外,如果您的服务已启动,并接受绑定,然后当系统调用你的
onUnbind()
方法,你可以选择返回
,如果你想获得一个呼叫
onRebind()
的下一次客户端绑定到服务。
onRebind
()
返回void,但客户端仍然收到
的IBinder
在其
onServiceConnected()
回调。下面,图1中示出了用于这种生命周期的逻辑。



图1为已启动,并且还允许绑定一个服务的生命周期。

有关在启动服务的生命周期的更多信息,请参阅服务文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息