1、概述

Messenger是一种轻量级的IPC通信方案,对AIDL进行了封装,可以在不同进程中传递Message对象。

2、使用Messenger通信

Server端代码

public class MessengerService extends Service {
    public static final String TAG = "MyMessenger";
    public static final int MSG_FROMCLIENT = 1000;
    public static final int MSG_FROMSERVER = 1001;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    private Handler mHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case MSG_FROMCLIENT:
                    Log.d(TAG, "receive message from client:" + msg.getData().getString("msg"));

                    Messenger messenger = msg.replyTo;
                    Message message = Message.obtain(null, MSG_FROMSERVER);
                    Bundle bundle = new Bundle();
                    bundle.putString("rep", "message form server");
                    message.setData(bundle);
                    try {
                        messenger.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    };

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

Service端接收Client端发送的消息,并返回一个消息。Server端要点是创建Handler对象,并在其handleMessage方法中处理Client端发送的消息。如果要返回消息给Client端,则需要Client发送消息时传递Client端的Messenger对象到Server端。同样的Client端要发送消息到Server端,也是通过Server端传递过去的Messenger对象。

Client端代码

public class MainActivity extends AppCompatActivity {

    private Handler mHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case MessengerService.MSG_FROMSERVER:
                    Log.d(MessengerService.TAG, "received message from server: " + msg.getData().getString("rep"));
                    break;
            }
        }
    };

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Messenger messenger = new Messenger(service);
            Message message = Message.obtain(null, MessengerService.MSG_FROMCLIENT);
            Bundle bundle = new Bundle();
            bundle.putString("msg", "message form client");
            message.setData(bundle);
            message.replyTo = new Messenger(mHandler);
            try {
                messenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

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

bindService时回调onServiceConnected,获取service返回的IBinder对象,由此重构Messenger对象,并用此Messenger对象发送消息给Server端。同时,如果需要处理Server端返回的消息,则需要创建一个Messenger对象并包含Handler对象,将其设置到Message对象的replyTo属性中,并将其传递到Server端,Server端通过这个replyTo获取的Messenger对象发送消息回Client端。

3、Messenger原理探究

从Messenger的使用中可以看出,Messenger通信依赖Binder、Handler和Message。Handler机制是Android线程间通信的机制,BInder是Android进程间通信的机制。

  • 构造函数
public Messenger(Handler target) {
    mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

messenger有两个构造函数,分别是传入一个Handler对象和一个IBinder类型的对象作为参数,都会去设置mTarget属性。
先来看一下Handler作为参数的情况,调用的是Handler中的getIMessenger方法。

final IMessenger getIMessenger() {
    synchronized (mQueue) {
        if (mMessenger != null) {
            return mMessenger;
        }
        mMessenger = new MessengerImpl();
        return mMessenger;
    }
}

返回的是IMessenger对象,如果Handler中已经设置了该对象则直接返回,如果没有设置,则返回一个MessengerImpl对象。MessengerImpl是Handler中的内部类,继承自IMessenger.Stub,并重写了send方法。

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

可以看出IMessenger是一个aidl接口,里面有一个send方法。
另外一个构造函数就更直接了,直接调用asInterface方法返回一个IMessenger的实例。

  • 发送消息
public void send(Message message) throws RemoteException {
    mTarget.send(message);
}

调用的是mTarget的send方法,因为mTarget是IMessenger的实例,调用的是Handler中MessengerIml内部类的send方法。从上面的方法中可以看到实际调用的就是Handler中的sendMessage方法。

  • 总结
    Messenger实际是通过Binder来实现跨进程通信,通过Handler机制来处理消息循环。Messenger封装Handler来进行消息的发送和处理,消息发送后通过Binder完成进程间通信。