对AIDL的理解

本文详细介绍了Android中AIDL(Android Interface Definition Language)的工作原理及其应用场景。内容覆盖了AIDL的基本类型、数据流向控制以及如何在客户端和服务端之间实现交互的具体步骤。同时,还深入分析了AIDL的源码实现,帮助开发者更好地理解和使用AIDL。
摘要由CSDN通过智能技术生成

AS只有build之后才能将.aidl文件转换为.java文件

AILD(只支持方法,不支持静态变量)语法 

基本类型

  1)Java的4类8种基本类型。byte,short(因为Parcel不支持short,而AIDL的底层需要Parcel传数据,所以AIDL也不支持short),int,long,float,double,char.(基本类型默认且只能是in);

 2)String,Charsequence;

 3)List,map(底层是靠arrayList,HashMap实现,所以发送换是接收得要是这2种)

 4)Parcelable接口的实现类;

除了1)不标数据流向之外,2),3),7)作为方法参数需要表示数据的流向.数据流向用in,out,inout表示.

in--->表示数据由客户端流向服务端,服务端的修改不会同步到客户端--->_arg0 = data.readInt();

out--->表示数据由服务端流向客户端,服务端的改变会同步到客户端--->服务端会新建一个空对象,并将服务端对此对象的修改写给reply,传给客户端。

_arg0 = new com.example.iadlserver.Person();
java.util.List<java.lang.String> _result = this.basicTypes(_arg0);
reply.writeNoException();
reply.writeStringList(_result);
inout--->表示数据既可以从服务端流向客户端,也可以从客户端流向服务端,从客户端传给服务端的数据会同步到服务端,服务端的修改会同步到客户端----->将客户端传过来的数据接收下来,传给service中对接口的实现方法进行处理,并将服务端的修改传递给客户端。
if ((0!=data.readInt())) {
_arg0 = com.example.iadlserver.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
java.util.List<java.lang.String> _result = this.basicTypes(_arg0);
reply.writeNoException();
reply.writeStringList(_result);

 

AIDL具体实现:

服务端:

定义AIDL接口,Parcelable接口的实现类需要import包,即使该实现类和aidl文件在同一个包。因为AIDL在aidl文件夹下,java文件在java文件夹下,AS的默认gradle在java文件夹,将实现Parcelable接口的java文件放在aidl文件夹下,则AS不能gradle,实现Parcelable接口的java文件放在java文件夹下,则aidl不能使用。为了解决这种问题。解决方案有2种:

解决方案一:将实现Parcelable接口的java文件放在java文件夹下,但在aidl文件夹定义一个该实现类的aidl文件,并用parcelable声明该类。

解决方案二:将实现Parcelable接口的java文件放在aidl文件夹下,改变AS默认的gradle方式,找到build。gradle文件,在Android{}中添加该语句

服务端应该开启一个Service去接收客户端的请求。实现该AIDL接口的.Stub对象

在该实现类中写服务端的处理流程。

在onbind()方法中返回。

客户端:将服务端的AIDL文件拷贝到客户端,若有Parcelable接口的实现类,按照服务端的方法操作。客户端启动Service,从Android5.0之后,Service只能通过显示启动,

绑定的服务,必须在onDestroy()中解绑服务。

这样就可以在客户端听过mBind操作服务端的方法了。

AIDL源码分析

aidl接口的.java文件的整体框架,包括一个stub和在aidl接口中声明的方法.

IMyAidlInterface.Stub.asInterface(iBinder)的返回值是一个Proxy(代理),关键代码如下:

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.iadlserver.IMyAidlInterface))) {
return ((com.example.iadlserver.IMyAidlInterface)iin);
}
return new com.example.iadlserver.IMyAidlInterface.Stub.Proxy(obj);
若客户端的 iBinder和服务端在同一个进程,则返回Stub对象 。否则,返回代理。

Proxy是在内部类Stub中的一个类,Stub的主要方法:

 public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags);
第一个参数表示某个方法,aidl将方法编号,根据编号执行不同的代码。data,reply封装客户端传递的参数和返回给客户端的参数。
返回值表示客户端的请求能否成功。
测试数据流向:
客户端:代码:
Person person=new Person(24,"zhangce");
Person person2=new Person(24,"zhangce");
Person person3=new Person(24,"zhangce");
try {
    Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());
    mBind.basicTypes(person,person2,person3);
    Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());
} catch (RemoteException e) {
    e.printStackTrace();
}
结果:
MainActivity:out person Person{userName='zhangce',userId=24} in person Person{userName='zhangce',userId=24} 
inout person Person{userName='zhangce',userId=24} 
MainActivity:out person Person{userName=null,userId=0} in person Person{userName='zhangce',userId=24} 
inout person Person{userName='zhangce',userId=23} 

服务端:
代码 :
Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());
person.setUserId(23);
person2.setUserId(23);
person3.setUserId(23);
Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());
结果:
MainActivity:out person Person{userName=null,userId=0} in person Person{userName='zhangce',userId=24} 
inout person Person{userName='zhangce',userId=24} 
MainActivity:out person Person{userName=null,userId=23} in person Person{userName='zhangce',userId=23} 
inout person Person{userName='zhangce',userId=23} 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值