最近一直在看Android开发艺术探索的IPC机制,做下笔记。
首先新建三个文件,Book.java,Book.aidl,IBookManager.aidl
然后Rebuild Project一下,我们可以看到系统为IBookManager.aidl生产的类,通过Ctrl+N查找IBookManager.java
package com.ffm.bindertest; public interface IBookManager extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.ffm.bindertest.IBookManager { private static final java.lang.String DESCRIPTOR = "com.ffm.bindertest.IBookManager"; /** * Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.ffm.bindertest.IBookManager interface, * generating a proxy if needed. */ public static com.ffm.bindertest.IBookManager asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.ffm.bindertest.IBookManager))) { return ((com.ffm.bindertest.IBookManager) iin); } return new com.ffm.bindertest.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<com.ffm.bindertest.Book> _result = this.getBookList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addBook: { data.enforceInterface(DESCRIPTOR); com.ffm.bindertest.Book _arg0; if ((0 != data.readInt())) { _arg0 = com.ffm.bindertest.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 com.ffm.bindertest.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<com.ffm.bindertest.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<com.ffm.bindertest.Book> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); _reply.readException(); _result = _reply.createTypedArrayList(com.ffm.bindertest.Book.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void addBook(com.ffm.bindertest.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(); } } } 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<com.ffm.bindertest.Book> getBookList() throws android.os.RemoteException; public void addBook(com.ffm.bindertest.Book book) throws android.os.RemoteException; }
DESCRIPTOR
Binder的唯一标识
asInterface(android.os.IBinder obj)
用于将服务端的Binder对象转换成客户端所需的AIDL借口类型的对象,如果客户端和服务端是同一进程,返回的是服务端的Stub对象本身;否则返回的是系统封装后的Stub.proxy对象。
asBinder
返回当前Binder对象。
onTransact
这个方法运行在服务端的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理。
Proxy中的getBookList和addBook方法都运行在客户端。
再看下客户端代码
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, BookManagerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IBookManager manager = IBookManager.Stub.asInterface(service); try { manager.getBookList(); manager.asBinder(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onDestroy() { unbindService(mConnection); super.onDestroy(); } }
bindService成功后在onServiceConnected方法中,可以拿到服务端的Binder对象。通过asInterface(android.os.IBinder obj)方法,可以将服务端的Binder对象转换成Stub.proxy对象,这个对象是AIDL接口类型的对象。通过这个对象调用getBookList()方法,此方法是运行在客户端的。然后看下IBookManager.Sutb.proxy中的getBookList()方法,mRemote调用transact方法,mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); 这个时候客户端的线程挂起,然后会执行服务端的onTransact()方法。在onTransact()方法中,java.util.List<com.ffm.bindertest.Book> _result = this.getBookList();是服务端进程的方法实现
public class BookManagerService extends Service { @Override public void onCreate() { super.onCreate(); mBookList.add(new Book(1, "Android")); mBookList.add(new Book(2, "Ios")); } @Override public IBinder onBind(Intent intent) { return mBinder; } private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList(); private Binder mBinder = new IBookManager.Stub() { @Override public List<Book> getBookList() throws RemoteException { return mBookList; } @Override public void addBook(Book book) throws RemoteException { mBookList.add(book); } }; }
拿到数据后将结果写在_reply中,回到Stub.Proxy的getBookList()方法中,客户端就能拿到数据了。