AIDL文件中的asInterface
这个方法是用来将服务端的Binder对象转换成客户端所需的AIDL接口类型对象,这种转换时区分进程的,那么如何区分呢?咱们先做一个实验,创建一个Service,在一个Activity中绑定它,然后再将Service设置为与Activity同一进程和不再同一进程两种情况,并打印出ServiceConnection
中绑定成功返回的IBinder,结果如下:
同一进程时
非同一进程时
从Log日志可以看出,当同一进程时,返回IBinder是BookServices$1,我们知道$表示的是BookServices中的内部类,而在BookServices的定义中,我们只在mBinder的初始化中定义了一个IBookManager.Stub()的子类,即同进程时,在onServiceConnected接收到的是IBookManager.Stub()类型。
先看下asInterface
的代码:
public static com.example.administrator.ipctest.IBookManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.administrator.ipctest.IBookManager))) {
return ((com.example.administrator.ipctest.IBookManager)iin);
}
return new com.example.administrator.ipctest.IBookManager.Stub.Proxy(obj);
}
从代码中可以看出,区分是否在同一进程主要由obj.queryLocalInterface(DESCRIPTOR)
决定,那么再看queryLocalInterface
的源码:
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
从代码中可以看到,其实是对传入的descriptor与mDescriptor进行比较,那么mDescriiptor又是怎么定义的呢?
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
原来是在attachInterface
中定义的,不过是不是很眼熟?因为attachInterface
函数是在Stub的构造函数中被调用的this.attachInterface(this, DESCRIPTOR);
,所以在queryLocalInterface
中的比较结果肯定为true,那么返回的mOwner也就是Stub本身了。
当然这是在同一进程的情况下,那么当服务端和客户端不在同一进程时呢?
由上面的log可知,跨进程调用时,onSericeConnected中接收到的service为android.os.BinderProxy类型,从上面的源代码可以看出,当queryLocalInterface
返回为空时,asInterface
返回的就是android.os.BinderProxy类型。
那么还有一个问题:为什么同一进程下回返回Stub,而不同进程下回返回BinderProxy呢?