关于Messenger实现进程间通信

370 阅读3分钟

1.Messenger与AIDL的区别

  • 当需要进行进程间通信时,使用 Messenger 要比使用 AIDL 实现它更加简单,它不需要实现aidl接口
  • 支持回调,他可以与客户端进行交互
  • Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
  • 对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。
  • 但是如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。

2.如何使用Messenger进行进程间通信

  1. 服务实现一个 Handler,由其接收来自客户端的每个调用的回调
  2. Handler 用于创建 Messenger 对象(对 Handler 的引用)
  3. Messenger 创建一个 IBinder,服务通过 onBind() 使其返回客户端
  4. 客户端使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用后者将 Message 对象发送给服务。在本地新建一个clientMessenger(引用本地新建的Handler)实例化,在发送对象给服务时,通过Message.replyto方法设置为clientMessenger,以便服务端与客户端进行通信。
  5. 服务在其 Handler 中(具体地讲,是在 handleMessage() 方法中)接收每个 Message,通过msg.replyto拿到客户端的Messenger实例,通过该messenger与客户端进行交互。

3.Messenger使用示例

  1. 新建服务端apk,创建服务类MessengerService

    public class MessengerService extends Service {
     /** Command to the service to display a message */
     static final int MSG_SAY_HELLO = 1;
     static final int MSG_SAY_HELLO_TO_CLIENT = 2;
     private static final String TAG = "MessengerService";
    
     /** get Messenger from client **/
     private Messenger clientMessenger;
     /**
      * Handler of incoming messages from clients.
      */
     class IncomingHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_SAY_HELLO:
                     Log.i(TAG, "handleMessage: "+"服务端收到客户端消息");
                     Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                     clientMessenger = msg.replyTo;
                     if(clientMessenger != null){
                         Message msgToClient = Message.obtain();
                         msgToClient.what = MSG_SAY_HELLO_TO_CLIENT;
                         try {
                             clientMessenger.send(msgToClient);
                         } catch (RemoteException e) {
                             e.printStackTrace();
                         }
                     }
                     break;
                 default:
                     super.handleMessage(msg);
             }
         }
     }
    
     /**
      * Target we publish for clients to send messages to IncomingHandler.
      */
     final Messenger mMessenger = new Messenger(new IncomingHandler());
    
     /**
      * When binding to the service, we return an interface to our messenger
      * for sending messages to the service.
      */
     @Override
     public IBinder onBind(Intent intent) {
         Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
         return mMessenger.getBinder();
     }
    }

    2.新建客户端apk,创建客户端ClientActivity

public class ClientActivity extends Activity {
    @BindView(R.id.messenger_test)
    Button messengerBtn;
    private static final int MSG_SAY_HELLO = 1;
    private static final int MSG_SAY_HELLO_TO_CLIENT = 2;
    /** Messenger for communicating with the service. */
        Messenger mService = null;
        /** Flag indicating whether we have called bind on the service. */
        private Messenger clientMessenger = new Messenger(new ClientHandler());


        private class ClientHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == MSG_SAY_HELLO_TO_CLIENT) {
                    Log.i("ClientActivity", "客户端收到Service的消息: ");
                }
            }
        }


    boolean mBound;

    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.

            mService = new Messenger(service);
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
            mBound = false;
        }
    };

    public void sayHello() {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        Message msg = Message.obtain(null, MSG_SAY_HELLO, 0, 0);
        msg.replyTo = clientMessenger;
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        ButterKnife.bind(this);

        messengerBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Bind to the service

                sayHello();
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent("com.installer.ServerService"), mConnection,
                Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}