Android aidl的理解和使用
理解:
底层是binder。代码上就是接口,使用interface声明,但其中只能使用简单数据类型,复杂数据类型如某类则需要创新其对应aidl文件并实现相关函数才能使用
作用:
获取跨进程binder并调用其中相关内容
实例:
IPackageManager mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService(“package”));
IPackageManager 是aidl文件
ServiceManager.getService(“package”)返回值是binder对象
- IPackageManager负责通信。IPackageManager接口类中定义了很多业务方法,但是由于安全等方面的考虑,Android对外(即SDK)提供的仅仅是一个子集,该子集被封装在抽象类PackageManager中。客户端一般通过Context的getPackageManager函数返回一个类型为PackageManager的对象,该对象的实际类型是PackageManager的子类ApplicationPackageManager。ApplicationPackageManager并没有直接参与Binder通信,而是通过mPM成员变量指向了一个IPackageManager.Stub.Proxy类型的对象
- AIDL中的Binder服务端是PackageManagerService,因为PackageManagerService继承自IPackageManager.Stub。由于IPackageManager.Stub类从Binder派生,所以PackageManagerService将作为服务端参与Binder通信。
- AIDL中的Binder客户端是ApplicationPackageManager中成员变量mPM,因为mPM内部指向的是IPackageManager.Stub.Proxy
解释:
假设你是一个公司的商务负责人,正在和客户商谈事务,在涉及公司的具体业务的同事,你要请示你的老板,你需要给你老板打电话,交流商务谈判的具体细节,这里面,你就是应用进程里面的ApplicationPackageManager,IPackageManager就是你们的通信工具——电话,你老板就是SystemServer进程里面的PackageManagerService,你的电话就是IPackageManager.Stub.Proxy,老板的电话是IPackageManager.Stub。IPackageManager其实就是一个具体业务场景下的数据交换的工具而已。
解释底层Binder
Android 系统跨进程通讯的底层实现都是通过 Binder 实现,正常情况下客户端进程发起一个远程方法调用的流程大致如下:
1. 客户端线程发起调用;
2. 客户端线程将远程调用操作交给 Binder 线程池,并阻塞等待返回远程方法执行完毕返回;
这也就意味着,我们不能在客户端进程的 UI 线程中发起远程方法调用,不然如果远程方法执行了耗时操作,客户端的 UI 线程将会被阻塞,从而造成 ANR 的问题存在。读者可以自行尝试自定义 aidl 并发起一个耗时的远程方法调用进行验证。但是,如果你使用系统提供的 Messenger ,则不会出现这样的问题,无论你的远程方法执行多么耗时,客户端 Messenger 发起调用后会继续执行接下来的代码,并不会进行阻塞等待。这里让我百思不得其解,为什么呢?前面我们可以看到 Messenger 的 send 方法实现是在 MessengerImpl 中
并且,发送 Messeage 的操作是利用主线程的 Handler ,并没有其他的异步操作,为何执行的过程中不阻塞?这点我也完全没有想明白,最后折腾半天无果向任玉刚老师求助才得到答案。原来,默认情况下发起的远程方法调用都是阻塞式的,但也可以是非阻塞式的。 Messenger 就是采用非阻塞的方式通讯,其关键就在于 IMessenger.aidl 的实现
相比平常自定义的 aidl,多了 oneway 的关键字,声明和不声明 oneway 关键字的在于生成 Java 类中一个参数
不声明 oneway 时,mRemote.transact 传入的最后一个参数是 0;声明 oneway 时,mRemote.transact 传入的最后一个参数是 android.os.IBinder.FLAG_ONEWAY 。
查看 API 文档即可以看到 FLAG_ONEWAY 的作用就是让客户端能够非阻塞的调用远程方法,如果我们自定义的 aidl 也想实现非阻塞的调用,只需声明 oneway 关键字即可。
本文来自博客园,作者:小汀,转载请注明原文链接:https://www.cnblogs.com/1118zjg/p/16009902.html