深入解析AndroidIPC中的Messenger机制
作者:手机用户2502918445 | 来源:互联网 | 2024-12-21 11:11
本文详细介绍了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. ...
[详细]
蜡笔小新 2024-12-28 08:54:34
本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ...
[详细]
蜡笔小新 2024-12-28 10:51:55
本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ...
[详细]
蜡笔小新 2024-12-27 16:11:49
本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ...
[详细]
蜡笔小新 2024-12-28 04:11:47
本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ...
[详细]
蜡笔小新 2024-12-27 16:07:12
本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ...
[详细]
蜡笔小新 2024-12-27 15:04:09
本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ...
[详细]
蜡笔小新 2024-12-28 13:35:19
本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ...
[详细]
蜡笔小新 2024-12-28 10:36:30
本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ...
[详细]
蜡笔小新 2024-12-28 09:46:23
Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ...
[详细]
蜡笔小新 2024-12-28 09:44:49
本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ...
[详细]
蜡笔小新 2024-12-27 19:39:42
本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ...
[详细]
蜡笔小新 2024-12-27 18:51:49
1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ...
[详细]
蜡笔小新 2024-12-27 18:36:54
主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ...
[详细]
蜡笔小新 2024-12-27 18:18:10
本文详细介绍如何使用Samba软件配置CIFS文件共享服务,涵盖安装、配置、权限管理及多用户挂载等关键步骤。通过具体示例和命令行操作,帮助读者快速搭建并优化Samba服务器。 ...
[详细]
蜡笔小新 2024-12-26 17:44:08
手机用户2502918445
这个家伙很懒,什么也没留下!