http://blog.csdn.net/nkmnkm/article/details/7359321
概述
绑定的service是在一个客户端-服务端接口中的服务.绑定的ervice允许组件(比如activities)绑定到service,发送请求,接收回应,甚至执行进程间通讯(IPC).绑定的service一般只生存于为其它应用组件服务其间并且不会永远行于后台.
本文档向你展示了如何创建一个绑定的service,包括如何从其它应用组件绑定到service.然而,你应该也去参考Service的文档来学习更多通用知识,比如如何从servcie发出通知,如何设置service为前台运行,等等.
绑定到一个"运行的"Service
如同在Service文档中所述,你可以创建一个既是"运行的"又是"绑定的"的service.即,这个service可以通过调用startService()启动,这使得这个service可以永远运行,同时也允许一个客户端通过调用indService()绑定到它.
如果你允许你的service是"运行的"和"绑定的",那么当service启动后,系统不会在所有客户端解除绑定后销毁service,而是,你必须通过调用stopSelf()或stopService()显示地停止这个service
尽管你通常应该实现onBind()或onStartCommand(),但有时需要同时实现两者.例如,一个音乐播放器可能发现允许它的service永久运行同时又能被绑定是很有用的.这样一来,一个activity可以启动这个service来播放一些音乐并且即使用户离开了这个应用,播放也会继续.
基础知识
一个绑定的service是一个允许应用绑定然后进行交互的类Service的实现.要为service提供绑定,你必须实现onBind()回调方法.此方法返回一个IBinder对象,此对象定义了客户端可以用来与service交互的程序接口.
一个客户端可以通过调用bindService()绑定到service.当它这样做时,它必须提供了一个ServiceConnection的实现.这个实现用于监视客户端与service的连接.bindService()方法会立即返回并且不会返回任何值,但当Android系统创建客户端与service之间的连接时,它调用ServiceConnection的onServiceConnected()来传送客户端用来与servcie通信的IBinder.
多个客户端可以同时连接到一个service.然而,系统只在第一个客户端绑定时才调用你的service的onBind()方法来接收IBinder.之后系统把同一个IBinder传给其它客户端,所以不会再调用onBind().
当最后一个客户端取消绑定到service时,系统销毁这个service(除非这个service同时也是一个"运行的"service).
当你实现你的绑定的service,最重要的部分是定义你的onBind()回调方法所返回的接口.有许多不同的方法可以定义你的service的IBinder接口,并且下面的章节会讨论每种技术.
创建一个绑定的Service
当创建一个提供绑定的service时,你必须提供一个客户端用来与service交互的IBinder.有三种方式你可以定义这个接口:
-
从类Binder派生
如果你的service是你自己应用的私有物,并且与客户端运行于同一个进程中(一般都这样),你应该通过从类Binder派生来创建你的接口并且从onBind()返回一它的实例.客户端接收这个Binder然后使用它来直接操作所实现的Binder甚至Service的公共接口.
当你的service仅仅是一个后台工作并且仅服务于自己的应用时,这是最好的选择.唯一使你不能以这种方式创建你的接口的理由就是你的service被其它应用使使用或者是跨进程的.
-
使用一个Messenger
如果你需要你的接口跨进程工作,你可以为service创建一个带有Messager的接口.在此方式下,service定义一个Handler来负责不同类型的Message对象.这个Handler是Messenger可以与客户端共享一个IBinder的基础,它允许客户端使用Message对象发送命令给servic.客户端可以定义一个自己的Messenger以使service可以回发消息.
这是执行IPC的最简单的方法,因为Messenger把所有的请求都放在队列中依次送入一个线程中,所以你不必把你的service设计为线程安全的
-
使用AIDL
AIDL(Android接口定义语言)执行把对象分解为操作系统能够理解并能跨进程封送的基本体以执行IPC的所有的工作.上面所讲的使用一个Messenger,实际上就是基于AIDL的.就像上面提到的,Messenger在一个线程中创建一个容纳所有客户端请求的队列,使用service一个时刻只接收一个请求.然而,如果你想要你的service同时处理多个请求,那么你可以直接使用AIDL.在此情况下,你的service必须是多线程安全的.
要直接使用AIDL,你必须创建一个.aidl文件,它定义了程序的接口.AndroidSDK工具使用这个文件来生成一个实现接口和处理IPC的抽象类,之后你在你的service内派生它.
注:大多数应用不应使用AIDL来处理一个绑定的service,因为它可能要求有多线程能力并且导致实现变得更加复杂.同样的,AIDL也不适合于大多数应用并且本文档不会讨论如何在你的service中使用它.如果你确定你需要直接使用AIDL,请看AIDL的文档.