本文主要罗列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通信过程。