一、概述
AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。目的是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信。
AIDL的语法和Java是一样的,只是在一些细微处有些许差别:
-
文件类型:用AIDL书写的文件的后缀是 .aidl,而不是 .java。
-
数据类型:AIDL默认支持一些数据类型,在使用这些数据类型的时候是不需要导包的,但是除了这些类型之外的数据类型,在使用之前必须导包。默认支持的数据类型包括:Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。String 类型。CharSequence类型。
List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。List可以使用泛型。
Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的。 -
定向tag:AIDL中的定向 tag 表示了在跨进程通信中数据的流向,其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。另外,Java 中的基本类型和 String ,CharSequence 的定向 tag 默认且只能是 in 。注意:不要滥用定向 tag ,而是要根据需要选取合适的,全都用 inout ,等工程大了系统的开销就会大很多。
-
两种AIDL文件:AIDL文件大致可以分为两类。一类是用来定义parcelable对象,以供其他AIDL文件使用AIDL中非默认支持的数据类型的。一类是用来定义方法接口,以供系统使用来完成跨进程通信的。
二、简单使用
2.1 服务端实现
数据类
首先要定义两个进程间通信的数据类,由于不同的进程有着不同的内存区域,并且它们只能访问自己的那一块内存区域。所以我们必须将要传输的数据转化为能够在内存之间流通的形式。这个转化的过程就叫做序列化与反序列化。选择的序列化方式是实现 Parcelable
接口。
@Parcelize
data class Book(var name: String? = null, var price: Int = 0) : Parcelable {
fun readFromParcel(dest: Parcel) {
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
name = dest.readString()
price = dest.readInt()
}
}
在kotlin中,中实现 Parcelable
非常简单首先,在所属模块的 build.gradle 文件中应用 kotlin-parcelize 插件,然后在定义的实体类添加 @Parcelize
注解,并实现 Parcelable 接口即可。注意:添加 @Parcelize
注解生成器就会自动创建writeToParcel()
/ createFromParcel()
方法,但不会生成readFromParcel()
方法,而如果要支持为 out 或者 inout 的定向 tag 的话,还需要实现 readFromParcel()
方法
plugins {
id 'com.android.application'
id 'kotlin-android'
/*序列化插件*/
id 'kotlin-parcelize'
}
书写AIDL文件
鼠标移到app上面去,点击右键,然后 new->AIDL->AIDL File
Book.aidl
// Book.aidl
package com.matt.myaidltest.ipc;
//注意parcelable是小写
parcelable Book;
BookManager.aidl
// BookManager.aidl
package com.matt.myaidltest.ipc;
import com.matt.myaidltest.ipc.Book;
interface BookManager {
//所有的返回值前都不需要加任何东西,不管是什么数据类型
List<Book> getBooks();
//传参时除了Java基本类型以及String,CharSequence之外的类型
//都需要在前面加上定向tag,具体加什么量需而定
void addBook(in Book book);
}
注意:Book.kt 的包名要与 Book.aidl 一致,不然会会报 Symbol not found 的错误
如果包名路径不一致的话,修改 build.gradle 文件:在 android{} 中间加上下面的内容:
sourceSets {
main {
java.srcDirs = ['src/main/java', 'src/main/aidl']
}
}
在写完AIDL文件后,需要Rebuild Project一下项目,生成相应文件,然后再编写Server
编写服务端代码
/**
* 服务端的AIDLService
*
*/
class AIDLService : Service() {
val TAG = this.javaClass.simpleName
//包含Book对象的list
private var list: MutableList<Book> = mutableListOf()
//由AIDL文件生成的BookManager
private val mBookManager: BookManager.Stub = object : BookManager.Stub() {
override fun