Android IPC之Messenger

来源:互联网 发布:mac os系统镜像下载 编辑:程序博客网 时间:2024/05/16 03:29

Messenger,主要用于进程间通信(以下简称“IPC”),这是实现IPC的最简单的方式。而且Messenger 会在单一线程中创建包含所有请求的队列,这样开发者不必对服务进行线程安全设计。换而言之,Messenger是处理单一线程的IPC方式。

这里可以多提一句,Messenger底层源码也是通过AIDL实现的。

如何使用Messeneger

服务端实现

  1. 在服务端创建一个Service,该Service提供给客户端远程绑定。
  2. 在Service中创建一个Handler对象,该Handler对象用于接收来自客户端的消息。
  3. 在Service中创建一个Messenger对象,该Messenger对象通过构造方法会持有Handler对象的应用。
  4. 在Service的onBind()方法中,返回IBinder对象。该对象通过Messenger.getBinder()方法获取。

客户端实现

  1. 在客户端远程绑定服务,并获取服务返回的IBinder对象。
  2. 创建一个Messenger对象,该Messenger对象会通过构造方法持有IBinder对象的应用。
  3. 通过调用Messenger对象send()方法,给服务端放松Message对象,完成数据通信。

通过以上的步骤就可以实现通过Messenger完成IPC的整个过程,但是该流程仅仅只支持单向通信(客户端发送消息到服务端)。

如果想通过Messenger对象完成双向通行(客户端、服务端互相发送消息),我们需要进一步完善上面的步骤。如下:

双向通行实现

  1. 在客户端创建一个Handler对象,该Handler对象用于接收来自服务端的消息。
  2. 在客户端创建一个Messenger对象,该Messenger对象通过构造方法会持有Handler对象的应用。
  3. 在客户端在向服务端发送Message时,将该Messenger赋值给message.replyTo属性。
  4. 服务端在通过服务端定义的Handler获取到Message,并通过Message.replyTo方法获取客户端创建的Messenger对象,通过send()方法可以给客户端发送消息。

以上就是通过Messenger实现Client/Server双向通信的整个流程。

实例演示

对于在android设备上实现调起微信或者支付宝实现第三方支付的场景相比大家并不陌生,在这里我们也通过Messenger来模拟这个流程。

服务端实现(模拟支付宝应用)

/** * 服务:通过Messenger实现进程间通信 */public class IPayService extends Service {    public static final String TAG = "IPayService";    /**     * 客户端发送的消息标识     */    public static final int MSG_CODE_FROM_CLIENT = 1;    /**     * 服务端发送的消息标识     */    public static final int MSG_CODE_FROM_SERVER = 2;    public IPayService() {}    @Override    public IBinder onBind(Intent intent) {        System.out.println("远程绑定服务...");        /**         * 3、通过Messenger获取binder对象,并通过service的onBind方法将binder对象返回到客户端         */        return mMessenger.getBinder();    }    /**     * 2、声明并创建一个Messenger对象,并将Handler作为参数传入     */    final Messenger mMessenger = new Messenger(new PayHandler());    /**     * 1、声明一个Handler类,用于处理客户端Message     */    class PayHandler extends Handler {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_CODE_FROM_CLIENT:                    int price = msg.arg1;                    int count = msg.arg2;                    String desc = msg.getData().getString("desc");                    int totalPrice = price * count;                    Log.e(TAG, "总价:" + totalPrice + "\t" + desc);                    /**                     * 实现双向通信,向客户端做出响应                     */                    sendResult(msg, totalPrice);                    break;                default:                    super.handleMessage(msg);                    break;            }        }        /**         * 实现双向通信,该方法用于向客户端发送消息         */        private void sendResult(Message msg, int totalPrice) {            try {                Messenger clientMessenger = msg.replyTo;                Message message = Message.obtain(null, MSG_CODE_FROM_SERVER);                Bundle resultData = new Bundle();                resultData.putString("result", "支付成功,一共花费 " + totalPrice + " 元");                message.setData(resultData);                clientMessenger.send(message);            } catch (RemoteException e) {                e.printStackTrace();            }        }    }}

客户端实现

public class MainActivity extends AppCompatActivity {    /**     * 客户端发送的消息标识     */    public static final int MSG_CODE_FROM_CLIENT = 1;    /**     * 服务端发送的消息标识     */    public static final int MSG_CODE_FROM_SERVER = 2;    private EditText mEtPrice;    private EditText mEtCount;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mEtPrice = (EditText) findViewById(R.id.et_price);        mEtCount = (EditText) findViewById(R.id.et_count);    }    /**     * 1、绑定服务     */    public void bindService(View view) {        Intent intent = new Intent();        intent.setComponent(new ComponentName("com.zhangke.messengerserverdemo", "com.zhangke.messengerserverdemo.IPayService"));        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);    }    Messenger mServerMessenger;    ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            /**             * 2、通过服务端返回的binder对象创建一个Messenger对象, 通过该Messenger对象可以给服务端发送Message             */            mServerMessenger = new Messenger(iBinder);        }        @Override        public void onServiceDisconnected(ComponentName componentName) {            mServerMessenger = null;        }    };    /**     * 3、 通过Messenger对象给服务端发送Message     */    public void pay(View view) throws RemoteException {        Message message = Message.obtain(null, MSG_CODE_FROM_CLIENT);        message.arg1 = Integer.valueOf(mEtPrice.getText().toString().trim());        message.arg2 = Integer.valueOf(mEtCount.getText().toString().trim());        Bundle bundle = new Bundle();        bundle.putString("desc", "优惠价格");        message.setData(bundle);        /**         * 3、实现双向通信,将客户端Messenger对象传递到服务端         */        message.replyTo = mClientMessenger;        mServerMessenger.send(message);    }    /**     * 2、实现双向通信,创建一个客户端Messenger对象,该对象会被传递到服务端,然后服务端会通过该Messenger发送消息给客户端。     */    Messenger mClientMessenger = new Messenger(new ResultHander());    /**     * 1、实现双向通信,创建一个Handler对象,用于处理服务端返回的消息     */    private class ResultHander extends Handler {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_CODE_FROM_SERVER:                    String result = msg.getData().getString("result");                    Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();                    break;                default:                    super.handleMessage(msg);                    break;            }        }    }}

演示效果:
这里写图片描述

演示代码