Android IPC之Messenger分析

155 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

一.Messenger简介

与AIDL进程间通信作用一样,Messenger是基于Message对象进行跨进程通信的,类似于Handler发送消息实现子线程和UI线程进行通信,此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信。         普通的进程间通信,需要服务端自己提供AIDL接口文件,然后本地实现Stub内方法,客户端需要引入方可进行通信;Messenger是系统提供统一的AIDL接口文件,并且由Handler来实现Stub内方法,服务端在Handler内处理即可,客户端不需要引入,直接可以通信;

二.Messenger实现流程

a.服务端实现
  1. 创建一个Handler对象,并实现handleMessage方法,用于接收来自客户端的消息并作处理;
  2. 创建一个Messenger(送信人),封装Handler;
  3. 用Messenger的getBinder()方法获取一个IBinder对象,通过onBind返回给客户端;        代码如下:
public class MyService extends Service {
    private static final String TAG = MyService.class.getSimpleName();
    public MyService() {
    }

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

    private MessengerHandler mHandler = new MessengerHandler();
    private Messenger mMessenger = new Messenger(mHandler);
    private static class MessengerHandler extends Handler{

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //取出客户端的消息内容
            Bundle bundle = msg.getData();
            String clientMsg = bundle.getString("client");
            Log.i(TAG,"来自客户端的消息:"+clientMsg);
            //新建一个Message对象,作为回复客户端的对象
            Message message = Message.obtain();
            Bundle bundle1 = new Bundle();
            bundle1.putString("server","已收到消息");
            message.setData(bundle1);
            try {
                msg.replyTo.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}

服务端接受到客户端的消息,其实与线程间通信一样,也是在handleMessage方法中进行处理;

如果服务端需要回复客户端,则需要获取到客户端携带过来的Messenger对象(即msg.replyTo),通过msg.replyTo.send()给客户端发送信息。

b.客户端实现
  1. 绑定服务,创建ServiceConnection并在其中使用IBinder将Messenger实例化;
  2. 使用Messenger向服务端发送消息;
  3. 接收服务端发送过来的message;
  4. 解绑服务;

       实现如下:

public class MyActivity extends Activity implements View.OnClickListener {
    private static final String TAG = MyActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bindService = findViewById(R.id.bindService);
        Button unBindService = findViewById(R.id.unBindService);
        bindService.setOnClickListener(this);
        unBindService.setOnClickListener(this);
    }

    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bindService:
                Intent intent = new Intent();
                intent.setAction("com.hly.learn.server.action");
                bindService(intent,mConnection,BIND_AUTO_CREATE);
                break;
            case R.id.unBindService:
                unbindService(mConnection);
                break;
           default:
                break;
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //获取服务端关联的Messenger对象
            Messenger mService = new Messenger(service);
            //创建Message对象
            Message message = Message.obtain();
            Bundle bundle = new Bundle();
            bundle.putString("client","hello");
            message.setData(bundle);
            try {
                mService.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

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

客户端在绑定服务之后,在ServiceConnection中通过IBinder得到Messenger对象(mService),然后用mService的send方法把Message作为形参发送给服务端。