Android-Android进程间通讯之messenger
转自‘https://www.cnblogs.com/makaruila/p/4869912.html
平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯。它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽。哈哈。
此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信。
与 AIDL 比较:
当您需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。
接下来看下怎么用:
服务端:
1.创建一个handler对象,并实现hanlemessage方法,用于接收来自客户端的消息,并作处理
2.创建一个messenger(送信人),封装handler
3.用messenger的getBinder()方法获取一个IBinder对象,通过onBind返回给客户端
客户端:
1.在activity中绑定服务
2.创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化
3.使用Messenger向服务端发送消息
4.解绑服务
5.服务端中在 handleMessage() 方法中接收每个 Message
这样,客户端并没有调用服务的“方法”。而客户端传递的“消息”(Message 对象)是服务在其 Handler 中接收的。
上面实现的仅仅是单向通信,即客户端给服务端发送消息,如果我需要服务端给客户端发送消息又该怎样做呢?
其实,这也是很容易实现的,下面就让我们接着上面的步骤来实现双向通信吧
1.在客户端中创建一个Handler对象,用于处理服务端发过来的消息
2.创建一个客户端自己的messenger对象,并封装handler。
3.将客户端的Messenger对象赋给待发送的Message对象的replyTo字段
4.在服务端的Handler处理Message时将客户端的Messenger解析出来,并使用客户端的Messenger对象给客户端发送消息
这样就实现了客户端和服务端的双向通信了。
注意:注:Service在声明时必须对外开放,即android:exported="true"
是不是看的头晕,忘掉吧,直接看下面。
看一个简单的例子

1 package com.zixue.god.myapplication;
2
3 import android.app.Service;
4 import android.content.Intent;
5 import android.os.Handler;
6 import android.os.IBinder;
7 import android.os.Message;
8 import android.os.Messenger;
9 import android.os.RemoteException;
10 import android.widget.Toast;
11
12 //服务端service
13 public class MyService extends Service {
14 private static final int CODE = 1;
15 public MyService() {
16 }
17 @Override
18 public IBinder onBind(Intent intent) {
19 return mMessenger.getBinder();
20 }
21
22 //创建一个送信人,封装handler
23 private Messenger mMessenger = new Messenger(new Handler() {
24 @Override
25 public void handleMessage(Message msg) {
26 Message toClient = Message.obtain();
27 switch (msg.what) {
28 case CODE:
29 //接收来自客户端的消息,并作处理
30 int arg = msg.arg1;
31 Toast.makeText(getApplicationContext(),arg+"" , Toast.LENGTH_SHORT).show();
32 toClient.arg1 = 1111111111;
33 try {
34 //回复客户端消息
35 msg.replyTo.send(toClient);
36 } catch (RemoteException e) {
37 e.printStackTrace();
38 }
39 }
40 super.handleMessage(msg);
41 }
42 });
43 }

//客户端

1 package com.zixue.god.fuck;
2
3 import android.content.ComponentName;
4 import android.content.Intent;
5 import android.content.ServiceConnection;
6 import android.os.Bundle;
7 import android.os.Handler;
8 import android.os.IBinder;
9 import android.os.Message;
10 import android.os.Messenger;
11 import android.os.RemoteException;
12 import android.support.v7.app.AppCompatActivity;
13 import android.util.Log;
14 import android.view.View;
15 import android.widget.Button;
16 import android.widget.Toast;
17
18 public class MainActivity extends AppCompatActivity {
19 private boolean mBond;
20 private Messenger serverMessenger;
21 private MyConn conn;
22
23 @Override
24 protected void onCreate(Bundle savedInstanceState) {
25 super.onCreate(savedInstanceState);
26 setContentView(R.layout.activity_main);
27 //绑定服务
28 Intent intent = new Intent();
29 intent.setAction("com.zixue.god.myapplication.server");
30 conn = new MyConn();
31 bindService(intent, conn, BIND_AUTO_CREATE);
32 Button button = (Button) findViewById(R.id.bt);
33 button.setOnClickListener(new View.OnClickListener() {
34 @Override
35 public void onClick(View v) {
36 Message clientMessage = Message.obtain();
37 clientMessage.what = 1;
38 clientMessage.arg1 = 12345;
39 try {
40 clientMessage.replyTo = mMessenger;
41 serverMessenger.send(clientMessage);
42 } catch (RemoteException e) {
43 e.printStackTrace();
44 }
45 }
46 });
47 }
48
49 private class MyConn implements ServiceConnection {
50
51 @Override
52 public void onServiceConnected(ComponentName name, IBinder service) {
53 //连接成功
54 serverMessenger = new Messenger(service);
55 Log.i("Main", "服务连接成功");
56 mBond = true;
57 }
58
59 @Override
60 public void onServiceDisconnected(ComponentName name) {
61 serverMessenger = null;
62 mBond = false;
63 }
64 }
65 private Messenger mMessenger = new Messenger(new Handler(){
66 @Override
67 public void handleMessage(Message msg) {
68 Toast.makeText(getApplicationContext(),msg.arg1+"",Toast.LENGTH_SHORT).show();
69 super.handleMessage(msg);
70 }
71 });
72 @Override
73 protected void onDestroy() {
74 if (mBond) {
75 unbindService(conn);
76 }
77 super.onDestroy();
78 }
79
80 }

这样就实现了客户端和服务端双向通信,是不是很简单呢。
其实messenger底层也是AIDL。客户端和服务端通讯,就是普通的AIDL,客户端实例化stub之后,通过stub的send方法把消息发到服务端。服务端和客户端通讯:服务端通过解析message的replyto,获得客户端的stub,然后通过send方法发送到客户端。有精力的可以去翻一下源码。
Android-Android进程间通讯之messenger的更多相关文章
- Android Binder 进程间通讯机制梳理
什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...
- Android进程间通讯之messenger
这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...
- 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】
本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...
- android IPC 进程间通讯
参考资料: http://blog.csdn.net/birdsaction/article/details/39451849 在这里我说一下学习技术的方法,别人的博客,别人的东西,再简单,自己没有写 ...
- Android进阶笔记04:Android进程间通讯(IPC)之Messenger
一. Android进程间通讯之Messenger 的引入 (1)引言: 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...
- android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...
- Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...
- Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
随机推荐
- check source code after macro expand
Some time I'd like check source code after macro expand. We can use -E option to stop after the prep ...
- 学习总结——Postman做http接口功能测试
Postman做各种类型的http接口测试 首先,做接口测试前要有明确的接口文档(e.g. http://test.nnzhp.cn/wiki/index.php?doc-view-59) ,假设已经 ...
- 查询/删除/建立DB2数据表的主键
一.查询表主键. describe indexes for table <instancename>.<tablename> 例: describe indexes for t ...
- Oracle 查看表存储内存
--分配表的物理存储1 select segment_name, bytes from user_segments where segment_type = 'TABLE'; From User_Ex ...
- 【ActiveMQ】消息生产者自动注入报错:Could not autowire. No beans of 'JmsMessagingTemplate' type found
使用ActiveMQ过程中,定义消息生产者: package com.sxd.jms.producer; import org.springframework.beans.factory.annota ...
- cocos3.x新建项目
cocos new -p FishRunMan com.game.simple -l cpp
- kindeditor编辑器,获取textarea值
在获取textarea值的时候,从数据库读出来的值都能获取到,但是新输入的值就得不到,只要是新输入的都得不到值 答案: 我昨天刚用kindeditor,我是使用ajaxForm提交表单的在360浏览器 ...
- Android蓝牙开发教程(三)——蓝牙设备相互通讯
在上一篇中已经介绍如何连接我们搜索到的蓝牙设备,如果你还没阅读过,建议先看看上一篇文章Android蓝牙开发教程(二)——连接蓝牙设备 在上一篇文章中,无论是自动连接还是被动连接,连接成功后,都是将获 ...
- TestNG的參数化測试、共享线程池配置、參数默认值配置
在使用TestNG进行測试时,常常会使用到一些參数化配置,比方数据库.连接池.线程池数. 使用TestNG的參数@Parameter注解进行自己主动化读取 原创文章,版权全部.同意转载,标明出处:ht ...
- node在Fedora 22系统下开发环境搭建
事实上,环境搭建在linux系统还是比較简单的,下载已经编译好的包,配置一下环境变量. 或者下载源代码,自己编译. 这里记录一下,主要是node版本号变化节奏很块的情况下.怎样配置一次环境变量就不要再 ...