AIDL 全名 Android Interface Define Languange 用来建立进程间通信的接口,这里只介绍使用,不介绍原理。 首先要创建AIDL文件,定义AIDL接口,然后makeProject,在Production视图下gen目录能看到系统帮你生成的接口 定义AIDL接口注意的地方,接口中使用到的自定义类必须继承Parcelable,以支持序列化(在进程间传递的前提)接口继承Interface。自定义类作为AIDL接口必须声明是in或out或inout,输入输出类型参数。每引用一个其他类或者接口,都需要import。接口总使用的接口也必须是AIDL接口,接口监听数组使用RemotCallBackList,避免去除Listener出错,因为不是同一对象,传递的数据到另外一个进程生成一个新的相同的对象,要用Binder作为他们的唯一标识。onDestory时解除监听。 AIDL接口里的成员: 内部含有一个IBinder类型的Stub抽象类实现了定义的AIDL接口。主要使用这个来进行通信。Stub抽象类里还有一个Proxy代理类实现了定义的AIDL接口,不是同一个进程它就代替Stub进行通信。除此之外还有接口中定义的方法。 使用过程: 服务端:提供方法供调用的一端,建立一个Service,注册到ServiceManager中,里面声明一个Stub对象(Binder类型,在Service的onBind方法中返回此对象), 客户端:建立ServiceConnection实例,在onServiceConnected函数中的参数就是Service的onBind方法返回的对象。使用Stub对象的静态asInterface方法返回所定义的AIDL接口对象(因为Stub对象实现了AIDL接口)。就可以调用AIDL接口对象的定义的方法。onServiceConected函数是运行在UI线程中,所以不要做太耗时的操作。 最后bindService, 如果有多个AIDL接口要使用可以设计一个BinderPool,先返回一个Binder,它的接口方法就是根据参数不同返回其他Binder。 package com.example.administrator.test.aidl; public interface IOnNewBookArrivedListener extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.administrator.test.aidl.IOnNewBookArrivedListener { private static final java.lang.String DESCRIPTOR = "com.example.administrator.test.aidl.IOnNewBookArrivedListener"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.administrator.test.aidl.IOnNewBookArrivedListener interface, * generating a proxy if needed. */ public static com.example.administrator.test.aidl.IOnNewBookArrivedListener asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.example.administrator.test.aidl.IOnNewBookArrivedListener))) { return ((com.example.administrator.test.aidl.IOnNewBookArrivedListener)iin); } return new com.example.administrator.test.aidl.IOnNewBookArrivedListener.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_onNewBookArrived: { data.enforceInterface(DESCRIPTOR); com.example.administrator.test.aidl.Book _arg0; if ((0!=data.readInt())) { _arg0 = com.example.administrator.test.aidl.Book.CREATOR.createFromParcel(data); } else { _arg0 = null; } this.onNewBookArrived(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.example.administrator.test.aidl.IOnNewBookArrivedListener { 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 void onNewBookArrived(com.example.administrator.test.aidl.Book newBook) 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 ((newBook!=null)) { _data.writeInt(1); newBook.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_onNewBookArrived, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_onNewBookArrived = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public void onNewBookArrived(com.example.administrator.test.aidl.Book newBook) throws android.os.RemoteException; }
public class BookManagerService extends Service { private static final String TAG = "BMS"; private CopyOnWriteArrayList<Book>mBookList = new CopyOnWriteArrayList<>(); private RemoteCallbackList<IOnNewBookArrivedListener>mListener=new RemoteCallbackList<>(); 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); int count = mListener.getRegisteredCallbackCount(); Log.v("sss",count+""); mListener.beginBroadcast(); for(int i=0;i<count;i++) { mListener.getBroadcastItem(i).onNewBookArrived(book); } mListener.finishBroadcast(); }
@Override public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException { mListener.register(listener); }
@Override public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException { mListener.unregister(listener); }
};
@Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } } private IOnNewBookArrivedListener mlistener = new IOnNewBookArrivedListener.Stub() { @Override public void onNewBookArrived(Book newBook) throws RemoteException { Log.v("sss","书到了!"+newBook.bookName); } }; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iBookManager = IBookManager.Stub.asInterface(service); List<Book>list= null; try { list = iBookManager.getBookList(); Log.i("sss","listtype"+list.getClass().getCanonicalName()); iBookManager.registerListener(mlistener); } catch (RemoteException e) { e.printStackTrace(); } try { iBookManager.addBook(new Book(1,"我日")); } catch (RemoteException e) { e.printStackTrace(); } } Intent intent = new Intent(this,BookManagerService.class); bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
|