热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析AndroidIPC中的Messenger机制

本文详细介绍了Android中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。
在之前的文章中,我们探讨了使用 AIDL 实现 Android IPC 的方法。今天我们将聚焦于另一种常用的 IPC 方式——Messenger。

### 一、Messenger 概述

Messenger 是一种基于消息传递的进程间通信机制。它允许不同进程之间的对象通过 Handler 发送和接收消息。具体来说,一个进程可以通过创建指向本地 Handler 的 Messenger 对象,并将其传递给另一个进程来实现跨进程通信。

#### 工作原理

1. **服务端与客户端**:Messenger 需要服务端和客户端两部分。客户端需要绑定到远程服务,成功后可以获取远程 IBinder 对象并由此得到远程的 Messenger 对象。
2. **消息发送**:客户端向服务端发送消息时,需使用从服务端获取的 Messenger 对象,并将自身的 Messenger 对象作为回复地址附加在消息中。
3. **消息回复**:服务端接收到消息后,可以通过消息中的 replyTo 属性找到客户端的 Messenger 对象,从而向客户端发送响应。

![Messenger 工作流程图](https://img7.php1.cn/3cdc5/cdfb/978/d2f0c12aaecaf93f.jpeg)

### 二、实例演示

为了展示 Messenger 的实际应用,我们可以创建两个独立的应用程序,分别作为服务端和客户端。这里以服务端为例,展示如何处理来自客户端的消息并返回响应。

```java
public class MessengerService extends Service {
private static final String TAG = "MessengerService";
private static final int WHAT = 0x101;
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT:
Bundle bundle = (Bundle) msg.obj;
String str = bundle.getString("str");
Log.e(TAG, "收到客户端消息: " + str);
// 回复客户端
Message reply = Message.obtain();
Bundle replyBundle = new Bundle();
replyBundle.putString("str", "已收到,继续努力!");
reply.setData(replyBundle);
try {
msg.replyTo.send(reply);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
private final Messenger mMessenger = new Messenger(mHandler);

@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
```

客户端代码负责绑定服务并发送初始消息。当接收到服务端的响应时,会显示在日志中。

```java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int WHAT = 0x102;
private boolean isBound;
private Messenger mClientMessenger = new Messenger(new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == WHAT) {
Bundle bundle = msg.getData();
String respOnse= bundle.getString("str");
Log.e(TAG, "收到服务端回复: " + response);
}
}
});
private Messenger mServiceMessenger;
private ServiceConnection mCOnnection= new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServiceMessenger = new Messenger(service);
isBound = true;
sendInitialMessage();
}

@Override
public void onServiceDisconnected(ComponentName name) {
mServiceMessenger = null;
isBound = false;
}
};

private void sendInitialMessage() {
Message message = Message.obtain(null, WHAT);
Bundle bundle = new Bundle();
bundle.putString("str", "你好,我是客户端");
message.setData(bundle);
message.replyTo = mClientMessenger;
try {
mServiceMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_start_service).setOnClickListener(v -> bindService());
}

private void bindService() {
Intent intent = new Intent("cn.xinxing.messengerservice");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(mConnection);
}
}
}
```

### 三、源码剖析

Messenger 的核心在于其构造函数和内部使用的 IMessenger 接口。构造函数接受一个 Handler 并从中提取出 IMessenger 对象。IMessenger 是一个 AIDL 接口,定义了 send 方法用于跨进程传递消息。

```java
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
```

`getIMessenger()` 方法返回一个实现了 IMessenger 接口的对象,即 `MessengerImpl`。这个类重写了 send 方法,利用 Handler 来分发消息。

```java
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
```

### 四、总结

- **底层实现**:Messenger 基于 AIDL 构建,但封装了复杂的细节,简化了开发者的使用。
- **通信方式**:服务端和客户端之间通过各自持有的 Messenger 对象进行消息交换。
- **参数传递**:所有数据必须实现 Parcelable 接口,推荐使用 Bundle 封装参数。
- **线程支持**:Messenger 默认是单线程的,不支持并发操作。若需多线程,请考虑使用 AIDL 或其他方案。

希望本文能帮助你更深入地理解 Android IPC 中的 Messenger 机制及其应用场景。
推荐阅读
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 深入解析JVM垃圾收集器
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 本文详细介绍如何使用Samba软件配置CIFS文件共享服务,涵盖安装、配置、权限管理及多用户挂载等关键步骤。通过具体示例和命令行操作,帮助读者快速搭建并优化Samba服务器。 ... [详细]
author-avatar
手机用户2502918445
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有