一、AIDL是什么
它全称是Android Interface Definition Language,即Android接口定义语言,为了使其他的进程也可以访问本进程提供的服务,Android使用AIDL来公开服务的接口,它里面定义了本进程可以为其他进程提供什么服务,即定义了一些方法,其他进程就可以通过RPC(远程调用)来调用这些方法,从而获得服务,其中提供服务的进程称为服务端,获取服务的进程称为客户端。
二、AIDL接口的创建
AIDL接口用来暴露服务点提供给客户端的方法,新建一个AIDL接口文件,只需要在你的项目中 点击包名 -> 右键 -> new -> AIDL -> Aidl.file,然后输入AIDL接口名称,这里我输入了IUserManager,然后点击Finish,就会在你的main目录下创建了一个aidl文件夹,aidl文件夹里的包名和java文件夹里的包名相同,里面用来存放AIDL接口文件,如下:
在里面你会发现你刚刚创建的AIDL接口IUserManager,点进去,如下:
// IUserManager.aidl
package com.example.aidltest;
// Declare any non-default types here with import statements
interface IUserManager {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
里面声明了一个方法,写着AIDL支持的一些数据类型(int、long、boolean、float、double、String),除了这些,AIDL还支持其他的基本数据类型、ArrayList(里面的每个元素都要被AIDL支持)、HashMap(里面的每个元素都要被AIDL支持)、实现了Parcelable接口的对象和AIDL接口本身,还有AIDL接口中只支持声明方法,不支持声明静态常量。
其中如果要在AIDL接口文件中使用AIDL对象,必须显式的 import 进来,即使它们在同一个包内,还有如果在AIDL接口文件用到了Parcelable对象,必须新建一个和它同名的AIDL文件,并在其中声明它为parcelable类型,接下来我要使用User这个Parcelable对象,所以我要在aidl文件夹下新建一个和他同名的AIDL文件,如下:
然后在User.aidl中添加如下内容:
// User.aidl
package com.example.aidltest;
parcelable User;
在里面,我声明了User.java这个对象为parcelable类型,接下来把IUserManager中的basicTypes方法删除,添加一个根据用户姓名获得用户信息的方法,如下:
// IUserManager.aidl
package com.example.aidltest;
import com.example.adiltest.User;
interface IUserManager {
User getUser(String name);
}
在里面我显示的 import 了User这个AIDL文件,即使它们在同一个包内,并声明了一个getUser方法,这个方法将会在服务端实现,然后在客户端调用(RPC)。
三、根据AIDL接口生成 对应的Binder类
有了AIDL接口后我们需要根据AIDL接口生成客户端和服务端对应的Binder类,有两种方式生成,一种是通过SDK自动生成,另外一种是我们自己手动编码实现,其中能够进行手动编码实现的前提是基于对SDK自动生成的各种Binder类的充分理解,下面我们先来介绍SDK自动生成的Binder类。
3.1、SDK自动生成
我们在AS导航栏 Build -> ReBuild Project,SDK就会替我们在 app\build\generated\aidl_source_output_dir\debug\compileDebugAidl\out\包名 下生成一个IUserManager.java,它就是根据IUserManager.aidl文件生成的,里面没有缩进,所以看起来不习惯,使用快捷键ctrl+alt+L,格式化一下代码,如下:
//IUserManager.java
/**
* 1、IUserManager接口,getUser方法定义在其中
**/
public interface IUserManager extends android.os.IInterface {
/**
* 1、抽象类Stub,需要在远程服务端实现
*/
public static abstract class Stub extends android.os.Binder implements com.example.aidltest.IUserManager {
private static final java.lang.String DESCRIPTOR = "com.example.aidltest.IUserManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.example.aidltest.IUserManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.aidltest.IUserManager))) {
return ((com.example.aidltest.IUserManager) iin);
}
return new com.example.aidltest.IUserManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: