Android基础——初学者必知的AIDL在应用层上的Binder机制
初学者必知的AIDL在应用层上的Binder机制
首先得理解几个概念:
IPC:Inter-Process Communication,进程间的通信或跨进程通信。简单点理解,一个应用可以存在多个进程,但需要数据交换就必须用IPC;或者是二个应用之间的数据交换。
Binder:Binder是Android的一个类,它实现了IBinder接口。从IPC角度来说,Binder是Android中的一种跨进程通信方式。通过这个Binder对象,客户端就可以获取服务端提供的服务或数据,这里的服务包括普通服务和基于AIDL的服务。
AIDL:Android Interface Definition language,它是一种Android内部进程通信接口的描述语言。
一、AIDL的使用
服务端:
创建一个服务端工程,在工程中点击右键New->AIDL->AIDL File,默认直接点确定,这时会在工程中出现一个aidl文件:
我们打开这个aidl文件,我们创建一个我们需要测试的方法:
由于Android Studio是要手动编译才能生成对应AIDL的java文件,既然aidl文件是个接口,那就必须存在着实现这个接口的类,点击编译,系统自动生成一个java类,该java类的代码就是整个Binder机制的原理所在(会在下面第二步骤介绍原理):
既然是个服务端,那么我们就要开始写服务了,创建一个类,继承Service:
既然是个服务,就必须在manifests文件中配置:
到现在服务端写好了,开启模拟器启动这个程序,记得在代码中开启服务:
客户端:
在工程中点击右键New->Module,按默认确定,finish:
关键的一步来了,复制服务端的aidl整个文件夹(包括里面的包、aidl文件、完整无缺)粘贴到客户端对应放aidl的地方:
不要忘了,客户端还要手动编译:
好了我们来写客户端的代码(我们在MainActivity中放一个”AIDL“的按钮,先绑定服务,然后点击按钮调用):
测试结果(先开启服务端,开启服务后,接着开启客户端,绑定远程服务):
二、AIDL的Binder机制原理分析
分析原理:
我们来分析一下这个类
首先本身继承Iinterface,所以他也是个接口,接口中必须有方法,代码定位到结尾有2个方法。
这两个方法就是basicTypes和add,就是我们服务端的2个方法。
接着发现该接口中有1个内部类Stub,继承自本身(IMyAidlInterface)接口,代码定位到Stub类。
这个Stub有个构造方法、asInterface、asBinder、onTransact(先不介绍)。
接着发现该内部类Stub还有一个内部类,代码定位到Proxy(我们把它称为代理)类,也是继承自本身(IMyAidlInterface)接口,所以实现该接口的两个方法。
在这个类里面我们会发现有2个标识:用来区分两个方法,到底你远程请求哪个方法的唯一标识,代码定位到代理类的结尾。
回过头来,还记得我们客户端做了什么吗?答案:绑定一个服务,在回调方法获取一个接口(iMyAidlInterface),它是直接静态使用IMyAidlInterface里面的静态类Stub的asInterface的方法:(雅思高分作文好了我们去跟踪到Stub类asInterface这个方法)
代码定位到Stub类asInterface方法:
前面只是做一些判断、看一下最后一句话:我们将传过来的obj还是传给了它的代理类来处理,返回的是代理类的对象
所以在客户端的iMyAidlInterface=……,则是拿到它的代理类,好了,这个时候就看客户端调用代理类干嘛了:
他调用了代理类的add方法,代码定位到代理类的add方法:
你会发现,它把数据写进了_data里面,最后调用transact方法,传入_data数据,唯一标识Stub.TRANSACTION_add。
然后这个transact方法就是通过底层了,通过底层结束后,这些参数送到哪了?答案:底层会走到stub类中的onTransact方法,通过判断唯一标识,确定方法:
在这个地方将传过来的参数解包,readInt方法。然后调用this.add方法,this指的就是服务端,调用服务端的add的方法:
将得到的结果,写入reply:
最后一句话,最后返回系统的ontransact方法,传入结果reply:
所以我们在上面获得的结果就是reply(答案:3):
最后总结下整个过程
三、AIDL编写时候的一些错误
错误一:
这个错误很有可能是你写的服务端,忘记返回myS了,返回的是个null
错误二:
这个错误很有可能是的服务端在manifests文件中少了exported="true"的属性