美文网首页
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