为了方便描述,以下用“服务端”代表Service,用“客户端”代表启动Service的一端。与Service通信的方法有很多种,比如:.
- 直接启动Service,通过Intent传入参数。
- 通过Binder绑定Service进行直接通信,绑定Service也有三种不同的实现分别用于不同的场景
* 实现一:如果服务只在自己的程序里用,并且在同一个进程中,那么可以通过在Service里扩展Binder类并提供相关接口,这样当客户端首次和服务端绑定时,服务端可以通过onBind获取我们扩展的这个Binder类给客户端。一种比较常见的做法是在扩展的Binder类中编写一个方法获取当前的Service实例,这样客户端绑定服务拿到Binder后就可以通过这个方法获取Service实例从而可以访问到Service的公共方法、字段等等,达到通信的目的。
* 实现二:不过如果服务想要给程序的其它进程使用或要给其它程序使用就不能用实现一了,因为实现一的实现是进程内的通信,而非进程间通信。如果要进程间通信,要进行比较复杂的流程,所以安卓给我们提供了Messenger,让我们更加简单快捷地实现进程间的通信。Messenger的作用,顾名思义,送信人,送什么信呢?送的是handler中的message!我们可以服务端和客户端各创建一个handler,分别处理来自对方的message,达到通信的目的。在服务绑定的时候,客户端可以获取服务端的Messenger,通过这个Messenger,可以由客户端发送message给服务端,也正因为有这个Messenger,我们可以在客户端创建一个自己的Messenger,通过服务端的Messenger发送给服务端,这样服务端也可以通过这个Messenger发送message给客户端,这样双方的通信就打通了。基于这种实现Messenger会把所有的请求放入一个独立进程中的队列,这样你就不一定非要把服务设计为线程安全的模式了,这在绝大多数场景来说是适用的且有益的。但是如果服务端需要进行并发处理,这种实现就不适用了。
* 实现三:基于AIDL实现进程通信,这种方式的实现是安卓在你自己的进程中内部维护一个线程池,分配的远程进程的调用在线程池中处理,所以AIDL接口的实现必须要自己保证线程安全。具体实现参考谷歌的文档。