AIDL生成的类解析

AIDL生成的类解析

首先我们有一个如下的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_getBookListTRANSACTION_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;
    }
}

你可能感兴趣的:(aidl,Android)