新建aidl文件夹:
在新建里的aidl文件夹中新建Java文件:其中Book实现了parcelable接口
Book代码:
package cqupt.second.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
public int bookId;
public String bookName;
public Book() {
}
public Book(int bookId, String bookName) {
this.bookId = bookId;
this.bookName = bookName;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(bookId);
out.writeString(bookName);
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
public Book createFromParcel(Parcel in) {
return new Book(in);
}
public Book[] newArray(int size) {
return new Book[size];
}
};
private Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
}
@Override
public String toString() {
return String.format("[bookId:%s, bookName:%s]", bookId, bookName);
}
}
创建aidl文件、创建Book.aidl、创建IBookManager.aidl:
Book.aidl中的代码:
package cqupt.second.aidl;
parcelable Book;
IBookManager.aidl中的代码:
package cqupt.second.aidl;
import cqupt.second.aidl.Book;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}
最终自动生成了IBookManager.java文件:
IBookManager.java中的代码:
package cqupt.second.aidl;
public interface IBookManager extends android.os.IInterface {
public java.util.List<cqupt.second.aidl.Book> getBookList()
throws android.os.RemoteException;
public void addBook(cqupt.second.aidl.Book book)
throws android.os.RemoteException;
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements cqupt.second.aidl.IBookManager {
private static final java.lang.String DESCRIPTOR = "cqupt.second.aidl.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);
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an cqupt.second.aidl.IBookManager interface,
* generating a proxy if needed.
*/
public static cqupt.second.aidl.IBookManager asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) &&
(iin instanceof cqupt.second.aidl.IBookManager))) {
return ((cqupt.second.aidl.IBookManager) iin);
}
return new cqupt.second.aidl.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<cqupt.second.aidl.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
cqupt.second.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = cqupt.second.aidl.Book.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 cqupt.second.aidl.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<cqupt.second.aidl.Book> getBookList()
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<cqupt.second.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data,
_reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(cqupt.second.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(cqupt.second.aidl.Book book)
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 ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
}
}
其中:DESCRIPTOR是Binder的唯一标识,一般用当前Binder类名表示
asInterface(android.os.IBinder obj):用于将服务端的Binder对象转换成客户端所需要的AILDL接口类型的对象,如果客户端与服务端在同一进程,返回服务端的Stub对象本身,否则返回系统封装后的Stub.proxy对象
asBinder():返回当前Binder对象
onTransact(int code, android.os.Parcel data,android.os.Parcel reply, int flags):运行在服务端的Binder线程池中,当客户端发起进程间请求,远程请求会通过系统封装之后交由此方法处理。服务端通过code可以确定客户端请求的目标方法是什么,接着从data中取出目标方法所需要的参数(如果目标方法有参数的话),然后执行目标方法。放执行完毕之后,向reply中写入返回值(如果有返回值的话)
Proxy类中的getBookList():客户端调用获取数据。将创建该方法所需要的参数:输入型Parcel对象_data、输出型Parcel对象_reply和返回值队形List写入该方法的参数_data中,然后调用transact方法发起RPC(远程过程调用)请求,同时线程被挂起,接着服务端调用onTransact()方法,RPC过程结束,当前线程继续执行,从_reply中取出RPC过程返回的数据,最后返回_reply中的数据
Proxy类中的addBook(cqupt.second.aidl.Book book):客户端调用,过程与getBookList()类似
注意:客户端发起请求后,当前线程会被挂起,直到服务端进程返回数据。
服务端的Binder方法运行在Binder线程池中。
给Binder设置死亡代理:
private IBookManager mRemoteBookManager;
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mRemoteBookManager == null) {
return;
}
mRemoteBookManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
mRemoteBookManager = null;
// TODO: 2017/2/12 重新绑定service
}
};
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
mRemoteBookManager = bookManager;
try {
mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};