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.
A bound service is an implementation of the
to bind to it and interact with it. To provide binding for a service, you must implement the
method. This method returns an
clients can use to interact with the service.
you can create a service that is both started and bound. That is, the service can be started by calling
which allows the service to run indefinitely, and also allow a client to bind to the service by calling
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
Although you should usually implement either
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
When it does, it must provide an implementation of
monitors the connection with the service. The
returns immediately without a value, but when the Android system creates the connection between the client and service, it calls
the
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
to retrieve the
any additional clients that bind, without calling
When the last client unbinds from the service, the system destroys the service (unless the service was also started by
When you implement your bound service, the most important part is defining the interface that your
method returns. There are a few different ways you can define your service's
and the following section discusses each technique.
When creating a service that provides binding, you must provide an
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
and returning an instance of it from
receives the
or even the
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
In this manner, the service defines a
This
can then share an
using
its own so the service can send messages back.
This is the simplest way to perform interprocess communication (IPC), because the
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
above, the
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
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.
If your service is used only by the local application and does not need to work across processes, then you can implement your own
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
contains public methods that the client can call
returns the current
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
method.
In the client, receive the
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
The
call
Here's an activity that binds to
The above sample shows how the client binds to the service using an implementation of
the
The next section provides more information about this process of binding to the service.
Note: In the example above, the
from the service. Clients should unbind from services at appropriate times, as discussed in Additional
Notes.
For more sample code, see the
and the
inApiDemos.
your interface is simpler than implementing it with AIDL, because
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
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
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
The service implements a
for each call from a client.
The
(which is a reference to the
The
the service returns to clients from
Clients use the
references the service's
to the service.
The service receives each
in the
In this way, there are no "methods" for the client to call on the service. Instead, the client delivers "messages" (
that the service receives in its
Here's a simple example service that uses a
Notice that the
where the service receives the incoming
All that a client needs to do is create a
by the service and send a message using
a simple activity that binds to the service and delivers the
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
the client. Then when the client receives the
it sends a
the
You can see an example of how to provide two-way messaging in the
and
samples.
Application components (clients) can bind to a service by calling
The Android system then calls the service's
which returns an
The binding is asynchronous.
immediately and does not return the
the client must create an instance of
The
deliver the
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
Your implementation must override two callback methods:
by the service's
Call
passing the
When the system calls your
method, you can begin making calls to the service, using the methods defined by the interface.
To disconnect from the service, call
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
and request the
With this
to
For example:
The first parameter of
an
The second parameter is the
The third parameter is a flag indicating options for the binding. It should usually be
order to create the service if its not already alive. Other possible values are
or
Here are some important notes about binding to a service:
You should always trap
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
unbind during
If you want your activity to receive responses even while it is stopped in the background, then you can bind during
unbind during
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
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
in ApiDemos.
When a service is unbound from all clients, the Android system destroys it (unless it was also started with
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
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
another component calls
of whether it is bound to any clients.
Additionally, if your service is started and accepts binding, then when the system calls your
you can optionally return
next time a client binds to the service.
void, but the client still receives the
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)。同时它还有另一个应用程序组件并不会在后台运行下去一个绑定服务通常只生活。
本文将向您展示如何创建绑定服务,包括如何绑定到其他应用程序组件的服务。但是,你也应该参考服务文档,对一般的服务,比如如何从服务交付通知,设置服务在前台运行,以及更多其他信息。
绑定的服务是一个实现
如果你允许你的服务要启动和约束,那么当该服务已启动,系统就不会在所有客户端解除销毁服务。相反,你必须明确停止服务,通过调用
虽然你通常应该要么实现
请务必阅读关于部分管理一个绑定的服务生命周期中,大约添加时绑定到一个启动的服务的服务生命周期的更多信息。
客户端可以通过调用绑定到服务
多个客户端可以连接到服务一次。但是,系统调用服务的
当最后一个客户端从服务解除绑定,系统破坏服务(除非该服务也被启动
当你实现你的绑定服务,最重要的部分是定义你的界面
当创建一个提供绑定服务,你必须提供
扩展类粘结剂如果您的服务是专用于自己的应用程序,并在同一个进程中的客户端(这是常见的)运行时,你应该通过扩展创建界面
直接访问任何可用的公共方法
这是当你的服务仅仅是自己的应用程序后台工作的首选技术。唯一的原因,你会不会创建界面这种方式是因为你的服务被其他应用程序或通过单独的进程。
使用信使如果您需要的接口在不同的流程工作,你可以创建一个服务的界面
务
这是执行进程间通信(IPC)最简单的方法,因为
使用AIDLAIDL(Android界面定义语言)执行所有工作分解物进入原语操作系统能够理解和马歇尔他们整个进程来执行IPC。以前的技 术,采用了
直接使用AIDL,你必须创建一个
注意:大多数应用程序不应该使用AIDL创建绑定的服务,因为它可能需要多线程功能,可以导致更复杂的实现。因此,AIDL是不适合大多数的应用程序和本文档不讨论如何使用它为你服务。如果你确信你需要直接使用AIDL,看到AIDL 文件。
如果您的服务只能由本地应用程序,也不需要工作跨进程,那么你就可以实现自己的
注意:这只有在客户端和服务都在相同的应用程序和过程,这是最常见的。例如,这将为需要的活性绑定到其自己的服务正在播放音乐的背景音乐应用工作得很好。
以下是如何设置它:
在服务中,创建一个实例
包含公共方法,客户端可以调用
返回当前
或者,返回由服务与公共方法的客户端可以调用托管于其他类的实例
返回的这个实例
在客户端,接收
注意:在服务和客户端必须在同一应用程序的原因是这样的客户机可投返回的对象和正确地调用它的API。服务和客户端也必须是在相同的过程中,由于该技术不跨进程执行任何编组。
例如,下面是为客户提供接触到通过服务方法服务
该
下面是结合活动
上面的示例显示了客户端使用的实现如何绑定到服务
注:在上面的例子中,
欲了解更多示例代码,请参见
对于大多数应用,该服务并不需要执行多线程,因此使用
如果您需要的服务与远程进程进行通信,那么你可以使用一个
下面是如何使用的总结
的服务实现了一个
该
该
客户端使用
服务的
该服务接收的每个
以这种方式,不存在“的方法”为客户端上的服务调用。相反,客户端提供“信息”(
下面是一个使用一个简单的例子服务
注意,
所有的客户需要做的是建立一个
请注意,这个例子没有说明如何服务可以响应客户端。如果你想在服务响应,那么你还需要创建一个
你可以看到如何提供一种在双向消息 传送的示例
应用程序组件(客户端)可通过调用绑定到服务
的结合是异步的。
注意:只有活动,服务和内容提供商可以绑定到一个服务,你不能绑定到从广播接收机的服务。
因此,从客户端绑定到一个服务,你必须:
实施
你的实现必须重写两个回调方法:
调用
当系统调用你的
从服务断开连接,调用
如果你的客户仍难免,当你的应用程序破坏了客户服务,破坏导致客户端解除绑定。它更好的做法是,只要它完成与服务进行交互解除客户端。这样做可以让闲置的服务关闭。有关适当的时候更多的信息,绑定和取消绑定,请参阅其他注意事项。
例如,下面的代码片段客户端连接到由上面创建的服务 扩展粘合剂类,因此,所有必须做的是转换返回
与此
第一个参数
第二个参数是
第三个参数是指示用于结合选择的标志。它通常应该是
以下是关于绑定服务的一些重要事项:
你应该总是陷阱
对象引用跨进程计数。
通常你应该配对绑定和解除绑定匹配调高客户的生命周期和拆除过程中的瞬间。例如:
如果你只需要与服务进行交互,而你的活动是可见的,你应该在绑定
如果你希望你的活动来接收响应即使它是在后台停止了,那么你就可以在绑定
注意:您通常应该不绑定,你的活动的过程中解除
欲了解更多示例代码,展示如何绑定到服务,请参阅
当服务是所有客户端绑定,Android系统破坏它(除非它也与启动
但是,如果您选择实现
此外,如果您的服务已启动,并接受绑定,然后当系统调用你的
图1为已启动,并且还允许绑定一个服务的生命周期。
有关在启动服务的生命周期的更多信息,请参阅服务文档
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 Serviceclass 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
IBinderobject 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
IBinderthat
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
IBinderonly when the first client binds. The system then delivers the same
IBinderto
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
IBinderinterface
and the following section discusses each technique.
Creating a Bound Service
When creating a service that provides binding, you must provide an IBinderthat 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
Binderclass
and returning an instance of it from
onBind(). The client
receives the
Binderand can use it to directly access public methods available in either the
Binderimplementation
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
Handlerthat responds to different types of
Messageobjects.
This
Handleris the basis for a
Messengerthat
can then share an
IBinderwith the client, allowing the client to send commands to the service
using
Messageobjects. Additionally, the client can define a
Messengerof
its own so the service can send messages back.
This is the simplest way to perform interprocess communication (IPC), because the
Messengerqueues
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
Messengercreates 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
.aidlfile 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 Binderclass
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
Binderthat either:
contains public methods that the client can call
returns the current
Serviceinstance, 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
Binderfrom the
onBind()callback
method.
In the client, receive the
Binderfrom 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
Binderimplementation:
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
LocalBinderprovides 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
LocalServiceand 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
ServiceConnectionand
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.javaclass
and the
LocalServiceActivities.javaclass
inApiDemos.
Using a Messenger
Compared to AIDL
When you need to perform IPC, using aMessengerfor
your interface is simpler than implementing it with AIDL, because
Messengerqueues
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
Messengerallows
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
Messengerto
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
Handlerthat receives a callback
for each call from a client.
The
Handleris used to create a
Messengerobject
(which is a reference to the
Handler).
The
Messengercreates an
IBinderthat
the service returns to clients from
onBind().
Clients use the
IBinderto instantiate the
Messenger(that
references the service's
Handler), which the client uses to send
Messageobjects
to the service.
The service receives each
Messagein 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" (
Messageobjects)
that the service receives in its
Handler.
Here's a simple example service that uses a
Messengerinterface:
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
Handleris
where the service receives the incoming
Messageand decides what to do, based on the
whatmember.
All that a client needs to do is create a
Messengerbased on the
IBinderreturned
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_HELLOmessage 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
Messengerin
the client. Then when the client receives the
onServiceConnected()callback,
it sends a
Messageto the service that includes the client's
Messengerin
the
replyToparameter 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
IBinderfor interacting with the service.
The binding is asynchronous.
bindService()returns
immediately and does not return the
IBinderto the client. To receive the
IBinder,
the client must create an instance of
ServiceConnectionand pass it to
bindService().
The
ServiceConnectionincludes 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
IBinderreturned
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
ServiceConnectionimplementation.
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
IBinderto the
LocalServiceclass
and request the
LocalServiceinstance:
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
Intentthat explicitly names the service to bind (thought the intent could be implicit).
The second parameter is the
ServiceConnectionobject.
The third parameter is a flag indicating options for the binding. It should usually be
BIND_AUTO_CREATEin
order to create the service if its not already alive. Other possible values are
BIND_DEBUG_UNBINDand
BIND_NOT_FOREGROUND,
or
0for none.
Additional notes
Here are some important notes about binding to a service:You should always trap
DeadObjectExceptionexceptions,
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.javaclass
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 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.
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
trueif 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
IBinderin 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为已启动,并且还允许绑定一个服务的生命周期。
有关在启动服务的生命周期的更多信息,请参阅服务文档
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories