1. 定义IBookManager接口
public interface IBookManager extends IInterface {
static final java.lang.String DESCRIPTOR = "qingfengmy.developmentofart._2activity.Manual.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);
public java.util.List<qingfengmy.developmentofart._2activity.aidl.Book> getBookList() throws android.os.RemoteException;
public void addBook(qingfengmy.developmentofart._2activity.aidl.Book book) throws android.os.RemoteException;
}
声明一个aidl性质的接口,只需要继承IInterface接口(接口继承接口)。定义两个业务方法和对应的ID,以及binder特有的唯一标识符DESCRIPTOR,一般为完整类名。
2. 实现Stub类
public class BookManagerImpl extends Binder implements IBookManager {
/**
* Construct the stub at attach it to the interface.
* 构建连接到接口的stub
*/
public BookManagerImpl() {
this.attachInterface(this, DESCRIPTOR);
}
@Override
public List<Book> getBookList() throws RemoteException {
// 待实现
return null;
}
@Override
public void addBook(Book book) throws RemoteException {
// 待实现
}
@Override
public IBinder asBinder() {
return this;
}
}
3. 添加Stub的子类Proxy
/**
* Cast an IBinder object into an IBookManager interface,
* generating a proxy if needed.
* <p/>
* 客户端连接服务端会通过该方法获得Binder,根据是否跨应用会返回IBookManager或者代理Proxy.
* 跨应用时返回代理,客户端拿到代理,调用方法时,实际是transact方法去调用onTransact的。
*/
public static IBookManager asInterface(IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof IBookManager))) {
return ((IBookManager) iin);
}
return new BookManagerImpl.Proxy(obj);
}
private static class Proxy implements IBookManager {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.util.List<Book> getBookList() throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
List<Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(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_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
4. onTransact方法
Binder中的方法定义
/**
* Default implementation is a stub that returns false. You will want
* to override this to do the appropriate unmarshalling of transactions.
*
* <p>If you want to call this, call transact().
*/
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {}
如果要调用binder中的onTransact方法,调用transact即可。transact是IBinder中定义的方法,Binder实现了IBinder,所以也有transact方法。如下
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
可见其中调用了onTransact方法,在方法之前和之后做了处理。之前把输入型对象data的dataPosition设为0;之后把输出型对象reply的dataPosition设为0.
transact翻译为办理,binder在里面处理业务。根据code判断是哪个方法,data是输入型,reply是输出型。
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
List<Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
Book _arg0;
if ((0 != data.readInt())) {
_arg0 = Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
开发中我们可以使用aidl,aidl的意义在于为我们提供了一种快速实现Binder的工具。它不是实现Binder的必须品,我们可以手写Binder。
5. 本应用使用自定义的Binder
public class ManualService extends Service {
// 服务中的binder是private
private BookManagerImpl bookManager;
public ManualService() {
bookManager = new BookManagerImpl();
}
@Override
public IBinder onBind(Intent intent) {
return bookManager;
}
}
public class ManualActivity extends AppCompatActivity {
ServiceConnection serviceConnection;
// 接口是暴露出来的
IBookManager bookManager;
Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manual);
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bookManager = BookManagerImpl.asInterface(service);
Log.e("aaa","-----onServiceConnected-----");
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
intent = new Intent(this, ManualService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
// click-调用getBookList方法
bookManager.getBookList();
// onDestroy
}
6. 跨应用调用服务
和aidl一样,首先创建包名类名一样的几个文件
qingfengmy.developmentofart._2activity.aidl.Book
qingfengmy.developmentofart._2activity.Manual.BookManagerImpl
qingfengmy.developmentofart._2activity.Manual.IBookManager
客户端调用
IBookManager iBookManager;
ServiceConnection serviceConnection;
Intent intent;
intent = new Intent();
intent.setAction("qingfengmy.developmentofart.ManualService");
intent.setPackage("qingfengmy.developmentofart");
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service != null) {
iBookManager = BookManagerImpl.asInterface(service);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
// click点击事件调用服务端方法
iBookManager.getBookList();
7. likeToDeath和unlikeToDeath
Binder运行在服务端,如果服务端进程由于某种原因异常终止,这个时候我们连接服务端的Binder连接断裂(称之为Binder死亡),会导致我们的远程调用失败。
如果我们不知道Binder连接已经断裂,那么客户端的功能就会受影响。解决方法是给Binder设置死亡代理,当Binder死亡时,我们就会收到通知,这个时候我们就可以重新发起连接请求从而恢复连接。
// 定义死亡代理 recipient翻译为收件人
final IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
// binder死亡时,会回调这个方法
if (bookManager == null){
return;
}
bookManager.asBinder().unlinkToDeath(this,0);
bookManager = null;
// 重连
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
};
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bookManager = BookManagerImpl.asInterface(service);
// 设置死亡代理
service.linkToDeath(mDeathRecipient,0);
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
8. isBinderAlive
该方法用于判断Binder的状态
bookManager.asBinder().isBinderAlive();