遇到的问题
最近在看《Android开发艺术探索》,为了更深入了解一下Android通信机制,浅试了一下Android studio中实现AIDL,结果调试了一上午,看了好几遍文档,也没看出来有啥问题,但是都无法正常通信。
原来在API级别高于30的时候加入了限制,所以有两种办法:
方法一:把项目的 targetSdkVersion 版本修改到30以下
方法二:在manifest.xml下加入:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.myapplication">
<queries>
<package android:name="com.example.myaidlserver" />
</queries>
// 如果想要与其他的应用进行AIDL通信的话,需要在这里注册包名的信息
// 官方文档:https://developer.android.google.cn/guide/topics/manifest/queries-element?hl=en
<application
......
<activity
其他代码就不贴了,可以参考远程服务Service(含AIDL & IPC讲解)
预备知识
Binder是Android的一个类,继承于IBinder接口;
它是ServiceManager ----- ActivityManager、WindowManager、XXManagerService中的桥梁
生成的aidl.java文件解读
interface MyAidl implements IInterface{
// 默认实现
static class Default implements MyAidl{
int add(){return 0;}
}
IBinder asBinder(){return null;}
static abstract class Stub extends Binder implements MyAidl{
static MyAidl asInterface(IBinder obj){
return MyAdidl.Stub.Proxy(obj)
}
IBinder asBinder(){ return this; }
boolean onTranact(){ switch语句,代表着输入 }
setDefaultImpl(){ Stub.proxy.Impl = impl; }
static Proxy implements MyAidl{
Proxy(IBinder remote){ mRemote = remote; }
int add(){
remote.onTransact()
}
}
}
}
classDiagram
IMyAidl <|-- absStub
Stub <|-- Proxy
class IMyAidl{
Default
}
class absStub{
asInterface(IBinder obj)
asBinder()
onTranact()
}
class Proxy{
customOperation(
}
在生成的aidl.java中,有Aidl接口,以及Stub和Proxy两个实现了MyAidl接口的类。其中Stub定义在MyAidl接口中,Proxy定义在Stub类中。 为什么不把他们分开呢,为了防止有多个ADIL类时,Stub和Proxy重名,把他们套娃在aidl接口里,使用时就可以直接Aidl.Stub也直接方便。
Stub类继承了 Binder, 说明它是一个 Binder 本地对象,它实现了 IInterface 接口 Stub类中重要的是的asInterface方法和onTransact方法。 在Client中,我们会这么写:
MyAidl.Stub.asInterface(某IBinder对象).add(1, 2);
asInterface方法的作用是判断参数——也就是IBinder对象,和自己是否在同一个进程:
是的话则直接转换、直接使用
// 如果不是则把这个IBinder参数包装成一个Proxy对象
return new MyAidl.Stub.Proxy(obj)
// 再调用Stub的sum方法->间接调用Proxy的sum方法
// Proxy在自己的sum方法中,会使用Parcelable来准备数据
// 最后使用IBinder的transact方法传递参数,把数据就传给Binder的Server端了。
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0)
// _data中包含函数名称、函数参数,_reply接收函数返回值
在Server中,通过onTransact方法接收数据,找到对应方法,返回结果
总结
顺便总结一下AIDL:
- 其实这个过程中就是根据AIDL文件生成了一个java文件来实现进程间通信,我们完全可以自己写一个这样的ADIL.java文件
- ADIL其实就是是binder的延伸,binder在kennel层,ADIL在Framework层
- Messager也是AIDL封装的,但是它只能进行进程间通信
- 和ContentProvider相比呢,底层都是Binder
- AIDL的优势在于支持一对多并发实时通信
- ContentProvider可以理解为受约束的AIDL,它的优势在于使用方便,有强大的数据共享能力,比较适合在通讯录、日历使用
四大组件的启动和后续流程,都是在和AMS来来回回的通信,四大组件给AMS发消息,四大组件就是Client,而AMS就是Server;AMS发消息通知四大组件,角色就互换,就这样发送返回发送返回。为什么称为Android四大组件,我理解它们都是能够直接和AMS通信的,那么四大组件共同的源头是哪里呢?又是怎么样统一管理的?小伙伴们可能就会好奇了