只从Binder的上层原来来说,因为其很复杂。
直观来说,Binder是Android中的一个类,它实现了IBinder接口。从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没有;从Android Framework角度来说,Binder是ServiceManager链接各种Manager和相应的ManagerService的桥梁;从android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。
首先,我们要明确的是,aidl文件的本质是系统为我们提供了一种实现Binder的工具,仅此而已。然后不管它不讨论。
通过aidl自动生成需要的类:(生成方法自己百度)
DESCRIPTOP:
Binder的唯一标识,一般用当前Binder的雷鸣表示
asInterface:
用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象。
asBinder:
此方法用于返回当前Binder对象。
onTransact:
这个方法运行在服务端中的BInder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理。该方法的原型为publich Boolean onTransact(.......省略)。服务端通过code可以确定客户端所请求的目标方法是什么,接着从data中取出目标方法所需的参数
(如果目标方法有参数的话)
,然后执行目标方法,当目标方法执行完毕后,就向reply中写入返回值
(如果目标方法有返回值的话)。
onTransact方法的执行过程就是这样的。需要注意的是,如果此方法返回false,那么客户端的请求会失败,因此我们可以利用这个特性来做权限验证,毕竟我们也不希望随便一个进程都能远程调用我们的服务。
Proxy#getBookList:
这个方法运行在客户端,当客户端远程调用此方法时,它的内部实现是这样的:首先创建该方法所需要的输入型Parcel对象_data、输出型
Parcel对象_reply和返回值对象List;然后把该方法的参数信息写入_data选中(如果有参数的话);接着调用transact方法来发起RPC(远程过程调用)请求,同事当前线程挂起;然后服务端的onTransact方法会被调用,知道RPC过程返回后,当前线程继续执行,并从
_reply中取出RPC过程的返回结果;最后返回
_reply中的数据。
Proxy#addBook:
这个方法运行在客户端,它的执行过程和getBookList是一样的,addBook没有返回,所以它不需要从_reply中取出返回值。
还有两点需要额外说明一下:首先,当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法是很耗时的,那么不能再UI线程中发起此远程请求;其次,由于服务端的Binder方法运行在Binder的线程池中,所以Binder方法不管是否耗时都应该采用同步的方式去实现,因为它已经运行在一个线程中了。
Binder中提供了连个配对方法linkToDeah和unlinkToDeath,通过linkToDeath我们可以给Binder设置一个死亡代理,当Binder死亡时,我们就会收到通知,这个时候我们可以重新发起连接请求从而恢复连接。另外,通过Binder的方法isBinderAlive也可以判断Binder是否死亡。
以上IPC基础知识完毕。