当前位置:   article > 正文

Android轻量级进程间通信Messenger源码分析

Android轻量级进程间通信Messenger源码分析

一. 概述

        Android中比较有代表性的两大通信机制:1. 线程间Handler通信   2. 进程间Binder通信,本篇文章中我们在理解AIDL原理的基础上来解读一下Messenger的源代码, 并结合示例Demo加深理解。 在看本篇文章前,建议先查阅一下笔者的 Android 进程间通信机制(六) 手写AIDL文件

        首先说下我对Messenger的个人理解:

1. 从概念上阐述

    Messenger进程间通信的信使,是一个轻量级的IPC通信方案, 和Message消息不是一个概念。

2. 从实现上描述

     实现: AIDL  +  Handler    它的底层实现原理还是使用 AIDL,  对应的文件为(IMessenger.aidl)

相应的接口方法:

  1. oneway interface IMessenger {
  2. void send(in Message msg);
  3. }

Messenger使用了Handler进行通信, 调用的这句代码

  1. private final class MessengerImpl extends IMessenger.Stub {
  2. public void send(Message msg) {
  3. msg.sendingUid = Binder.getCallingUid();
  4. //核心代码
  5. Handler.this.sendMessage(msg);
  6. }
  7. }

3. 使用场景

    两个进程间只进行简单的,轻量级通信, 不需要处理多线程的业务场景。

二. 示例

2.1 先看一下清单文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.messengertest">
  4. <application
  5. android:allowBackup="true"
  6. android:icon="@mipmap/ic_launcher"
  7. android:label="@string/app_name"
  8. android:roundIcon="@mipmap/ic_launcher_round"
  9. android:supportsRtl="true"
  10. android:theme="@style/Theme.MessengerTest">
  11. <activity
  12. android:name=".MainActivity"
  13. android:exported="true"
  14. android:process=":client">
  15. <intent-filter>
  16. <action android:name="android.intent.action.MAIN"/>
  17. <category android:name="android.intent.category.LAUNCHER"/>
  18. </intent-filter>
  19. </activity>
  20. <service
  21. android:name=".MyService"
  22. android:exported="true"
  23. android:enabled="true"
  24. android:process=":server">
  25. </service>
  26. </application>
  27. </manifest>

我把MainActivity作为客户端,  MyService作为服务端, 用android:process标记让两个组件运行在不同的进程中。

2.2 客户端

  1. public class MainActivity extends AppCompatActivity {
  2. private static final String TAG = "MainActivity";
  3. private Messenger mServiceMessenger;
  4. //创建客户端 Messenger 对象,并绑定 Handler
  5. private Messenger mClientMessenger = new Messenger(new MessengerHandler());
  6. private static final class MessengerHandler extends Handler {
  7. @Override
  8. public void handleMessage(@NonNull Message msg) {
  9. super.handleMessage(msg);
  10. switch (msg.what) {
  11. case MyConstants.MSG_FROM_SERVER: //接受来自 服务端 的消息
  12. Log.d(TAG, "receive msg from server: " + msg.getData().get("reply"));
  13. break;
  14. default:
  15. break;
  16. }
  17. }
  18. }
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_main);
  23. //绑定服务端的 Service, 成功后用返回的 IBinder 对象创建 Messenger
  24. Intent intent = new Intent(this, MyService.class);
  25. bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
  26. }
  27. private ServiceConnection mConnection = new ServiceConnection() {
  28. @Override
  29. public void onServiceConnected(ComponentName name, IBinder binder) {
  30. mServiceMessenger = new Messenger(binder); // 获取服务端的 Messenger对象, 通过它向服务端发送消息
  31. Message msg = Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
  32. Bundle data = new Bundle();
  33. data.putString("msg", "hello, this is client");
  34. msg.setData(data);
  35. msg.replyTo = mClientMessenger ; //将客户端的 Messenger 传给 服务端
  36. try {
  37. mServiceMessenger.send(msg);
  38. } catch (RemoteException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. @Override
  43. public void onServiceDisconnected(ComponentName name) {
  44. }
  45. };
  46. }

2.3 服务端

  1. public class MyService extends Service {
  2. private static final String TAG = "MyService";
  3. //服务端创建 Messenger对象,并绑定对应 Handler, 用于处理 Client 发过来的消息
  4. private final Messenger mServiceMessenger = new Messenger(new MessengerHandler());
  5. @Nullable
  6. @Override
  7. public IBinder onBind(Intent intent) {
  8. //返回 Binder 对象给 Client
  9. return mServiceMessenger.getBinder();
  10. }
  11. public MyService() {
  12. }
  13. private static class MessengerHandler extends Handler {
  14. @Override
  15. public void handleMessage(@NonNull Message msg) {
  16. super.handleMessage(msg);
  17. switch (msg.what) {
  18. case MyConstants.MSG_FROM_CLIENT:
  19. Log.d(TAG, "receive msg from client:" + msg.getData().getString("msg"));
  20. Messenger clientMessenger = msg.replyTo; //获取传递过来的客户端Messenger对象
  21. Message replyMsg = Message.obtain(null, MyConstants.MSG_FROM_SERVER);
  22. Bundle bundle = new Bundle();
  23. bundle.putString("reply", " server have receive your msg");
  24. replyMsg.setData(bundle);
  25. try {
  26. clientMessenger.send(replyMsg);
  27. } catch (RemoteException e) {
  28. e.printStackTrace();
  29. }
  30. break;
  31. default:
  32. break;
  33. }
  34. }
  35. }
  36. }

2.4 消息常量

  1. public class MyConstants {
  2. public static final int MSG_FROM_SERVER = 2;
  3. public static final int MSG_FROM_CLIENT = 1;
  4. }

2.5 运行结果

  1. 16:12:57.139 31928 31928 D MyService: receive msg from client:hello, this is client
  2. 16:12:57.181 31894 31894 D MainActivity: receive msg from server: server have receive your msg

客户端和服务端关键代码处有注释说明,方便理解。

三. 模型

上面Demo,可以用如下图来说明

四. 源码解析

大多数应用,跨进程只是一对一通信,  并且无需执行多线程处理的业务, 此时使用Messenger更适合一点。

我们重点看如下5个方法:

  1. public final class Messenger implements Parcelable {
  2. ......
  3. //1. mTarget 为 IMessenger接口实例化对象
  4. private final IMessenger mTarget;
  5. //2. 创建一个指向target Handler的Messenger,
  6. // 然后调运Messenger的send 实质是调用Handler的sendMessage方法
  7. public Messenger(Handler target) {
  8. mTarget = target.getIMessenger();
  9. }
  10. //3. 跨进程发送消息方法
  11. public void send(Message message) throws RemoteException {
  12. mTarget.send(message);
  13. }
  14. //4. 获得Messenger的Binder,一般用在service端获取返回
  15. public IBinder getBinder() {
  16. return mTarget.asBinder();
  17. }
  18. //5. 获取getBinder相同的Messenger对象,一般用在client端获取
  19. public Messenger(IBinder target) {
  20. mTarget = IMessenger.Stub.asInterface(target);
  21. }
  22. ......
  23. }

第1个方法  mTarget 为 IMessenger 接口实例化对象, 在java语法规则中,接口类不能直接创建对象, 只能实例化实现该接口的类对象,我们来看看IMessenger.java 它是IMessenger.aidl 文件通过aapt编译自动生成的,具体输出路径为:

out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/android/os/IMessenger.java

  1. public interface IMessenger extends android.os.IInterface {
  2. ......
  3. }

它是一个public 接口类,不能直接通过new IMessenge() 来创建对象,但是可以new 实现了该接口的类对象。

第2和5个方法 是Messenger类的两个构造方法

  1. private final IMessenger mTarget;
  2. public Messenger(Handler target) {
  3. mTarget = target.getIMessenger();
  4. }
  5. public Messenger(IBinder target) {
  6. mTarget = IMessenger.Stub.asInterface(target);
  7. }

可以这样子理解两个方法的用途: 

1. 参数为Handler的是远程端进程的实例方法

2. 参数为IBinder的是客户端进程的实例方法

第1个构造方法的内容:

  1. //frameworks/base/core/java/android/os/Handler.java 文件中
  2. IMessenger mMessenger;
  3. //对于一个Handler对象来说getIMessenger得到的Messenger是一个单例模式对象
  4. final IMessenger getIMessenger() {
  5. synchronized (mQueue) {
  6. if (mMessenger != null) {
  7. return mMessenger;
  8. }
  9. //这里就是new了一个实现该接口类的对象
  10. mMessenger = new MessengerImpl();
  11. return mMessenger;
  12. }
  13. }
  14. //这里其实是IMessenger.aidl的接口send的具体实现类
  15. private final class MessengerImpl extends IMessenger.Stub {
  16. public void send(Message msg) {
  17. msg.sendingUid = Binder.getCallingUid();
  18. //核心还是与该(进程绑定的Handler)去发送消息
  19. Handler.this.sendMessage(msg);
  20. }
  21. }

结论:Messenger类中的mTarget其实就是一个Handler中 实现了(IMessenger远程IPC send接口)的MessengerImpl 单例对象。

第2个方法的使用,就是在客户端拿到服务端的Messenger对象

在MyService.java中 我们看下Service中的onBind实现,其调运了Messenger的getBinder方法,这个方法源码如下:

  1. //服务端创建 Messenger对象,并绑定对应 Handler, 用于处理 Client 发过来的消息
  2. private final Messenger mServiceMessenger = new Messenger(new MessengerHandler());
  3. @Nullable
  4. @Override
  5. public IBinder onBind(Intent intent) {
  6. //返回 Binder 对象给 Client
  7. return mServiceMessenger .getBinder();
  8. }
  1. public IBinder getBinder() {
  2. return mTarget.asBinder();
  3. }
  4. //调用mTarget.asBinder()方法,也即是this对象自己
  5. //在 Stub类中
  6. public static abstract class Stub extends android.os.Binder implements android.os.IMessenger{
  7. ....
  8. @Override public android.os.IBinder asBinder()
  9. {
  10. return this;
  11. }
  12. ....
  13. }
  14. //还记得上面的Handler类中的 MessengerImpl 实现了 IMessenger.Stub
  15. IMessenger mMessenger = new MessengerImpl()
  16. private final class MessengerImpl extends IMessenger.Stub {
  17. }

可以看见,其实asBinder返回的就是this, 也就是把Service中的Messenger通过onBind方法返回给客户端。

然后再回到客户端 MainActivity.java 中的 onServiceConnected 方法

  1. private Messenger mServiceMessenger;
  2. private final IMessenger mTarget;
  3. // 1. 获取服务端的 Messenger对象, 通过它向服务端发送消息
  4. public void onServiceConnected(ComponentName name, IBinder binder) {
  5. mServiceMessenger = new Messenger(binder);
  6. // 2. 上面的 new Messenger(binder)调用方法
  7. /**
  8. * Create a Messenger from a raw IBinder, which had previously been
  9. * retrieved with {@link #getBinder}.
  10. *
  11. * @param target The IBinder this Messenger should communicate with.
  12. */
  13. public Messenger(IBinder target) {
  14. mTarget = IMessenger.Stub.asInterface(target);
  15. }

通过asInterface方法转化一下,由于不在同一个进程,会把Stub转换成Proxy代理对象

  1. public static android.os.IMessenger asInterface(android.os.IBinder obj)
  2. {
  3. if ((obj==null)) {
  4. return null;
  5. }
  6. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  7. if (((iin!=null)&&(iin instanceof android.os.IMessenger))) {
  8. return ((android.os.IMessenger)iin);
  9. }
  10. return new android.os.IMessenger.Stub.Proxy(obj);
  11. }

就这样客户端就拿到了服务端的Messenger对象,接下来就可以在客户端中用Messenger给服务端发送消息了。

五. 小结

1.  客户端和服务端都有自己的Handler对象,用于在各自的进程中接收处理消息,发送消息则是和Handler绑定的Messenger对象。

2.  通过IMessenger.aidl 中的 send(Message msg)方法进行跨进程通信, 注意 msg.replyTo变量实则是一个Messenger对象, 用于两个进程传递各自的Messenger对象。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/122364
推荐阅读
相关标签
  

闽ICP备14008679号