赞
踩
Android中比较有代表性的两大通信机制:1. 线程间Handler通信 2. 进程间Binder通信,本篇文章中我们在理解AIDL原理的基础上来解读一下Messenger的源代码, 并结合示例Demo加深理解。 在看本篇文章前,建议先查阅一下笔者的 Android 进程间通信机制(六) 手写AIDL文件
首先说下我对Messenger的个人理解:
1. 从概念上阐述
Messenger进程间通信的信使,是一个轻量级的IPC通信方案, 和Message消息不是一个概念。
2. 从实现上描述
实现: AIDL + Handler 它的底层实现原理还是使用 AIDL, 对应的文件为(IMessenger.aidl)
相应的接口方法:
- oneway interface IMessenger {
- void send(in Message msg);
- }
Messenger使用了Handler进行通信, 调用的这句代码
- private final class MessengerImpl extends IMessenger.Stub {
- public void send(Message msg) {
- msg.sendingUid = Binder.getCallingUid();
- //核心代码
- Handler.this.sendMessage(msg);
- }
- }
3. 使用场景
两个进程间只进行简单的,轻量级通信, 不需要处理多线程的业务场景。
2.1 先看一下清单文件
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.messengertest">
-
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/Theme.MessengerTest">
- <activity
- android:name=".MainActivity"
- android:exported="true"
- android:process=":client">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
-
- <service
- android:name=".MyService"
- android:exported="true"
- android:enabled="true"
- android:process=":server">
- </service>
- </application>
-
- </manifest>
我把MainActivity作为客户端, MyService作为服务端, 用android:process标记让两个组件运行在不同的进程中。
2.2 客户端
- public class MainActivity extends AppCompatActivity {
-
- private static final String TAG = "MainActivity";
- private Messenger mServiceMessenger;
-
- //创建客户端 Messenger 对象,并绑定 Handler
- private Messenger mClientMessenger = new Messenger(new MessengerHandler());
-
- private static final class MessengerHandler extends Handler {
-
- @Override
- public void handleMessage(@NonNull Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case MyConstants.MSG_FROM_SERVER: //接受来自 服务端 的消息
- Log.d(TAG, "receive msg from server: " + msg.getData().get("reply"));
- break;
- default:
- break;
- }
- }
- }
-
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- //绑定服务端的 Service, 成功后用返回的 IBinder 对象创建 Messenger
- Intent intent = new Intent(this, MyService.class);
- bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- }
-
- private ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder binder) {
- mServiceMessenger = new Messenger(binder); // 获取服务端的 Messenger对象, 通过它向服务端发送消息
- Message msg = Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
- Bundle data = new Bundle();
- data.putString("msg", "hello, this is client");
- msg.setData(data);
- msg.replyTo = mClientMessenger ; //将客户端的 Messenger 传给 服务端
- try {
- mServiceMessenger.send(msg);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
-
- }
- };
- }
2.3 服务端
- public class MyService extends Service {
-
- private static final String TAG = "MyService";
-
- //服务端创建 Messenger对象,并绑定对应 Handler, 用于处理 Client 发过来的消息
- private final Messenger mServiceMessenger = new Messenger(new MessengerHandler());
-
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- //返回 Binder 对象给 Client
- return mServiceMessenger.getBinder();
- }
-
- public MyService() {
- }
-
- private static class MessengerHandler extends Handler {
-
- @Override
- public void handleMessage(@NonNull Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case MyConstants.MSG_FROM_CLIENT:
- Log.d(TAG, "receive msg from client:" + msg.getData().getString("msg"));
- Messenger clientMessenger = msg.replyTo; //获取传递过来的客户端Messenger对象
- Message replyMsg = Message.obtain(null, MyConstants.MSG_FROM_SERVER);
-
- Bundle bundle = new Bundle();
- bundle.putString("reply", " server have receive your msg");
- replyMsg.setData(bundle);
-
- try {
- clientMessenger.send(replyMsg);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- break;
- default:
- break;
- }
- }
- }
- }
2.4 消息常量
- public class MyConstants {
-
- public static final int MSG_FROM_SERVER = 2;
- public static final int MSG_FROM_CLIENT = 1;
- }
2.5 运行结果
- 16:12:57.139 31928 31928 D MyService: receive msg from client:hello, this is client
- 16:12:57.181 31894 31894 D MainActivity: receive msg from server: server have receive your msg
客户端和服务端关键代码处有注释说明,方便理解。
上面Demo,可以用如下图来说明
大多数应用,跨进程只是一对一通信, 并且无需执行多线程处理的业务, 此时使用Messenger更适合一点。
我们重点看如下5个方法:
- public final class Messenger implements Parcelable {
- ......
-
- //1. mTarget 为 IMessenger接口实例化对象
- private final IMessenger mTarget;
-
-
- //2. 创建一个指向target Handler的Messenger,
- // 然后调运Messenger的send 实质是调用Handler的sendMessage方法
- public Messenger(Handler target) {
- mTarget = target.getIMessenger();
- }
-
- //3. 跨进程发送消息方法
- public void send(Message message) throws RemoteException {
- mTarget.send(message);
- }
-
- //4. 获得Messenger的Binder,一般用在service端获取返回
- public IBinder getBinder() {
- return mTarget.asBinder();
- }
-
- //5. 获取getBinder相同的Messenger对象,一般用在client端获取
- public Messenger(IBinder target) {
- mTarget = IMessenger.Stub.asInterface(target);
- }
-
- ......
-
- }
第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
- public interface IMessenger extends android.os.IInterface {
- ......
- }
它是一个public 接口类,不能直接通过new IMessenge() 来创建对象,但是可以new 实现了该接口的类对象。
第2和5个方法 是Messenger类的两个构造方法
- private final IMessenger mTarget;
-
- public Messenger(Handler target) {
- mTarget = target.getIMessenger();
- }
-
- public Messenger(IBinder target) {
- mTarget = IMessenger.Stub.asInterface(target);
- }
可以这样子理解两个方法的用途:
1. 参数为Handler的是远程端进程的实例方法
2. 参数为IBinder的是客户端进程的实例方法
第1个构造方法的内容:
- //frameworks/base/core/java/android/os/Handler.java 文件中
-
- IMessenger mMessenger;
-
- //对于一个Handler对象来说getIMessenger得到的Messenger是一个单例模式对象
- final IMessenger getIMessenger() {
- synchronized (mQueue) {
- if (mMessenger != null) {
- return mMessenger;
- }
- //这里就是new了一个实现该接口类的对象
- mMessenger = new MessengerImpl();
- return mMessenger;
- }
- }
-
- //这里其实是IMessenger.aidl的接口send的具体实现类
- private final class MessengerImpl extends IMessenger.Stub {
- public void send(Message msg) {
- msg.sendingUid = Binder.getCallingUid();
- //核心还是与该(进程绑定的Handler)去发送消息
- Handler.this.sendMessage(msg);
- }
- }
结论:Messenger类中的mTarget其实就是一个Handler中 实现了(IMessenger远程IPC send接口)的MessengerImpl 单例对象。
第2个方法的使用,就是在客户端拿到服务端的Messenger对象
在MyService.java中 我们看下Service中的onBind实现,其调运了Messenger的getBinder方法,这个方法源码如下:
- //服务端创建 Messenger对象,并绑定对应 Handler, 用于处理 Client 发过来的消息
- private final Messenger mServiceMessenger = new Messenger(new MessengerHandler());
-
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- //返回 Binder 对象给 Client
- return mServiceMessenger .getBinder();
- }
-
- public IBinder getBinder() {
- return mTarget.asBinder();
- }
- //调用mTarget.asBinder()方法,也即是this对象自己
-
- //在 Stub类中
- public static abstract class Stub extends android.os.Binder implements android.os.IMessenger{
- ....
- @Override public android.os.IBinder asBinder()
- {
- return this;
- }
- ....
- }
-
- //还记得上面的Handler类中的 MessengerImpl 实现了 IMessenger.Stub
- IMessenger mMessenger = new MessengerImpl()
- private final class MessengerImpl extends IMessenger.Stub {
-
- }
可以看见,其实asBinder返回的就是this, 也就是把Service中的Messenger通过onBind方法返回给客户端。
然后再回到客户端 MainActivity.java 中的 onServiceConnected 方法
- private Messenger mServiceMessenger;
-
- private final IMessenger mTarget;
-
- // 1. 获取服务端的 Messenger对象, 通过它向服务端发送消息
- public void onServiceConnected(ComponentName name, IBinder binder) {
- mServiceMessenger = new Messenger(binder);
-
- // 2. 上面的 new Messenger(binder)调用方法
-
- /**
- * Create a Messenger from a raw IBinder, which had previously been
- * retrieved with {@link #getBinder}.
- *
- * @param target The IBinder this Messenger should communicate with.
- */
- public Messenger(IBinder target) {
- mTarget = IMessenger.Stub.asInterface(target);
- }
通过asInterface方法转化一下,由于不在同一个进程,会把Stub转换成Proxy代理对象
- public static android.os.IMessenger asInterface(android.os.IBinder obj)
- {
- if ((obj==null)) {
- return null;
- }
- android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
- if (((iin!=null)&&(iin instanceof android.os.IMessenger))) {
- return ((android.os.IMessenger)iin);
- }
- return new android.os.IMessenger.Stub.Proxy(obj);
- }
就这样客户端就拿到了服务端的Messenger对象,接下来就可以在客户端中用Messenger给服务端发送消息了。
1. 客户端和服务端都有自己的Handler对象,用于在各自的进程中接收处理消息,发送消息则是和Handler绑定的Messenger对象。
2. 通过IMessenger.aidl 中的 send(Message msg)方法进行跨进程通信, 注意 msg.replyTo变量实则是一个Messenger对象, 用于两个进程传递各自的Messenger对象。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。