zoukankan      html  css  js  c++  java
  • 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"的属性 

  • 相关阅读:
    Python max() 函数
    Python log10() 函数
    Python log() 函数
    Python fabs() 函数
    Java开源-astar:A 星算法
    9款超绚丽的HTML5/CSS3应用和动画特效
    Java中处理异常的9个最佳实践
    Java泛型
    Android界面性能调优手册
    正确使用Android性能分析工具——TraceView
  • 原文地址:https://www.cnblogs.com/zhanglixina/p/9597625.html
Copyright © 2011-2022 走看看