通常,我们用aidl实现android上层进程间的通信, 除此之外,我们也可以用messenger来实现。 当然,
这俩者背后都是binder机制的实现,这里主要讲messenger的方式。
参考android4.0 bluetooth的源码,BluetoothHDPActivity.java, BluetoothHDPService.java这两个文件,其中,
Activity作为 client.
先看Server端,BuetoothHDPService.java
private class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { // Register UI client to this service so the client can receive messages. case MSG_REG_CLIENT: Log.d(TAG, "Activity client registered"); mClient = msg.replyTo; break; // Unregister UI client from this service. case MSG_UNREG_CLIENT: mClient = null; break; // Register health application. case MSG_REG_HEALTH_APP: registerApp(msg.arg1); break; // Unregister health application. case MSG_UNREG_HEALTH_APP: unregisterApp(); break; // Connect channel. case MSG_CONNECT_CHANNEL: mDevice = (BluetoothDevice) msg.obj; connectChannel(); break; // Disconnect channel. case MSG_DISCONNECT_CHANNEL: mDevice = (BluetoothDevice) msg.obj; disconnectChannel(); break; default: super.handleMessage(msg); } } } final Messenger mMessenger = new Messenger(new IncomingHandler()); @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); };
在server端, 定义了一个messenger,参数是一个Handler, 可以想到的是,这个Handler 一定是给 Client 去调用的,
并通过 onBind 方法, 返回了这个messenger的 binder对象(aidl的方式中,返回的是Server 的一个代理 finalIRemoteService.Stub mBinder=newIRemoteService.Stub() )
好了,我们看看,client 端, 通过bindService, 做了什么操作。
BluetoothHDPActivity.java,
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { mHealthServiceBound = true; Message msg = Message.obtain(null, BluetoothHDPService.MSG_REG_CLIENT); msg.replyTo = mMessenger; mHealthService = new Messenger(service);\ try { mHealthService.send(msg); } catch (RemoteException e) { Log.w(TAG, "Unable to register client to service."); e.printStackTrace(); } }
public void onServiceDisconnected(ComponentName name) { mHealthService = null; mHealthServiceBound = false; } };
这里, 我们看到,onServiceConnected 里,获取了server端的 messenger, 并通过send 的方式, 实现
了向 server 里的 handler 发送消息的功能,至此, 我们了解了, 通过messenger, 实现跨进程发送消息的功能.
在这段代码里, 他send 一个消息给server端, 看代码, msg.replyTo = mMessenger, 这里, 他有带了一个
client 端的mMessager 给server端,我们看mMessenger:
// Handles events sent by {@link HealthHDPService}. private Handler mIncomingHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { // Application registration complete. case BluetoothHDPService.STATUS_HEALTH_APP_REG: mStatusMessage.setText( String.format(mRes.getString(R.string.status_reg), msg.arg1)); break; //此处省略部分代码 case BluetoothHDPService.STATUS_DESTROY_CHANNEL: mStatusMessage.setText( String.format(mRes.getString(R.string.status_destroy_channel), msg.arg1)); mConnectIndicator.setText(R.string.disconnected); break; default: super.handleMessage(msg); } } }; private final Messenger mMessenger = new Messenger(mIncomingHandler);
这部分代码跟之前的代码一样, 功能也是一样的, 几可以将messenger对象带个server, 实现server向 client 发送消息。
通过上述介绍,利用messeger, 可以实现在 client和server之间相互发送消息, 个人觉得, 比aidl 的方式要好用些,
也容易理解些, aidl 的方式, 本文就不做过多的讲述。
总结:
1. 使用Messenger方式比使用AIDL的方式,实现起来要简单很多
2. 使用Messenger时,所有从Activity传过来的消息都会排在一个队列里,不会同时请求Service,所以是线程安全的。如果你的程序就是要多线程去访问Service,就可以用AIDL,不然最好使用Messenger的方式。