详解 Android IPC 机制(五)使用 Messenger 实现进程间通信

Author Avatar
wshunli 6月 07, 2018
  • 在其它设备中阅读本文章

通过 Messenger 可以在不同进程之间传递 Message 对象,是一种轻量级的 IPC 方案。

首先看 Messenger 的构造方法:

public Messenger(Handler target) {
    mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

实质上还是底层还是基于 AIDL 的。

对于 Message 对象可以存储传递的数据:

public int what; // 消息标识
public int arg1; // 整型数据
public int arg2; // 整型数据
public Object obj;
public Messenger replyTo;
/*package*/ Bundle data;
public void setData(Bundle data) {
    this.data = data;
}

其中 obj 只能传输系统中实现了 Parcelable 接口的对象。

对于 客户端 发送消息主要使用 bindService 方法绑定另一个进程的 Service 。

public class MessengerActivity extends AppCompatActivity {

    private static final String TAG = "MessengerActivity";

    private Messenger messenger;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            // 请求服务端
            messenger = new Messenger(service);
            Message message = Message.obtain(null, MConstants.MSG_FROM_CLIENT);
            Bundle bundle = new Bundle();
            Log.d(TAG, "这里是客户端,向服务端发送消息");
            bundle.putString("msg", "客户端发送内容");
            message.setData(bundle);
            // 注意设置 replyTo
            message.replyTo = getReplyMessenger;
            try {
                messenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private static class MessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "这里是客户端,接收服务端响应");
            switch (msg.what) {
                case MConstants.MSG_FROM_SERVICE:
                    // 接收服务端响应
                    Log.d(TAG, "客户端接收到: " + msg.getData().get("reply"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private Messenger getReplyMessenger = new Messenger(new MessageHandler());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);

        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        unbindService(connection);
        super.onDestroy();
    }
}

如果需要接收服务端返回的消息,注意在发送 Message 字段 replyTo 关联处理消息的 Messenger 对象。

对于 服务端 ,首先 Messenger 对象关联接收消息的 Handler ,然后在服务端 onBind 中调用 getBinder() 方法得到 Binder 对象。

其中 MessageHandler 继承 Handler 并重写 handleMessage 方法。

public class MessengerService extends Service {
    private static final String TAG = "MessengerService";

    private static class MessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "这里是服务端,响应客户端消息");
            switch (msg.what) {
                case MConstants.MSG_FROM_CLIENT:
                    Log.d(TAG, "服务端接收到: " + msg.getData().get("msg"));
                    // 响应客户端请求
                    Messenger replyTo = msg.replyTo;
                    Message replyMessage = Message.obtain(null, MConstants.MSG_FROM_SERVICE);
                    Bundle bundle = new Bundle();
                    bundle.putString("reply","服务端响应内容");
                    replyMessage.setData(bundle);
                    try {
                        replyTo.send(replyMessage);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private final Messenger messenger = new Messenger(new MessageHandler());

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

如果需要响应客户端请求,使用 replyTo 字段获取 Messenger 实例再发送消息即可。

最后注意在 Manifest 中注册 Service 组件。

<service
    android:name="com.wshunli.ipc.demo.message.MessengerService"
    android:process=":remote" />

Messenger进程间通信

Messenger 进程间通信在服务端是以串行的方式逐个处理的,所以有大量并发请求时使用 Messenger 不太合适。

参考资料
1、《Android开发艺术探索》 — 2.4.3 使用 Messenger
2、Android IPC机制(二)用Messenger进行进程间通信 | 刘望舒的博客
http://liuwangshu.cn/application/ipc/2-messenger.html
3、Android 基于Message的进程间通信 Messenger完全解析 - CSDN博客
https://blog.csdn.net/lmj623565791/article/details/47017485
4、Handler之Message详解 - 简书
https://www.jianshu.com/p/a6c01dd2efdc

如果本文对您有所帮助,且您手头还很宽裕,欢迎打赏赞助我,以支付网站服务器和域名费用。 https://paypal.me/wshunli 您的鼓励与支持是我更新的最大动力,我会铭记于心,倾于博客。
本文链接:https://www.wshunli.com/posts/9da3d2db.html