美文网首页
Android通信之IPC——AIDL

Android通信之IPC——AIDL

作者: 阳光的nick_lxz | 来源:发表于2018-08-10 17:35 被阅读0次

    用个例子来解释,首先客户端调用服务端的方法添加书籍,然后服务端每5秒自己新添加一本书籍,并且通知客户端。

    服务端

    建一个AIDL文件,将暴露给客户端的这个接口在这个AIDL文件中声明,首先要创建一个Service用来监听客户端的连接请求,实现这个AIDL的接口即可。
    1.创建AIDL文件,并声明所需要的方法,如下声明了四个方法。由于里面用到了Book这个类,要记得导包,及时在一个包下都需要导。

    // IBookManager.aidl
    package com.demo.nick.ipcstudy;
    
    // Declare any non-default types here with import statements
    import com.demo.nick.ipcstudy.Book;
    import com.demo.nick.ipcstudy.IOnNewBookArrivedListener;
    interface IBookManager {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
         List<Book> getBookList();
         void addBook(in Book book);
         void registerListener(IOnNewBookArrivedListener listener);
         void unregisterListener(IOnNewBookArrivedListener listener);
    }
    

    创建监听。

    package com.demo.nick.ipcstudy;
    
    // Declare any non-default types here with import statements
    import com.demo.nick.ipcstudy.Book;
    interface IOnNewBookArrivedListener {
      void onNewBookArrived(in Book book);
    }
    

    2.编写Service

    public class BookManagerService extends Service {
        private static final String TAG = "BookManagerService";
        private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();//书本集合
        //客户端监听器集合 beginBroadcast和finishBroadcast必须配对使用
       private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList=new RemoteCallbackList<>();
        private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);//是否销毁的标记
    //    private CopyOnWriteArrayList<IOnNewBookArrivedListener> mListenerList = new CopyOnWriteArrayList<>();
        //实现我们刚刚创建的AIDL接口
        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);
            }
    
            @Override
            public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
    //            if (!mListenerList.contains(listener)) {
    //                mListenerList.add(listener);
    //            }else {
    //                Log.e(TAG, "already exists: " );
    //            }
                mListenerList.register(listener);
                int a=mListenerList.beginBroadcast();
                Log.e(TAG, "当前监听器个数 "+a );
                mListenerList.finishBroadcast();
    //            Log.e(TAG, "registerListener监听器个数: "+mListenerList.size());
            }
    
            @Override
            public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
    //       if(mListenerList.contains(listener)){
    //           mListenerList.remove(listener);
    //           Log.e(TAG, "解除成功: " );
    //       }else {
    //           Log.e(TAG, "没有可解除的: " );
    //       }
    //            Log.e(TAG, "当前监听器个数 "+mListenerList.size() );
    //        }
                mListenerList.unregister(listener);
                int a=mListenerList.beginBroadcast();
                Log.e(TAG, "当前监听器个数 "+a );
                mListenerList.finishBroadcast();
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
            mBookList.add(new Book(1, "android"));
            mBookList.add(new Book(2, "ios"));
            new Thread(new ServiceWorker()).start();
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        @Override
        public void onDestroy() {
            mIsServiceDestoryed.set(true);
            super.onDestroy();
        }
    
        private void  onNewBookArrived(Book book) throws RemoteException {
            mBookList.add(book);
            final int N=mListenerList.beginBroadcast();
            for (int i=0;i<N;i++){
                IOnNewBookArrivedListener listener=mListenerList.getBroadcastItem(i);
                if (listener !=null) {
                    listener.onNewBookArrived(book);
                }
    
            }
            mListenerList.finishBroadcast();
        }
    
        private class ServiceWorker implements Runnable{
    
            @Override
            public void run() {
                //循环添加新书籍
                while (!mIsServiceDestoryed.get()){
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    int bookId=mBookList.size()+1;
                    Book newBook=new Book(bookId,"new book"+bookId);
                    try {
                        onNewBookArrived(newBook
                        );
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    客户端

    绑定服务端的Service,将服务端返回的Binder对象转换成AIDL接口所属的类型,就可以调用AIDL中的方法了。

    public class BookManagerAty extends AppCompatActivity {
        private static final String TAG = "BookManagerAty";
        private static final int MESSAGE_NEW_BOOK_ARRIVED=1;
        private IBookManager mRemoteBookManager;
        private Handler mHandler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case MESSAGE_NEW_BOOK_ARRIVED:
                        Log.e(TAG, "new BOOK: "+msg.obj );
                    break;
                default:
                    super.handleMessage(msg);
                }
    
            }
        };
        private ServiceConnection mConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                IBookManager bookManager=IBookManager.Stub.asInterface(service);
                try {
                    mRemoteBookManager=bookManager;
                    List<Book> list=bookManager.getBookList();
                    Log.e(TAG, "onServiceConnected: "+list.getClass().getCanonicalName());
                    Log.e(TAG, "onServiceConnected: "+list.toString() );
                    Book book=new Book(3,"java");
                    bookManager.addBook(book);
                    List<Book> newList=bookManager.getBookList();
                    Log.e(TAG, "onServiceConnected: "+newList.toString() );
                    bookManager.registerListener(mOnNewBookArrivedLisener);//注册监听
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mRemoteBookManager=null;
                Log.e(TAG, "onServiceDisconnected: " );
            }
        };
        private IOnNewBookArrivedListener mOnNewBookArrivedLisener=new IOnNewBookArrivedListener.Stub() {
            @Override
            public void onNewBookArrived(Book book) throws RemoteException {
                mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRIVED,book).sendToTarget();
            }
    
        };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_book_manager_aty);
            Intent intent=new Intent(this, BookManagerService.class);
            bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            if (mRemoteBookManager!=null&&mRemoteBookManager.asBinder().isBinderAlive()){
                Log.e(TAG, "onDestroy: "+mOnNewBookArrivedLisener );
                try {
                    mRemoteBookManager.unregisterListener(mOnNewBookArrivedLisener);//解除监听
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
    
            }
            unbindService(mConnection);
            super.onDestroy();
        }
    }
    
    

    这个时候我们的远程服务任何人都可以连接的,所以我们要做权限认证,
    在Mainfest文件中自定义一个权限

       <permission
            android:name="com.demo.nick.ipcstudy.permission.TEST"
            android:protectionLevel="normal"></permission>
    

    然后修改Service中的onBind方法,

        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            //验证权限,自定义个权限,防止其他人连接我们的服务.
            int check=checkCallingOrSelfPermission("com.demo.nick.ipcstudy.permission.TEST");
            if (check== PackageManager.PERMISSION_DENIED){
                //没有权限返回空,这样就绑定不了我们服务了。
                return null;
            }
            return mBinder;
        }
    
    

    相关文章

      网友评论

          本文标题:Android通信之IPC——AIDL

          本文链接:https://www.haomeiwen.com/subject/bsisextx.html