从AIDL浅析Binder机制
文章目录
AIDL(Android Interface Defination Language),Android接口定义语言。是Google专门为Android中跨进程调用服务所设计的一种接口语言。
其本质是Android中特有的一种IPC机制:Binder机制。通过对AIDL的分析我们也可以对Binder机制有所了解
AIDL的使用
首先让我们简单回顾一下AIDL是如何使用的。下面的操作基于Android Studio。
- 创建AIDL文件
在Project视图下,在/src/main/下创建与java同级的aidl文件夹,并在该文件夹下创建包名(例:com.example.diov.testaidl),在该文件夹下创建AIDL文件
package com.example.diov.testaidl;
interface TestAidl {
void add(int i);
}
在这个接口文件中定义Service需要实现的方法。
- 实现AIDL中的方法
创建完AIDL文件后,通过Gradle编译。编译成功后可以在/generated/source/debug/{packagename}/下找到生成的TestAidl.java文件。
然后我们回到Service中,实现AIDL接口中定义的方法
public class IRemoteService extends Service{
// 绑定服务时将IBinder对象返回出去
@Override
public IBinder onBind(Intent intent){
return iBinder;
}
private IBinder iBinder = new TestAidl.Stub(){
@Override
public int add(int i, int j) throws RemoteException {
// 具体实现
return i + j;
}
}
}
- 调用AIDL
在Client里按照第一步,把相同的AIDL文件创建出来。
绑定Service需要调用bindService(Intent intent, ServiceConnection conn, int flag)
方法。
这里主要是实现ServiceConnection接口,在这个接口的回调方法中就可以得到对应的服务所提供IBinder对象了
private TestAidl aidl;
private ServiceConnection conn = new ServiceConnection{
// 绑定成功时回调
@Override
public void onServiceConnected(ComponentName name, IBinder service){
// 获取到了远程服务
aidl = TestAidl.Stub.asInterface(service);
}
// 解除绑定时回调
@Override
public void onServiceDisconnected(ComponentName name){
aidl = null;
}
}
获取到IBinder对象后,就可以实现IPC,调用远程服务了。
AIDL的实现原理
现在来看看AS自动帮我们生成的TestAdil.java这个文件
package com.example.diov.testaidl;
public interface TestAidl extends android.os.IInterface {
/**
* 存根类,实现了Binder和TestAidl接口(IInterface接口)
*/
public static abstract class Stub extends android.os.Binder implements com.example.dio_v.materialdemo.TestAidl {
private static final java.lang.String DESCRIPTOR = "com.example.dio_v.materialdemo.TestAidl";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* 将IBinder对象转换成com.example.diov.testaidl.TestAidl接口,
* 如果需要的话生成一个代理.
*/
public static com.example.dio_v.materialdemo.TestAidl asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.dio_v.materialdemo.TestAidl))) {
return ((com.example.dio_v.materialdemo.TestAidl) iin);
}
return new com.example.dio_v.materialdemo.TestAidl.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
// 当Client调用Service时,获取代理类发送过来的数据
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws
android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_add: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
// 通过子类来实现方法中具体的操作,并将结果通过reply对象返回出去
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
// 代理类,实现了TestAidl接口(IInterface接口)
private static class Proxy implements com.example.dio_v.materialdemo.TestAidl {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public int add(int i, int j) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
// 通过序列化将参数发送
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(i);
_data.writeInt(j);
// 通过Framework将序列化后的参数发送给IBinder对象
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
// 通过返回的reply将Service返回的结果解析出来
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
// 接口中的方法
public int add(int i, int j) throws android.os.RemoteException;
}
- 在Client中绑定Service,会通过
TestAdil.Stub.asInterface()
方法去转换返回的IBinder对象(Stub继承的Binder类是IBinder接口的实现类),得到的是一个Proxy类对象 - Proxy类将参数序列化之后,通过Framework将参数发送给
Service.onBind()
返回的IBinder对象 - Service中返回的IBinder对象(Stub对象),通过具体实现来完成对参数的操作,并且将返回值封装在一个Parcel对象中
- Framework层将封装后的Parcel对象再返回给Proxy对象
- Proxy对象从Parcel对象中获取返回值
Binder机制
其实在Binder机制中存在一个重要的角色,ServiceManager,他是Service和Client中IPC交互的重要一环。ServiceManager负责在Framework层将参数传递、返回Proxy对象等等
而在Client,并不是真正持有了Service中的对象,而是通过ServiceManager,借助Proxy对象来完成跨进程通信。所以说Binder机制使用的其实就是/代理模式/。
对于Binder机制,我也还只是对概念有初步的了解。想要深入了解Binder机制,还需要继续学习。
资料推荐:
文章作者 Dio.Ye
上次更新 2016-03-20