Android 进程间通信中 Messager 的简单使用

news/2025/2/22 21:34:09/

Messenger 是 Android 中一种简单且高效的进程间通信(IPC)机制。它基于 BinderHandler 实现,适用于轻量级的跨进程通信场景。相比 AIDL(Android Interface Definition Language),Messenger 更加简单易用,但功能相对有限。

以下是 Messenger 的详细用法和实现步骤:


1. Messenger 的工作原理

Messenger 的核心思想是通过消息队列在不同进程之间传递消息:

  • 服务端:创建一个 Handler 来处理客户端发送的消息,并通过 MessengerHandler 暴露给客户端。
  • 客户端:通过绑定到服务端的 Service,获取服务端的 Messenger 对象,并使用它发送消息。
  • 消息格式:所有消息都封装在 Message 对象中,支持携带简单的数据(如整数、字符串等)或 Bundle

2. 使用 Messenger 的步骤

(1) 服务端实现

服务端需要创建一个 Service,并在其中定义一个 Handler 来处理客户端发送的消息。

示例代码:
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.util.Log;public class MessengerService extends Service {private static final String TAG = "MessengerService";// 定义 Handler 处理客户端消息private final Handler handler = new Handler(msg -> {Log.d(TAG, "Received message from client: " + msg.what);// 解析消息内容Bundle data = msg.getData();if (data != null) {String clientMessage = data.getString("key");Log.d(TAG, "Client message: " + clientMessage);}// 回复客户端消息Messenger clientMessenger = msg.replyTo;if (clientMessenger != null) {Message replyMessage = Message.obtain(null, 2); // 回复消息的 what 值为 2Bundle replyData = new Bundle();replyData.putString("reply_key", "Hello from server");replyMessage.setData(replyData);try {clientMessenger.send(replyMessage);} catch (Exception e) {e.printStackTrace();}}return true;});// 创建 Messenger 对象private final Messenger messenger = new Messenger(handler);@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "Service bound");return messenger.getBinder(); // 返回 Binder 对象}
}

(2) 客户端实现

客户端通过绑定到服务端的 Service,获取服务端的 Messenger 对象,并使用它发送消息。

示例代码:
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.util.Log;public class MessengerClient {private static final String TAG = "MessengerClient";private Messenger serviceMessenger; // 服务端的 Messengerprivate boolean isBound = false;// 定义 Handler 处理服务端回复的消息private final Handler handler = new Handler(msg -> {Log.d(TAG, "Received reply from server: " + msg.what);// 解析回复消息Bundle data = msg.getData();if (data != null) {String serverReply = data.getString("reply_key");Log.d(TAG, "Server reply: " + serverReply);}return true;});// 创建客户端的 Messengerprivate final Messenger clientMessenger = new Messenger(handler);// 定义 ServiceConnectionprivate final ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG, "Service connected");serviceMessenger = new Messenger(service); // 获取服务端的 MessengerisBound = true;// 发送消息给服务端sendMessageToService("Hello from client");}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG, "Service disconnected");serviceMessenger = null;isBound = false;}};// 绑定到服务端public void bindToService(Context context) {Intent intent = new Intent();intent.setComponent(new ComponentName("com.example.server", "com.example.server.MessengerService"));context.bindService(intent, connection, Context.BIND_AUTO_CREATE);}// 解绑服务public void unbindFromService(Context context) {if (isBound) {context.unbindService(connection);isBound = false;}}// 发送消息给服务端private void sendMessageToService(String message) {if (!isBound) return;// 创建消息Message msg = Message.obtain(null, 1); // 消息的 what 值为 1Bundle data = new Bundle();data.putString("key", message);msg.setData(data);// 设置回复 Messengermsg.replyTo = clientMessenger;try {serviceMessenger.send(msg); // 发送消息} catch (RemoteException e) {e.printStackTrace();}}
}

3. 配置 AndroidManifest.xml

确保服务端的 ServiceAndroidManifest.xml 中正确声明,并设置为可导出。

示例代码:
<serviceandroid:name=".MessengerService"android:exported="true"><intent-filter><action android:name="com.example.server.MessengerService" /></intent-filter>
</service>

4. 运行流程

  1. 服务端启动
    • 启动 MessengerService,等待客户端绑定。
  2. 客户端绑定
    • 客户端通过 bindService() 绑定到服务端。
    • 获取服务端的 Messenger 对象。
  3. 消息传递
    • 客户端通过 Messenger 发送消息给服务端。
    • 服务端处理消息并返回回复。
  4. 解绑服务
    • 客户端调用 unbindService() 解绑服务。

5. 优点与局限性

优点
  1. 简单易用:无需编写复杂的 AIDL 文件,直接使用 HandlerMessage
  2. 线程安全Messenger 内部使用 Handler,天然支持线程安全。
  3. 轻量级:适合简单的 IPC 场景。
局限性
  1. 单向通信限制:虽然可以通过 replyTo 实现双向通信,但逻辑较为复杂。
  2. 性能瓶颈:所有消息都通过主线程的 Handler 处理,不适合高并发场景。
  3. 数据类型限制:只能传递 Message 支持的数据类型(如 Bundle),不支持复杂对象。

6. 总结

Messenger 是一种简单且高效的 IPC 机制,适用于轻量级的跨进程通信场景。如果你的应用需要处理简单的消息传递(如状态更新、事件通知等),Messenger 是一个很好的选择。但如果需要更复杂的通信逻辑(如多线程、流式传输等),建议使用 AIDL 或其他高级 IPC 方案。

如果你还有其他问题或需要进一步的帮助,请随时告诉我!


http://www.ppmy.cn/news/1573569.html

相关文章

TypeScript 与后端开发Node.js

文章目录 一、搭建 TypeScript Node.js 项目 &#xff08;一&#xff09;初始化项目并安装相关依赖 1、创建项目目录并初始化2、安装必要的依赖包 &#xff08;二&#xff09;配置 TypeScript 编译选项&#xff08;如模块解析方式适合后端&#xff09; 二、编写服务器代码 &a…

本地DeepSeek模型GGUF文件转换为PyTorch格式

接前文,我们在本地Windows系统上,基于GGUF文件部署了DeepSeek模型(DeepSeek-R1-Distill-Qwen-1.5B.gguf版本),但是GGUF是已经量化的版本,我们除了对其进行微调之外,无法对其训练,那么还有没有其他办法对本地的GGUF部署的DeepSeek模型进行训练呢?今天我们就反其道而行之…

【Quest开发】全身跟踪

软件&#xff1a;Unity 2022.3.51f1c1、vscode、Meta XR All in One SDK V72 硬件&#xff1a;Meta Quest3 最终效果&#xff1a;能像meta的操作室沉浸场景一样根据头盔移动来推断用户姿势&#xff0c;实现走路、蹲下、手势匹配等功能 需要借助UnityMovement这个包 GitHub …

VSCode本地python包“无法解析导入”

问题现象 在使用 VSCode 编写 Python 代码时&#xff0c;虽然程序能正常运行&#xff0c;但遇到“无法解析导入”的问题&#xff0c;导致代码无法高亮。 解决方法 配置 python.autoComplete.extraPaths 打开 VSCode 设置&#xff08;CtrlShiftP -> Preferences: Open Wo…

【大语言模型】最新ChatGPT、DeepSeek等大语言模型助力高效办公、论文与项目撰写、数据分析、机器学习与深度学习建模等科研应用

ChatGPT、DeepSeek等大语言模型助力科研应用 随着人工智能技术的快速发展&#xff0c;大语言模型如ChatGPT和DeepSeek在科研领域的应用正在为科研人员提供强大的支持。这些模型通过深度学习和大规模语料库训练&#xff0c;能够帮助科研人员高效地筛选文献、生成论文内容、进行数…

01-零基础入门嵌入式系统

1.什么是嵌入式系统 首先我们要知道计算机系统分为大型机、通用计算机和嵌入式系统三大类。 计算机系统的发展&#xff0c;经历了由1台计算机系统为N个人服务的大型机时代到由1台计算机系统为1个人服务的PC时代&#xff0c;正在步入由N台计算机系统为1个人服务的嵌入式时代。 嵌…

文心一言,下一代模型开源

大家好&#xff0c;我是小悟。 百度官宣&#xff0c;将在未来几个月中陆续推出文心大模型 4.5 系列&#xff0c;并于 6 月 30 日起正式开源。 与此同时&#xff0c;百度近期发布多项 AI 开放政策&#xff0c;进一步降低大模型的使用门槛。随着文心大模型的迭代升级和成本不断…

Android Studio 提示 !Failed to initialize editor

网上的解决办法 将项目下的 .idea 文件夹删除 重新打开 AS File 菜单 Invalidate Caches/Restart 估计对大多数人都无效&#xff0c;就不说了。 还有一种原因就是JVM内存爆了&#xff0c;导致预览界面加载失败&#xff0c;修改 gradle.properties 文件 的 org.gradle.jvmar…