Binder对象
是android中的一个类,实现了IBinder接口,是一种android中实现跨进程通信的一种方式,可以ManagerService连接各种Manager(LayoutManager,ServiceManager,ActivityManager,SensorManager等等)和各种相应ManagerService的桥梁。
AIDL文件之自动生成的java文件
每次书写aidl文件之后,系统会自动生成相应的java文件,比如本人自己写的一个aidl文件:
// IBookManager.aidl
package micro.com.chapter2.inter.aidl;
// Declare any non-default types here with import statements
import micro.com.chapter2.inter.aidl.Book ;
import micro.com.chapter2.inter.aidl.Person ;
import micro.com.chapter2.inter.aidl.INewBookArriveListener ;
interface IBookManager {
List<Book> getBooks();
void addBook(in Book book) ;
void addPerson(in Person p);
}
系统自动生成的IBookManager.java文件是:
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package micro.com.chapter2.inter.aidl;
public interface IBookManager extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements micro.com.chapter2.inter.aidl.IBookManager {
private static final java.lang.String DESCRIPTOR = "micro.com.chapter2.inter.aidl.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an micro.com.chapter2.inter.aidl.IBookManager interface,
* generating a proxy if needed.
*/
public static micro.com.chapter2.inter.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof micro.com.chapter2.inter.aidl.IBookManager))) {
return ((micro.com.chapter2.inter.aidl.IBookManager) iin);
}
return new micro.com.chapter2.inter.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_getBooks: {
data.enforceInterface(DESCRIPTOR);
java.util.List<micro.com.chapter2.inter.aidl.Book> _result = this.getBooks();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
micro.com.chapter2.inter.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = micro.com.chapter2.inter.aidl.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_addPerson: {
data.enforceInterface(DESCRIPTOR);
micro.com.chapter2.inter.aidl.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = micro.com.chapter2.inter.aidl.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements micro.com.chapter2.inter.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<micro.com.chapter2.inter.aidl.Book> getBooks() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<micro.com.chapter2.inter.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBooks, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(micro.com.chapter2.inter.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(micro.com.chapter2.inter.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();
}
}
@Override
public void addPerson(micro.com.chapter2.inter.aidl.Person p) 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 ((p != null)) {
_data.writeInt(1);
p.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBooks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
public java.util.List<micro.com.chapter2.inter.aidl.Book> getBooks() throws android.os.RemoteException;
public void addBook(micro.com.chapter2.inter.aidl.Book book) throws android.os.RemoteException;
public void addPerson(micro.com.chapter2.inter.aidl.Person p) throws android.os.RemoteException;
}
其中重要属性和方法说明如下:
1.DESCRIPTOR:
Binder中唯一的标识,自动生成时用当前Binder类名表示。
static final int TRANSACTION_getBooks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
三个声明的整型的id用于标识在transact过程中客户端中请求的到底是哪个方法。
2.asInterface(android.os.IBinder object)
将服务端的Binder对象转换成客户端所需AIDL接口类型的对象,转换是区分进程的,客户端和服务器在同一进程中,返回的是服务端Stub本身,否则就返回系统封装后的Stub.proxy对象。
3.asBinder
返回当前的Binder对象
4.onTransact
本方法运行在服务器端中Binder线程池中,客户端发起跨进程请求时,远程请求会通过系统底层封装后交给此方法来处理:
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
通过code确定客户端方法的方法,然后从data中取得参数(如果存在参数的话),然后执行在服务端的目标方法,执行完成之后,向reply中写入返回值(如果客户端中需要返回值的话)。当然onTransact方法是有返回值的,如果返回false,那么客户端就会请求失败。
5.Proxy#getBookList
在客户端中运行,当客户端远程调用此方法时,内部实现方法如下:先创建所需的输入型Parcel对象_data,输出型Parcel对象 _replay和返回值对象List。先将需求参数写入_data中,接着调用transact方法发起远程调用(RPC)请求,同时当前线程会挂起,然后服务端的onTransact方法会被调用,当RPC方法结束返回后,当前线程从挂起状态变成重新运行状态,并从_reply中取出RPC过程的返回结果,最后返回 _reply中的数据。 基本图解如下:
linkToDeath & unlinkToDeath
Binder运行在服务端进程,如果服务进程由于某种原因异常终止,此时服务端的Binder链接断裂(Binder死亡),会导致我们的远程调用失败。更为关键的是,不知道Binder链接断裂,那么客户端的功能就会受影响。为了解决这个问题,Binder中提供了两个配对的方法lineToDeath和unlinkToDeath,通过linktoDeath可以Binder设置死亡代理,Binder死亡时会受到死亡通知,此时可以重新发起连接请求从而恢复链接。
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.d(TAG,"binder died...");
//unlinkToDeath
xxx.unlinkToDeath(mBinderPoolDeathRecipient,0);
//restart server or rebinding ServiceConnection
}
} ;
在客户端绑定远程服务成功后,给binder设置死亡代理:
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
try {
//linktoDeath
xxx.linkToDeath(mBinderPoolDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {}
} ;
基本上通过以上两个步骤,就会给我们的Binder设置死亡代理,当Binder死亡的时候就会受到相应的通知了。