首先我们有一个如下的AIDL文件:
import com.xsx.ipcdemo.Booker;
interface IBookManager {
List getBookList();
void addBook(in Booker booker);
}
那么系统会在工程目录的build/generated/aidl/com/xsx/ipcdemo/aidl路径下面给我们生成如下的一个类文件:(具体路径视你的包名而定)
这是一个好长好长的东西,先稍微掠一眼
public interface IBookManager extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.xsx.ipcdemo.IBookManager {
private static final java.lang.String DESCRIPTOR = "com.xsx.ipcdemo.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.xsx.ipcdemo.IBookManager interface,
* generating a proxy if needed.
*/
public static com.xsx.ipcdemo.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.xsx.ipcdemo.IBookManager))) {
return ((com.xsx.ipcdemo.IBookManager) iin);
}
return new com.xsx.ipcdemo.IBookManager.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 {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
java.util.List _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.xsx.ipcdemo.Booker _arg0;
if ((0 != data.readInt())) {
_arg0 = com.xsx.ipcdemo.Booker.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.xsx.ipcdemo.IBookManager {
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 java.util.List getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.xsx.ipcdemo.Booker.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(com.xsx.ipcdemo.Booker booker) 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 ((booker != null)) {
_data.writeInt(1);
booker.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public java.util.List getBookList() throws android.os.RemoteException;
public void addBook(com.xsx.ipcdemo.Booker booker) throws android.os.RemoteException;
}
代码太多,咋们一点一点分开看。首先是如下一个接口类:
public interface IBookManager extends IInterface{
...
}
再来这个接口文件里有这么一些东西:
public interface IBookManager extends IInterface{
public static abstract class Stub extends Binder implements IBookManager{
...
}
public List getBookList() throws RemoteException;
public void addBook(Booker booker) throws RemoteException;
}
这么一看就很清楚了,生成的接口类IBookManager继承了IInterface接口(这里先知道所有可以在Binder中传输的接口都需要继承IInterface接口)
IBookManager里包含了一个内部类Stub,和两个方法。这两个方法是不是很眼熟,没错,就是我们之前在IBookManager.aidl文件里写的方法。
getBookList();addBook();都是待实现的方法
那么Stub又是什么,Stub继承了Binder类,说明它本身是一个Binder,现在继续看Stub里有什么内容,为了解释方便稍微调整了一下代码顺序,如下:
public static abstract class Stub extends Binder implements IBookManager{
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
private static final String DESCRIPTOR = "com.xsx.ipcdemo.IBookManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static IBookManager asInterface(IBinder obj) {
...
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
...
}
private static class Proxy implements IBookManager{
...
}
}
吓到了,Stub里这么多东西,不急,喝杯茶,一个一个看。
先看到两个整型的变量:
TRANSACTION_getBookList和TRANSACTION_addBook
干嘛用的呢,其实就是标记IBookManager接口里的两个方法,之后可以在onTransact中可以根据这个标记判断客户端所请求的是哪个方法。
DESCRIPTOR
Binder的唯一标识,一般用当前的Binder的类名表示
asInterface(IBinder obj)
用于将服务端的Binder对象转化为客户端所需的AIDL接口类型的对象;如果客户端和服务端位于同一进程,那么返回的是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy代理对象。
public static IBookManager asInterface(IBinder obj) {
if ((obj == null)) {
return null;
}
//查找obj对象是不是存在本地进程中
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//如果存在本地进程
if (((iin != null) && (iin instanceof IBookManager))) {
//返回Stub对象本身
return ((IBookManager) iin);
}
//否则返回代理对象
return new IBookManager.Stub.Proxy(obj);
}
首先判断传入的IBinder对象是否为空,为空直接返回。
obj.queryLocalInterface(DESCRIPTOR);
根据Binder的唯一标示在当前进程里查找接口,如果接口不为空,返回接口,否则返回接口的代理
asBinder
返回当前的Binder对象。
onTransact
当客户端向服务器端发送请求时会调用该方法
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
//code指明请求的是哪个方法,每一个服务里的方法都对应一个int变量
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
List _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
Booker _arg0;
//如果有传过来参数
if ((0 != data.readInt())) {
//将序列化流转化为对象
_arg0 = Booker.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
onTransact()从data参数里先取得要执行的方法所需的参数,然后执行目标方法,执行完方法之后再将方法的返回值写入reply中。如果没有带参数的话则忽略读取和写入的步骤。
在向reply回写内容前,先调用writeNoException()方法指明没有异常发生
Proxy
从名字上我们就可以看出这是个代理类,在asInterface方法中调用了,如果客户端和服务器端不在同一进程则返回该对象。
private static class Proxy implements IBookManager{
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public IBinder asBinder() {
return mRemote;
}
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public List getBookList() throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
List _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(Booker booker) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((booker != null)) {
_data.writeInt(1);
booker.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
Binder的工作机制流程图:
具体实现类,先实现IBookManager接口,再复写方法
public class BookManager implements IBookManager{
@Override
public List getBookList() throws RemoteException {
return null;
}
@Override
public void addBook(Booker booker) throws RemoteException {
}
@Override
public IBinder asBinder() {
return null;
}
}