本文主要罗列demo代码,包括客户端Activity,服务端远程service、aidl及其Java接口文件,用来描述客户端和服务端应用binder交互流程。
大概简述一下此示例代码的功能,有一个名为BookManagerService的远程服务,它持有一个用于保存Book对象的list,并对外提供该list的get和add方法。而客户端Activity绑定服务并访问其接口。
- 客户端Activity在onCreate时绑定BookManagerService,连接成功即可生成IBookManager对象,通过该对象可以访问BookManagerService的对外接口。
- BookManagerService设置了remote,是运行在另一个进程中的远程服务,在onCreate时为list加载两行数据,之后在onBind方法里返回serviceBinder对象。
首先是aidl文件:
//IBookManager.aidl
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}
//Book.aidl
parcelable Book;
其次是客户端Activity:
private IBookManager mRemoteBookManager;
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);
List<Book> list = bookManager.getBookList();
Book newBook = new Book(3, "Android进阶");
bookManager.addBook(newBook);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_manager);
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
最后是服务端BookManagerService:
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
private Binder mBinder = new serviceBinder();
@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "Android"));
mBookList.add(new Book(2, "Ios"));
}
public class serviceBinder extends IBookManager.Stub{
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
}
程序属于在不同进程绑定一个服务,初次运行的大致流程是这样的:
- 客户端Activity进程向AMS发送一个绑定 BookManagerService服务的请求(其实这也是个binder请求,因为AMS运行在系统服务进程中);
- AMS例行检查,首先检查BookManagerService是否已经注册,哪个APP注册的(这些信息是在app安装时解析manifest获取的),然后检查启动BookManagerService的进程是否存在,因为BookManagerService设置了remote,所以此时进程是不存在的,于是会先把Service信息存下来,绑定请求押后,去创建一个新的进程。
- 新进程启动后,通知AMS准备就绪,AMS就会把刚才保存的Service信息发送给新进程去启动Service(例如oncreate),service启动完成后通知AMS。
- 接着AMS会把绑定的请求再发给BookManagerService,BookManagerService调用onbind,给AMS返回一个binder对象。
- AMS把binder对象返回给客户端Acitivty(onServiceConnected被调用)
其实这些过程已经被android屏蔽了,应用上我们只需要关注两个对象,第一个是客户端Activity的onServiceConnected返回的BinderProxy对象,第二个是服务端BookManagerService的onBind返回的Binder对象。然而在应用上我们看到的是Stub和Proxy,Stub继承了Binder,而Proxy是BidnerProxy的包装类,不管BinderProxy还是Bidner都,它们实现了IBinder接口,可以用IBinder接收。
- IBookManager接口定义了getBookList和addBook方法,其中还继承了IInterface接口,多了个asBinder方法,接下的Stub和Proxy都实现了IBookManager接口。
- Stub类不仅继承了Bidner类还继承了IBookManager接口,而服务端BookManagerService的serviceBinder继承了Stub类,实现了getBookList和addBook方法(asBinder接口由Stub类实现),serviceBinder的对象mBinder被返回给AMS。
- 客户端Activity的onServiceConnected返回BinderProxy,通过IBookManager.Stub.asInterface方法包装成了Proxy对象,这样便可调用Proxy实现的getBookList和addBook方法,同时Proxy还实现了asBinder接口。
IBookManager接口:
public interface IBookManager extends IInterface {
static final String DESCRIPTOR = "com.example.testbinder.IBookManager";
static final int TRANSACTION_getBookList = (IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (IBinder.FIRST_CALL_TRANSACTION + 1);
public List<Book> getBookList()throws RemoteException;
public void addBook(Book book)throws RemoteException;
}
Stub类:
public static abstract class Stub extends Binder implements IBookManager {
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
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 IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@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);
}
@Override
public List<Book> getBookList() throws RemoteException {
// 待服务端实现
return null;
}
@Override
public void addBook(Book book) throws RemoteException {
// 待服务端实现
}
}
Proxy类:
private static class Proxy implements IBookManager {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public IBinder asBinder() {
return mRemote;
}
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public List<Book> getBookList()throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
List<Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.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(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
在下一篇文章中,描述binder通信过程。