【Android】使用Messenger实现进程间通讯
1 Messenger 简介
Messenger 类实现了 Parcelable 接口,用于进程间传输并处理消息,调用流程如下:

- Client 通过 bindService() 请求绑定 Service
- Service 通过 messenger_s.getBinder() 获取 IBunder 并返回 Client
- Client 通过 messenger_s =new Messenger(service) 获取 Service 的 Messenger
- Client 通过 msg_c2s.replyTo=messenger_c 将自己的 Messenger 绑定到 msg_c2s
- Client 通过 messenger_s.send(msg_c2s) 给 Service 发送消息
- Service 通过 messenger_c=msg_c2s.replyTo 获取 Client 的 Messenger
- Service 通过 messenger_c.send(msg_s2c) 给 Client 发送消息
本文全部代码见→使用Messenger实现进程间通讯
2 项目结构

3 服务端 msger_S 代码
(1)创建服务
MyService.java
package com.example.msger_s;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
Messenger messenger_c; //客户端的Messenger
@Override
public IBinder onBind(Intent intent) {
return messenger_s.getBinder();
}
private Messenger messenger_s = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg_c2s) {
super.handleMessage(msg_c2s);
receive(msg_c2s);
messenger_c = msg_c2s.replyTo; //获取客户端的Messenger
send();
}
});
private void receive(Message msg) { //接收来自客户端的消息
Bundle bundle = (Bundle) msg.obj;
String msg_c2s = bundle.getString("msg_c2s");
Log.e("MyService", "来自客户端的消息:" + msg_c2s);
}
private void send() { //给客户端返回消息
Message msg = new Message();
Bundle bundle1 = new Bundle();
bundle1.putString("msg_s2c", "hello client");
msg.obj = bundle1;
try {
messenger_c.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
(2)注册服务
在 AndroidManifest.xml 文件中 application 节点下注册 service,如下。
<service
android:name=".MyService"
android:exported="true">
<intent-filter>
<action android:name="com.xxx.msger_s"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
(3)主 Activity
MainActivity.java
package com.example.msger_s;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
4 客户端 msger_C 代码
(1)设计布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.msger_c.MainActivity">
<EditText
android:id="@+id/et_send"
android:layout_width="match_parent"
android:layout_height="80dp"
android:text="hello service"
android:textSize="30dp"
android:background="#ffcc66"/>
<Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:textSize="30sp"
android:text="发送"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="返回的消息:"
android:textSize="30sp"
android:layout_marginTop="100dp"/>
<TextView
android:id="@+id/tv_receive"
android:layout_width="match_parent"
android:layout_height="80dp"
android:textSize="30sp"
android:background="#ffcc66"
android:layout_marginTop="20dp"/>
</LinearLayout>
界面如下:

(2)主 Activity
MainActivity.java
package com.example.msger_c;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Messenger messenger_s; //服务端的Messenger
private EditText et_send;
private Button btn_send;
private TextView tv_receive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
et_send = (EditText) findViewById(R.id.et_send);
btn_send = (Button) findViewById(R.id.btn_send);
tv_receive = (TextView) findViewById(R.id.tv_receive);
btn_send.setOnClickListener(cl);
}
View.OnClickListener cl = new View.OnClickListener(){
@Override
public void onClick(View v) {
hideInputMethod(MainActivity.this, v); //关闭输入法
if (v.getId()==R.id.btn_send) {
String msg_c2s = et_send.getText().toString();
sendMsg(msg_c2s);
}
}
};
private void sendMsg(String msg_c2s){
if (messenger_s==null) {
attemptToBindService();
}
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("msg_c2s",msg_c2s);
msg.obj = bundle;
msg.replyTo = messenger_c; //将客户端的Messenger传给服务端
try {
messenger_s.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private Messenger messenger_c = new Messenger(new Handler() { //客户端的Messenger
@Override
public void handleMessage(Message msg) { //处理服务端返回的消息
super.handleMessage(msg);
Bundle bundle = (Bundle) msg.obj;
String msg_s2c = bundle.getString("msg_s2c");
tv_receive.setText(msg_s2c);
}
});
private void attemptToBindService() {
Intent intent = new Intent();
intent.setAction("com.xxx.msger_s");
intent.setPackage("com.example.msger_s");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger_s = new Messenger(service); //获取服务端的Messenger
}
@Override
public void onServiceDisconnected(ComponentName name) {
messenger_s = null;
}
};
private void hideInputMethod(Activity act, View v) { //关闭输入法
InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(),0);
}
@Override
protected void onStart() {
super.onStart();
if (messenger_s==null) {
attemptToBindService();
}
}
@Override
protected void onStop() {
super.onStop();
if (messenger_s!=null) {
unbindService(conn);
}
}
}
5 效果展示
点击【发送】按钮,在服务端可以收到发送的消息,如下:

在客户端收到回复如下:

声明:本文转自【Android】使用Messenger实现进程间通讯
【Android】使用Messenger实现进程间通讯的更多相关文章
- Android进程间通讯之messenger
这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...
- Android进阶笔记04:Android进程间通讯(IPC)之Messenger
一. Android进程间通讯之Messenger 的引入 (1)引言: 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...
- Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- 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篇)-- 进程间通讯之Socket简介及示例
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android-Android进程间通讯之messenger
转自‘https://www.cnblogs.com/makaruila/p/4869912.html 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进 ...
- Android进程间通讯
最近研究了一下Android进程间通讯,原来只是会用,但是只是会用是不行滴,就来研究一下. 刚开始看的时候,我的头是这么大,看了一夜的时候,头就变成这样了,,吓得宝宝赶紧上床休息了,. 先喝喝茶讲个故 ...
- Android AIDL 进行进程间通讯(IPC)
编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...
随机推荐
- js - 使用 scroll属性手撸轮播图 —— 无缝连接,更丝滑
上效果图: 上代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- Python Code_02
author : 写bug的盼盼 development time : 2021/8/27 19:59 变量定义 name = '阿哈' print(name) print('标识',id(name) ...
- Go-基本类型-int-float-bool-byte-rune
- [转帖]配置ftp连接对象存储bucket子目录的方法
https://developer.jdcloud.com/article/1838 配置ftp连接对象存储bucket子目录的方法 京东云技术交付部 2021-01-27 IP归属:未知 441 ...
- [转帖]Kafka常见使用场景与Kafka高性能之道
https://juejin.cn/post/6958997115012186119 消息队列使用场景 队列,在数据结构中是一种先进先出的结构,消息队列可以看成是一个盛放消息的容器,这些消息等待着各种 ...
- [转帖]Kafka高可用 — KRaft集群搭建
Apache Kafka Raft 是一种共识协议,它的引入是为了消除 Kafka 对 ZooKeeper 的元数据管理的依赖,被社区称之为 Kafka Raft metadata mode,简称 K ...
- [转帖]linux下如何避免rsyslog系统日志不停打印到console
背景:linux环境下,服务器由于某种异常导致rsyslog message不停打印到console控制台,影响我们正常使用. ps:我遇见的场景: 解决办法:1. vim /etc/rsyslog. ...
- [转帖]银河麒麟服务器操作系统V10SP1-x86_64系统环境下部署aarch64虚拟机
文章目录 主机系统环境 搭建aarch64虚拟机环境 ①安装"虚拟系统管理器" ②编译安装Qemu for Aarch64 ③获取aarch64架构的qcow2镜像 ④使用qcow ...
- ESXi规避ESXiArgs勒索软件的简单方法
摘要 今天查看深信服科技的公众号 发现有一个ESXiArgs 的勒索软件. 感觉对公司存在一定的风险.但是感觉操作手册有点简单. 这里想着写全面一点. 作为操作手册使用. 并且深信服仅是解决了在运行, ...
- killall 以及 pkill 等命令
https://zhidao.baidu.com/question/1500084252693125099.html // 通过 killall 命令killall nginx// 通过 pkill ...