Android AIDL使用
创始人
2024-05-30 10:02:01
0

一. 概述

Android 接口定义语言 (AIDL) 与您可能使用过的其他接口语言 (IDL) 类似。您可以利用它定义客户端与服务均认可的编程接口,以便二者使用进程间通信 (IPC) 进行相互通信。在 Android 中,一个进程通常无法访问另一个进程的内存。因此,为进行通信,进程需将其对象分解成可供操作系统理解的原语,并将其编组为可供您操作的对象。

二. 定义 AIDL 接口

在构建每个包含 .aidl 文件的应用时,Android SDK 工具会生成基于该 .aidl 文件的 IBinder 接口,并将其保存到项目的 gen/ 目录中。服务必须视情况实现 IBinder 接口。然后,客户端应用便可绑定到该服务,并调用 IBinder 中的方法来执行 IPC

AIDL 使用一种简单语法,允许您通过一个或多个方法(可接收参数和返回值)来声明接口。参数和返回值可为任意类型,甚至是 AIDL 生成的其他接口。

您必须使用 Java 编程语言构建 .aidl 文件。每个 .aidl 文件均须定义单个接口,并且只需要接口声明和方法签名。

默认情况下,AIDL 支持下列数据类型:

1. Java 编程语言中的8中基本类型(如 byte  char  boolean  short   int   float  long   double)

2. CharSequence类型,如String、SpannableString等;

3. List
List 中的所有元素必须是以上列表中支持的数据类型,或者您所声明的由 AIDL 生成的其他接口或 Parcelable 类型。您可选择将 List 用作“泛型”类(例如,List)。尽管生成的方法旨在使用 List 接口,但另一方实际接收的具体类始终是 ArrayList。

4. Map
Map 中的所有元素必须是以上列表中支持的数据类型,或者您所声明的由 AIDL 生成的其他接口或 Parcelable 类型。不支持泛型 Map(如 Map 形式的 Map)。尽管生成的方法旨在使用 Map 接口,但另一方实际接收的具体类始终是 HashMap。

5. 所有Parceable接口的实现类,因为跨进程传输对象时,本质上是序列化与反序列化的过程;

6. AIDL接口,所有的AIDL接口本身也可以作为可支持的数据类型;

有两个需要注意的地方:

1、在Java中,如果一个对象和引用它的类在同一个package下,是不需要导包的,即不需要import,而在AIDL中自定义的Parceable对象和AIDL接口定义的对象必须在所引用的AIDL文件中显式import进来,不管这些对象和所引用它们的AIDL文件是否在同一个包下

2、如果AIDL文件中使用到自定义的Parceable对象,则必须再创建一个与Parceable对象同名的AIDL文件,声明该对象为Parceable类型,并且根据上一条语法规定,在AIDL文件中进行显式import。

定义服务接口时,请注意:

1)方法可带零个或多个参数,返回值或空值方法前不能用 public/private/protected/final 等关键字修饰.
2)所有非原基本类型参数均需要指示数据走向的方向标记。这类标记可以是 in、out 或 inout(见下方示例) , 比如Parcelable 对象.

3)定向tag正确使用
AIDL中,除了基本数据类型,其他类型的方法参数都必须标上数据在跨进程通信中的流向:in、out或inout:

1、in表示输入型参数:只能由客户端流向服务端,服务端收到该参数对象的完整数据,但服务端对该对象的后续修改不会影响到客户端传入的参数对象;

2、out表示输出型参数:只能由服务端流向客户端,服务端收到该参数的空对象,服务端对该对象的后续修改将同步改动到客户端的相应参数对象;

3、inout表示输入输出型参数:可在客户端与服务端双向流动,服务端接收到该参数对象的完整数据,且服务端对该对象的后续修改将同步改动到客户端的相应参数对象;

如果tag用的inout的话,在写自定义的Parcelable类时,必须要重写此方法,不然就会报错

public void readFromParcel(Parcel parcel)

定向tag需要一定的开销,根据实际需要去确定选择什么tag,不能滥用。
 

写到这里也顺便复习一下 Parcelable 基础知识

Parcelable 是 Android 特有的序列化接口:

public interface Parcelable {//writeToParcel() 方法中的参数,用于标识当前对象作为返回值返回//有些实现类可能会在这时释放其中的资源public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;//writeToParcel() 方法中的第二个参数,它标识父对象会管理内部状态中重复的数据public static final int PARCELABLE_ELIDE_DUPLICATES = 0x0002;//用于 describeContents() 方法的位掩码,每一位都代表着一种对象类型public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001;//描述当前 Parcelable 实例的对象类型//比如说,如果对象中有文件描述符,这个方法就会返回上面的 CONTENTS_FILE_DESCRIPTOR//其他情况会返回一个位掩码public int describeContents();//将对象转换成一个 Parcel 对象//参数中 dest 表示要写入的 Parcel 对象//flags 表示这个对象将如何写入public void writeToParcel(Parcel dest, int flags);//实现类必须有一个 Creator 属性,用于反序列化,将 Parcel 对象转换为 Parcelable public interface Creator {public T createFromParcel(Parcel source);public T[] newArray(int size);}//对象创建时提供的一个创建器public interface ClassLoaderCreator extends Creator {//使用类加载器和之前序列化成的 Parcel 对象反序列化一个对象public T createFromParcel(Parcel source, ClassLoader loader);}
}

写一个自定义的ParcelableObj类

public class ParcelableObj implements Parcelable {//元素nameprivate String mName;//构造法方法public ParcelableObj(String name){mName = name;}protected ParcelableObj(Parcel in) {mName = in.readString();}//序列化@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(mName);}/*内容描述*/@Overridepublic int describeContents() {return 0;}//反序列化public static final Creator CREATOR = new Creator() {//反序列创建对象@Overridepublic ParcelableObj createFromParcel(Parcel in) {return new ParcelableObj(in);}//反序列创建对象数组@Overridepublic ParcelableObj[] newArray(int size) {return new ParcelableObj[size];}};
}

通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,因此写的顺序和读的顺序必须一致.

三. 编写AIDL文件

AS中可以通过 new AIDL 自动创建一个aidl文件, 内容根据需求自定义编写.

在AndroidStudio中工程目录的Android视图下,右键new一个AIDL文件,

默认将创建一个与java文件夹同级的aidl文件夹用于存放AIDL文件aidl文件夹下的包名与build.gradle中配置的applicationId一致applicationId默认值是应用的包名

例子一 :普通的基本类型数据

// IMyAidlInterface.aidl
package com.example.myclient;// Declare any non-default types here with import statementsinterface IMyAidlInterface {String querybyID(int n);
}

注意事项:  aidl 接口方法中 不能加 public/ private/ protected/final 修饰符;否则就会报错

例子二:  aidl中 用到了自定义Parcelable对象

new 一个完整的app工程, 然后在new 一个 AIDL文件, 工程结构图如下:

PathParceTest.java  implement 实现  Parcelable类

public class PathParceTest implements Parcelable

对于用到自定义Parcelable对象的aidl文件, 创建的规则如下:

1.  自定义的Parcelable对象和AIDL对象必须要显示的import进来,不管他们是否和当前的AIDL文件位于同一个包内.

2. 如果AIDL文件中用到了自定义的Parcelable对象, 那么必须新建一个和它同名的AIDL文件, 并在其中声明它为Parcelable类型.

第2条在代码中体现如下:

比如ITest.aidl 用到了  PathParceTest对象, 那么我们先得写一个PathParceTest类, 然后创建 一个同名的PathParceTest.aidl文件

 上面是创建AIDL文件的语法规则, 按照规则书写代码即可,不然会报错.

对于例子二, 假如你在服务端已经写好了这些aidl代码, 现在要拷贝到客户端, 根据规则, 创建的aidl 必须保持包名一致拷贝过去,  但是你的PathParceTest.java是在服务端的src/main/java/com.example.myaidl/ 路径下,   如果要拷贝过去的话, 文件包名(路径名)在客户端又得新建,然后把PathParceTest.java放置在此路径下.  那么客户端的代码结构非常的难看.

那么,有没有什么更好优化解决办法呢?目的把aidl包所有文件整体拷贝就完事

如果我们把PathParceTest.java放置到同aidl包下,  在编译的时候会报错,提示这个类找不到.

 原因:

我们是在src/main/aidl文件夹下创建PathParceTest.java的,实际上这将因为找不到PathParceTest.java而报错,因为在AndroidStudio中使用Gradle构建项目时,默认是在src/main/java文件夹中查找java文件的,如果把PathParceTest.java放在src/main/aidl对应包名下,自然就会找不到这个文件了,所以需要修改app的build.gradle文件,在sourceSets下添加对应的源文件路径,即src/main/aidl

android {compileSdkVersion 33//加上这段代码 把 src/main/aidl/路径下的java文件也编译进来sourceSets {main {java.srcDirs = ["src/main/java", "src/main/aidl"]}}//加上这段代码 把 src/main/aidl/路径下的java文件也编译进来defaultConfig {applicationId "com.example.myaidl"minSdkVersion 16targetSdkVersion 33versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"................

这样子就解决了上述的问题, 当然客户端中也得加上这段代码, 接下来我们就可以直接拷贝整个aidl包了.

四. 总结

        本文主要讲解了AIDL的语法规则和创建AIDL文件的注意点, 特别是引用自定义Parcelable对象的aidl文件创建注意事项. 也是为后续写 进程间通信机制 相关的文章做个铺垫.


 

相关内容

热门资讯

有没有主角是植物的修仙小说?多... 有没有主角是植物的修仙小说?多多益善。落花时节又逢君,花妖的侧重爱情的极品超能少年
痞子蔡《第一次亲密接触》经典话... 痞子蔡《第一次亲密接触》经典话语我在你香烟上写下自己的名字...这不是补肾的方法,这样的做法也是错误...
鸟兽和木匠读后感 鸟兽和木匠读后感鸟兽和木匠读后感 《鸟兽与木匠》读后感 星期天,我读了一本书,叫《鸟兽与木...
高富帅的具体标准是什么? 高富帅的具体标准是什么?高富帅没有固定标准随着时代不同估计高会变更高富会更多才算是富帅,不同人心中的...
求,嫁给一个死太监的全文 求,嫁给一个死太监的全文密码:82cm
获奖过的讲文明,懂礼貌的手抄报... 获奖过的讲文明,懂礼貌的手抄报有哪些很多你可以去网上搜一定会有你需要的
孟母三迁原文及翻译 孟母三迁原文及翻译孟母三迁原文及翻译如下:【原文】邹孟轲母,号孟母。其舍近墓。孟子之少时,嬉游为墓间...
好看技术流的网游小说 好看技术流的网游小说网游之盗版神话网游之纵横天下网游之双手剑等等的!!!这基本不错给分啊!!!!
女孩于海24小时一元一分正规麻... 加V【ab120590】【hf420624】【mj120590】红中癞子、跑得快,等等,加不上微信就...
关注麻将24小时红中麻将群@... 微【ab120590】 【mj120590】【hf420624】等风也等你。喜欢打麻将的兄弟姐妹们、...
揭秘一元一分红中麻将群202... 微【ab120590】 【mj120590】【hf420624】(广东一元一分红中癞子爆炸码麻将群)...
玩家必看正规一块红中麻将群全面... 1.进群方式《ab120590》或者《mj120590》《hf420624》--QQ(4434063...
时下最流行资讯一块一分24小时... 一元一分麻将群加群主微【ab120590】【hf420624】 【mj120590】等风也等你。喜欢...
到哪里找盘点十大一元一分麻将群... 微【ab120590】 【mj120590】【hf420624】(广东一元一分红中癞子爆炸码麻将群)...
《西瓜视频》24小时不熄火跑的... 群主微信:【ab120590】 【mj120590】【hf420624】没有三缺一的无奈,手机上的麻...
哪里寻找一元一分红中麻将群20... 1.亮点:一元红中麻将微信“群”—ab120590—hf420624—mj120590—客服Q443...
推荐正规红中麻将跑的快群202... 微【ab120590】 【mj120590】【hf420624】等风也等你。喜欢打麻将的兄弟姐妹们、...
参观一元红中麻将群2024已更... 微【ab120590】 【mj120590】【hf420624】等风也等你。喜欢打麻将的兄弟姐妹们、...
西瓜视频上下分正规红中麻将群@... 加V【ab120590】【hf420624】【mj120590】红中癞子、跑得快,等等,加不上微信就...
我来教大家广东24小时在线一元... 认证群主微信微【ab120590】 【mj120590】【hf420624】(一元俩元红中麻将)(跑...