-
业务逻辑语境中,实现Service onBInd的那个app进程是服务端。技术上,A进程调用B进程的方法,B就是服务端;B调用A传递过来的callback方法,A就是服务端。
-
aidl接口参数的in out修饰符看的是技术上的服务端,数据流进就是in,数据流出就是out。实际上有更简单明确的理解,对于aidl接口的调用方,看到in参数就想:我把参数in进去就不用管了,对于out参数就想:我对这个参数我待会还得out出来用,有out参数的方法是同步阻塞的。inout具备双重特性
-
服务端拿到in参数的副本进行访问和修改,不会影响到客户端的实参。客户端调用方法时传入out参数,是不是实例对象无所谓,声明变量名 user = null,调用xxx(user),由于是out参数没有被binder驱动序列化到服务端,服务端拿不到也不关心user里在客户端那边的实例细节(服务端拿到的参数是binder驱动给的初始值没有意义),服务端创建一个user对象,处理好数据,赋值给user变量名,客户端那边的user变量就引用服务端实际处理的user对象的副本。客户端调用xxx(user),得等服务端xxx方法执行完处理完user数据,out参数aidl方法是一个同步阻塞的方法,不能用oneway修饰
-
aidl接口原生支持参数类型是基本数据类型和String类型,默认都是in。自定义参数类型分为两种一种是bean,得声明android.os.Parcelable接口,支持binder机制序列化/反序列化,一种是回调对象/监听器,也得声明为aidl interface,自定义参数类型最好显示声明in out
-
oneway修饰的方法,是异步的,不能有返回值,只能有in参数,调用处不用等待服务端方法实现处的执行结束。不加oneway默认是同步阻塞的,就像普通的方法调用一样,无论有无返回值,调用处都得等这个远程方法执行完,服务端方法执行完,才走调用处后续代码。
-
aidl接口实现跨进程通信是靠Android的binder机制,跨进程调用时要经过内核的binder驱动。服务端进程在内核binder驱动中映射一块缓存(binder内存映射技术),服务端可以访问。客户端通过binder驱动copy一次数据到缓存区,服务端就可以访问。
-
如果aidl接口的调用方和实现方在一个进程内,就不用走内核的binder驱动。
-
binder机制是Android系统中跨进程通信的核心,Broadcast、ContentProvider等都是依赖binder机制。aidl接口也是。
-
服务端定义aidl接口文件,Do.aidl,会被编译为一个java类,里面有接口存根Stub,里面定义abc三个方法,由上到下顺序,在Service onBind中实现Do.stub中的abc方法并返回binder对象。
-
客户端bindService异步请求绑定服务端service,连接回调走的是ServiceConnection中的方法。在什么线程调用bindService,客户端收到的连接回调就走在什么线程。
-
bindService时如果service端没有起来,会被拉起。建立连接后,系统会维护这个binder连接,如果服务端crash挂掉,系统会拉起服务端,保证连接的健壮性(一个项目的实践经验,有待确认)
-
客户端通过ServiceConnection的onServiceConnected方法拿到客户端binder对象的引用,通过Do.Stub.asInterface(binder)转化为程序里面可调abc方法的binder代理对象。
-
服务端和客户端都得有Do.aidl文件,双方都才能访问abc方法。互相复制一份相同的aidl文件,或者一方打包sdk给另一方集成
-
注意aidl的版本管理:aidl文件要具有"包名.类名"唯一性,Binder驱动会对双方的aidl文件里面定义的方法abc,按照顺序进行编号,编号->映射服务端对方法的实现。客户端调用方法时,传递方法编号,附带数值/可序列化的数据包作为参数,到Binder驱动中,binder驱动进行编号方法名映射,序列化/反序列化处理。
-
双方的aidl文件是相同的,都是包名.类名、方法定义、顺序都是一样的,举例编号1->a,2->b,3->c。最好双方aidl定义都一样,保持版本同步。如果服务端的aidl定义供很多客户端使用,下次改版时如果只是针对某个app aClient,不想大面积修改发版,增加一个方法d,得追加到最后,aidl文件同步给这个aClient,这个aClient和服务端都有编号1->a,2->b,3->c,4->d,其他客户端使用老版本aidl接口仍然是1->a,2->b,3->c,都可以编号方法映射正确。
-
如果双发都是1->a,2->b,3->c,现在服务端要改b为e,那么服务端1->a,2->e,3->c,客户端没改aidl定义,那么客户端仍然是1->a,2->b,3->c。那么客户端调用b时,告知binder驱动编号2,而在服务端2映射e方法,参数列表也可以能不一致,最终调用错乱,不符合业务逻辑。
-
aidl方法调用按照编号映射方法,而不是方法名匹配。当同一套aidl接口,涉及多端时,一定注意版本控制。注意同步/追加方法,绝对不能单方修改方法顺序
-
Binder驱动为服务端维护一个线程池,方法的调用是在那个线程时客户端的先择,服务端作为方法的实现端,被客户端调用时,方法执行在服务端binder线程中。
Android AIDL理解
银河系栋梁2026-01-26 9:51
相关推荐
松涛和鸣2 小时前
62、IIC通信解析掘根2 小时前
【jsonRpc项目】Dispatcher模块独行soc2 小时前
2026年渗透测试面试题总结-10(题目+回答)海星船长丶2 小时前
预编译与sql注入,正则回溯绕过,mysql常见绕过,报错注入7大常用函数studyForMokey2 小时前
【Android面试】Java & Kotlin语言zhojiew2 小时前
在EKS上使用LBC的GatewayAPI创建负载均衡器和扩展配置小五传输2 小时前
跨网文件摆渡系统是什么?详解其原理、应用与安全价值TTGGGFF2 小时前
告别繁琐命令行:自研多线程 SSH 极速文件传输助手(附 GitHub 源码)AlphaFinance2 小时前
Windows 服务器自动部署方案