什么是AIDL?
AIDL是Android开发者实现跨进程通信使用的类,内部实现Binder机制,方便开发者调用。 AIDL类似一个中间代理,开发者想跨进程,使用AIDL,AIDL实现其中各种规则,实现Binder调用。
AIDL使用
先看一下AIDL在Android开发中的使用
创建两个工程,一个client发送端,一个Service服务端
1、client发送端重点代码
看下Client端代码架构,创建要使用的两个AIDL
IMyAidl AIDL 类
interface IMyAidl {
void addPerson(in Person person);
List<Person> getPersonList();
void setData(in byte[] data);
}
Person AIDL类
parcelable Person;
Person普通类,实现pracelable.
Activity中操作首先对服务端Service绑定
private void bindService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.enjoy.service", "com.enjoy.service.MyAidlService"));//需要交互的服务端注册的Service
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected: success");
iMyAidl = IMyAidl.Stub.asInterface(service);// proxy
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceDisconnected: success");
iMyAidl = null;
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
asInterface区分是跨进程还是不跨进程,得到AIDL,客户端申请操作
2、Service服务端代码
代码架构里两个AIDL类与客户端一致,多个Service类,这个Service类必须是按照包名规定跟客户端client 中的bindService一致
其他代码一致,看下Service代码
public class MyAidlService extends Service {
private ArrayList<Person> persons;
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<>();
Log.e("xjz111", "success onBind");
return iBinder;//返回一个Binder处理
}
private IBinder iBinder = new IMyAidl.Stub() {
@Override
public void addPerson(Person person) throws RemoteException {
Log.i("xjz111","服务端给你添加了一个Person");
persons.add(person);
}
@Override
public List<Person> getPersonList() throws RemoteException {
Log.i("xjz111","服务端给你返回一个PersonList");
return persons;
}
@Override
public void setData(byte[] data) throws RemoteException {
}
};
@Override
public void onCreate() {
super.onCreate();
Log.e("xjz111", "onCreate: success");
}
}
看下运行结果
可以看到已经成功实现了两个进程间的简单通信
AIDL解析
看完使用,发现很简单,但是AIDL在其中到底做了什么工作呢?
可以看到,在build里,根据我们定义的方法,生成了对应的方法体,和Stub
IMyAIDL:就是两个进程间交互的通信协议,协议必须一致。
看看stub类里生成了啥
Proxy:给client客户端使用,里面会实现具体需要操作的方法
asInterface():返回代理对象,区分跨进程还是不跨进程
asInterface拿到对象后,返回一个aidl对象,去调用addPerson代码
看下其中生成的addPerson()怎么实现的
@Override public void addPerson(com.enjoy.service.Person person) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();//数据包,客户端给服务端
android.os.Parcel _reply = android.os.Parcel.obtain();//服务端返回数据后,用来接收的包
try {//安全检测
_data.writeInterfaceToken(DESCRIPTOR);
if ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
//最后transact()给Binder
boolean _status = mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().addPerson(person);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
可以看到,addPerson()开始就用了两个数据包接收,通过 mRemote.transact()告诉Binder需要调什么方法,就是这个方法,让客户端跑到了服务端里去。
调方法的流程:
static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getPersonList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_setData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
给定义的方法标记初始值+1,2,3,4 最终通过flag找到要执行的方法
mRemote.transact()回调到服务端使用的onTransact()进行添加人员,数据返回的处理
@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)//根据传递的方法flag决定去执行哪个方法
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_addPerson:
{
data.enforceInterface(descriptor);
com.enjoy.service.Person _arg0;
if ((0!=data.readInt())) {
_arg0 = com.enjoy.service.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getPersonList:
{
data.enforceInterface(descriptor);
java.util.List<com.enjoy.service.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_setData:
{
data.enforceInterface(descriptor);
byte[] _arg0;
_arg0 = data.createByteArray();
this.setData(_arg0);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
Binder通过这个方法,让客户端发送时,传递方法的flag,在服务端调用onTransact()对执行完的数据进行操作返回,reply.writeTypedList(_result)代码意思就是把结果写到reply包(上面说的服务端返回给客户端的包)。