Android AIDL相关
前言
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
AIDL
全称(Android Interface Definition Langague)
三种类型
AIDL
- IPC(Inter-Process Communication,进程间通信),多线程,多个应用程序。
Binder
- 只有IPC(Inter-Process Communication,进程间通信),没有多线程,多个应用程序。
Messenger
- 只有IPC(Inter-Process Communication,进程间通信),没有多线程。
实现步骤
创建.aidl文件
- 跟创建一个接口文件一样创建.aidl文件。
- Eclipse编译后会放在gen目录下。
- Android Studio直接创建AIDL目录,跟java目录同级,直接创建AIDL文件。
- Android Studio默认不编译,需要编译后才会在Debug目录下显示出来。
实现接口(Implement the interface)
- 创建一个继承Service的类,里面创建一个IBinder来实现Aidl.Stub里面的方法的IBinder类型的变量。
共享接口给客户端(Expose the interface to clients)
- 将onBind方法返回的IBinder设置成定义的IBinder变量。
客户端那里同样创建一个.aidl文件,同样的包名。
- 客户端绑定Service,使用Intent显示Intent启动,在5.0以后不支持隐式调用。
Intent intent = new Intent();
// 新版本5.0必须显式Intent启动绑定服务
intent.setcomponent(new ComponetName("包名","包名.类名");
- 客户端绑定Service,
bindService(intent, conn, Context.BIND_AUTO_CREATE);
。 - 客户端创建ServiceConnection变量,实现接口。
private ServiceConnection conn = new ServiceConnection(){
// 绑定服务的时候
@Overrive
public void onServiceConnected(ComponentName name, IBinder service){
// 拿到远程服务
iImoocAidl = IImoocAidl.Stub.asInterface(service);
}
// 断开服务的时候
@Overrive
public void onServiceDisconnected(ComponentName name){
iImoocAidl = null;
}
}
- 服务端的AndroidManifest.xml文件中添加service,需要添加name,exported,enabled,process。
- 客户端使用接口定义的方法。
注意
- 更新aidl文件的内容要,要卸载后再运行,才有用。
- 除了默认的类型外,都需要导包。
- 不支持short是因为序列化添加不了short类型。
AIDL支持的数据类型
基本的数据类型(byte,int,long,char,boolean,float,double,不支持short)
String,CharSequence
List,Map(必须是支持的类型,也就是不支持short,需要设置in或out或inout属性in List<String> aList
)
Parcelable(需要设置in或out或inout属性)
服务端创建实现Parcelable的实体类,如Person,创建构造方法、get、set方法,并且重写未实现的方法。
在
writeToParcel(Parcel dest, int flags)
方法里面写入数据。
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
- 创建CREATOR变量,在createFromParcel(Parcel source)方法里面返回new Person(source)。
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person[] newArray(int size) {
return new Person[size];
}
@Override
public Person createFromParcel(Parcel source) {
return new Person(source);
}
};
- 创建相应的构造方法,并且按顺序读取数据。
public Person(Parcel source) {
// 按顺序
this.name = source.readString();
this.age = source.readInt();
}
创建实体类对应的aidl文件,如Person.aidl。
parcelable Person;
在主aidl文件内import对应的实体类,并且创建对应的方法,Parcelable也要设置in或out或inout属性。
import com.example.aidlservice.Person;
interface AidlTestInterface {
List<Person> add(in Person person);
}
- 设置Service。
private ArrayList<Person> persons;
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<Person>();
return iBinder;
}
private AidlTestInterface.Stub iBinder = new Stub() {
@Override
public List<Person> add(Person person) throws RemoteException {
persons.add(person);
return persons;
}
};
将对应的实体类文件,实体类aidl文件,主aidl文件复制到客户端,包名必须一致。
客户端调用对应的方法。
AIDL原理
* Stub.asInterface(Ibinder)访问的是Proxy。
* Proxy通过发送code请求给Stub里面的OnTransact方法。