步骤
1、定义接口,继承IInterface,自定义两个方法
interface IBookManager extend IInterface{
void add(Book book) throws RemoteException;
List<Book> getList() throws RemoteException;
}
2、 定义一个静态抽象内部类:Stub
需要继承Binder 同时实现IBookManager
构造方法需要注册Binder
注册方法为attachInterface,需要传入自己和一个唯一标识DESCRIPTOR
需要定义自定义方法的唯一标识
interface IBookManager extend IInterface{
void add(Book book) throws RemoteException;
List<Book> getList() throws RemoteException;
public static abstract Stub extend Binder implement IBookManager{
//唯一标识用于注册该BInder,用包名+接口名定义
private static final String DESCRIPTOR="com.xxx.xxx.IBookManager";
//getList方法唯一标识
static final int TRANSACTION_getList = (IBinder.FIRST_CALL_TRANSACTION + 0);
//add方法唯一标识
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION + 1);
public Stub(){
//注册该binder
this.attachInterface(this, DESCRIPTOR);
}
}
}
3、 Stub需要实现几个方法
asInterface:共有静态方法,供客户端获取IBookManager
onTransact:跨进程方法处理会经过该方法
asBinder:获取当前binder
interface IBookManager extend IInterface{
void add(Book book) throws RemoteException;
List<Book> getList() throws RemoteException;
public static abstract Stub extend Binder implement IBookManager{
//唯一标识用于注册该BInder,用包名+接口名定义
private static final String DESCRIPTOR="com.xxx.xxx.IBookManager";
//getList方法唯一标识
static final int TRANSACTION_getList = (IBinder.FIRST_CALL_TRANSACTION + 0);
//add方法唯一标识
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION + 1);
public Stub(){
//注册该binder
this.attachInterface(this, DESCRIPTOR);
}
public static IBookManager asInterface(IBinder obj){
if ((obj == null)) {
return null;
}
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//查询当前进程
if (((iin != null) && (iin instanceof Stub))) {
return (Stub) iin;//当前进程返回IBookManager
}
return new Stub.Proxy(obj);//非当前进程返回Proxy
}
//该方法会处理通过代理类传递过来的方法标识code,参数载体data,返回值载体reply
//会通过code表示判断需要执行那个方法
//根据不同方法使用不同方式处理参数载体data,返回值载体reply
//返回true表示执行成功,所以该方法还可以进行权限判断
public boolean onTransact(){
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getList: {
data.enforceInterface(DESCRIPTOR);
List<Book> _result = this.getList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_add: {
data.enforceInterface(DESCRIPTOR);
Book _arg0;
if ((0 != data.readInt())) {
_arg0 = Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.add(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
public IBinder asBinder(){
return this;
}
}
}
4、定义私有的静态代理类Prxoy,
需要实现IBookManager接口
需要实现所有自定义方法
自定义方法的实现主要步骤和原理:
- 定义参数载体_data、返回载体_reply
- 处理参数(Book),放入_data
- 调用mRemote.transact,
- 传入code 、_data、 _reply
- transact方法最终会调用Stub的onTransact,onTransact中会将处理结果放入_reply
- 最后处理_reply,生成具体对象_result(List )并返回
interface IBookManager extend IInterface{
void add(Book book) throws RemoteException;
List<Book> getList() throws RemoteException;
public static abstract Stub extend Binder implement IBookManager{
//唯一标识用于注册该BInder,用包名+接口名定义
private static final String DESCRIPTOR="com.xxx.xxx.IBookManager";
//getList方法唯一标识
static final int TRANSACTION_getList = (IBinder.FIRST_CALL_TRANSACTION + 0);
//add方法唯一标识
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION + 1);
public Stub(){
//注册该binder
this.attachInterface(this, DESCRIPTOR);
}
public static void asInterface(IBinder obj){
if ((obj == null)) {
return null;
}
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//查询当前进程
if (((iin != null) && (iin instanceof Stub))) {
return (Stub) iin;//当前进程返回IBookManager
}
return new Stub.Proxy(obj);//非当前进程返回Proxy
}
//该方法会处理通过代理类传递过来的方法标识code,参数载体data,返回值载体reply
//会通过code表示判断需要执行那个方法
//根据不同方法使用不同方式处理参数载体data,返回值载体reply
//返回true表示执行成功,所以该方法还可以进行权限判断
public boolean onTransact(){
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getList: {
data.enforceInterface(DESCRIPTOR);
List<Book> _result = this.getList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_add: {
data.enforceInterface(DESCRIPTOR);
Book _arg0;
if ((0 != data.readInt())) {
_arg0 = Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.add(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
public IBinder asBinder(){
return this;
}
}
private static class Proxy implements IBookManager {
private IBinder mRemote;
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
public Proxy(IBinder obj) {
this.mRemote = obj;
}
//自定义方法的实现主要步骤和原理:
//定义参数载体_data,返回载体_reply
//处理参数(Book),放入_data
//调用mRemote.transact,
//传入code _data _reply
//该方法会调用Stub的onTransact,onTransact中会降返回结果放入_reply
//最后处理_reply,生成具体对象_result(List<Book> )并返回
@Override
public void add(Book book) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(TRANSACTION_add, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public List<Book> getList() throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
List<Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(TRANSACTION_getList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public IBinder asBinder() {
return mRemote;
}
}
}
至此一个完整的AIDL就手写完成。
实现思想:
当前进程:不需要处理数据的跨进程传递,所以可以直接使用接口
非当前进程:需要处理数据的跨进程传递,所以要使用代理接口,代理接口的作用是:处理数据的跨进程。而且看起来客户端得调用方式和同进程是一样的。