Messenger

来源:互联网 发布:淘宝 清明上河图 编辑:程序博客网 时间:2024/05/21 18:42

Messenger is based on AIDL. There are several key elements:

  • IMessenger, this interface is same as the interface generated by specific AIDL. It has an inner class of Stub. and contains a member function: void send(Message msg)
  • Handler is also a key element when talks about Messenger. Handler holds an instance that extends IMessenger.Stub (so it holds a Binder), and it's accessed by getIMessenger(), and implementation of that method is:    
    class Handler {     IMessgener mMessenger;     public IMessenger getIMessenger() {          if(mMessenger == null) {               mMessenger = new IMessengerImp();          }          return mMessenger;     }}class IMessengerImp extends IMessenger.Stub {...}

    So a handler actually holds the Binder between service and its remote-process clients.
  • Messenger class, the constructors and some key methods of this class:
    IMessenger mTarget;public Messenger(Handler target) {     // The target is the Handler as we talked about above, it holds a instance that extends IMessenger.Stub (which is both IMessenger and Binder).     mTarget = target;}public Messenger(IBinder target) {     mTarget = new IMessenger.Stub.asInterface(target);}public IBinder getBinder() {     return mTarget.asBinder();}public void send(Message msg) {     mTarget.send(msg); // calls IMessagener.send(), which will finally calls handler.send()}

Steps to create a service and remote process client which can send message to service, and service can get the message from client:

  • Create a service
    public class MessengerService extends Service {    public MessengerService() {    }    private static class MessengerHandler extends Handler {        @Override        public void handleMessage(Message msg) {            switch(msg.what) {                 ...            }        }    }    private final Messenger messenger = new Messenger(new MessengerHandler());     @Override    public IBinder onBind(Intent intent) {        return messenger.getBinder();    }}
  • Create a client
    private ServiceConnection mConnection = new ServiceConnection() {     private Messenger mMessenger;     @Override     public void onServiceConnected(ComponentName className, IBinder service) { // The service parameter is just the return value of Service.onBind().          mMessenger = new Messenger(service);          Message msg = Message.obtain(...);          Bundle data = new Bundle();          data.putString("msg", "XXX");          msg.setData(data);                    mMessenger.send(msg);     }}... and we need logic to bind to service.

Steps to create a service and remote process client, which can achieve two-way communication: 
KEY:Both service and client should holds two messenger, one for receiving message (constructed with a Handler instance), the other for sending message (service gets this messenger from client by calling messge.replyTo; client construct it with a Binder which got from service when onServiceConnected() triggered). 
  • Create service
public class MessengerService extends Service {    public MessengerService() {    }    private static class MessengerHandler extends Handler {        @Override        public void handleMessage(Message msg) {            switch(msg.what) {                 default:                    Messenger clientMessenger = msg.replyTo;                    Message msg = Message.obtain(...);                    Bundle data = new Bundle();                    data.putString("msg", "A reply from server");                    msg.setData(data);                    clientMessenger.send(msg);            }        }    }    private final Messenger messenger = new Messenger(new MessengerHandler());    @Override    public IBinder onBind(Intent intent) {        return messenger.getBinder();    }}
  • Create client
private ServiceConnection mConnection = new ServiceConnection() {     private Messenger mServiceMessenger;     private Messenger mClientMessenger;     private MessengerHandler mHandler = new MessengerHandler();     @Override     public void onServiceConnected(ComponentName className, IBinder service) { // The service parameter is just the return value of Service.onBind().          // Use two different constructor to construct Messenger instance.          mServiceMessenger = new Messenger(service);          mClientMessenger = new Messenger(mHandler);                    Message msg = Message.obtain(...);          Bundle data = new Bundle();          data.putString("msg", "A request from client");          msg.setData(data);          //[KEY STEP]          msg.replyTo = mClientMessenger;          mServiceMessenger.send(msg);     }     private static class MessengerHandler extends Handler {        @Override        public void handleMessage(Message msg) {            switch(msg.what) {                 ...            }        }    }     }



0 0
原创粉丝点击