Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍 (2)

上面代码中ViewUtils.findAndOnClick()是博主封装的一个方法,功能只是绑定控件并为控件添加onClick监听器,无需重点关注,接下来运行工程点击按钮,在Android Monitor中将切换到remote进程,查看log如下:

.../cn.codingblock.ipc:remote I/MessengerHandler: handleMessage: MSG_FROM_CLIENT:client bind messenger succeed! 3、服务端如何回应客户端?

到上面这一步一个简单的Messenger通讯就完成了,接下在MessengerActivity中我们就可以使用Messenger对象向服务端发送数据了,但是如何才能得到服务端的回应呢,或者服务端想向客户端发送数据怎么办?

这个其实也很简单,我们只需要在客户端这里也创建一个Messenger,然后再向服务端发送数据时在Message的replyTo指向客户单的Messenger对象即可,如下:

message.replyTo = clientMessenger;

然后再服务端通过获取Message.replyTo,就可以获取到客户端的Messenger:

Messenger client = msg.replyTo;

具体实现如下:

在上面的MessengerActivity中增加一个Handler,并通过Handler创建一个Messenger,在向服务端发送一条消息时告诉服务器接收回复的messenger:

// 新增一个MessengerHandler private class MessengerHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case AppConstants.MSG_FROM_SERVICE: Log.i(TAG, "handleMessage: MSG_FROM_SERVICE:" + msg.getData().getString("msg")); break; default:super.handleMessage(msg); } } } // 创建一个clientMessenger private Messenger clientMessenger = new Messenger(new MessengerHandler()); private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 链接messenger成功,利用service创建一个Messenger messenger = new Messenger(service); // 向服务端发送一条消息 Message message = Message.obtain(null, AppConstants.MSG_FROM_CLIENT); Bundle bundle = new Bundle(); bundle.putString("msg", "client bind messenger succeed!"); message.setData(bundle); // 关键点,告诉服务器接收回复的messenger message.replyTo = clientMessenger; try { messenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { messenger = null; } };

在上面的MessengerService中获取客户端的Messenger,并通过获取的这个Messenger对象向客户端回应消息:

private class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch (msg.what) { case AppConstants.MSG_FROM_CLIENT: // 接收客户端发来的消息 Log.i(TAG, "handleMessage: MSG_FROM_CLIENT:" + msg.getData().getString("msg")); // 服务端收到消息后,给客户端发送回应 Messenger client = msg.replyTo; Message replyMsg = Message.obtain(null, AppConstants.MSG_FROM_SERVICE); Bundle bundle = new Bundle(); bundle.putString("msg", "ok,I will reply you soon!"); replyMsg.setData(bundle); try { client.send(replyMsg); } catch (RemoteException e) { e.printStackTrace(); } break; default: super.handleMessage(msg); } } }

再次运行工程,点击按钮,将进程切换到主进程后log如下:

.../cn.codingblock.ipc I/MessengerActivity: handleMessage: MSG_FROM_SERVICE:ok,I will reply you soon!

至此,通过Messenger实现的一个完整的两个进程之间的交互过程完成了,上面的两个进程虽然都在同一个App中,但其效果同在两个App中几乎一致,只是如果是两个App的话在需要稍微修改一下绑定Service时的Intent并将Service的export属性设为true。

4、通过Messenger实现两个App通讯

接下来试验一下将两个进程中放入两个App中:

新建一个名为IpcClient的Module,将MessengerActivity拷贝过去,在bindService时,不要忘记将Intent稍作修改一下,因为现在MessengerService在另外一个工程中,无法直接传入到Intent中,需改为如下方式:

intent = new Intent(); intent.setComponent(new ComponentName("cn.codingblock.ipc", "cn.codingblock.ipc.messager.MessengerService"));

为了能够更加方便的区分是哪个工程传到Service端的消息,在发送消息时加入如下信息:

bundle.putString("msg", "client bind messenger succeed!(from ipc_client)");

其他代码不变。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfdzz.html