Messenger进行多进程通信时一次处理一个请求,在服务端不用考虑线程同步的问题,因为服务端不存在并发执行的情况。它的作用主要是为了传递消息,如果需要跨进程调用服务端的方法就不适合使用。
用Messenger实现多线程通信时,服务端:
在服务端创建一个Service来处理客户端的连接请求,同时创建一个Handler并通过这个Handler来创建一个Messenger对象,然后在Service的onBaind方法中返回这个Messenger对象底层的Binder即可。代码如下:
public class MessengerService extends Service { private static final int SAY_HOLLE = 0; private static final String TAG = "MessengerService"; private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch(msg.what){ case SAY_HOLLE: Log.e(TAG, "receive msg from client:" + msg.getData().getString("msg")); break; default: super.handleMessage(msg); } } } private final Messenger mMessenger = new Messenger(new MessengerHandler()); @Nullable @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } }Service在Android Manifest文件中的注册为:
<service android:name=".MessengerService" android:exported="true" android:enabled="true" android:process=":remote"/>通过Android Manifest文件中给Service指定process属性来实现与客户端处于不同的进程。
客户端:
客户端进程首先要绑定服务端的Service,绑定成功之后用服务端返回的IBinder对象创建一个Messenger,即通过onServiceConnected()方法中的IBinder service参数创建一个客户端的Messenger对象,然后通过这个Messenger就可以向服务端发送消息了,发送的消息是Message类型。(新建Message对象,Bundle对象,Bundle对象中放入需要往服务端发送的消息内容,然后将Bundle对象放进Message对象中,最后通过Messenger对象将该Message发送给服务端)代码如下图所示:
public class MainActivity extends AppCompatActivity { private static final int SAY_HOLLE = 0; private static final String TAG = "MainActivity"; private Messenger mService; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = new Messenger(service); Message msg = Message.obtain(null, SAY_HOLLE,0,0); Bundle data = new Bundle(); data.putString("msg", "hello, this is client."); msg.setData(data); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e(TAG, "onCreate"); Intent intent = new Intent(this, MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { unbindService(mConnection); super.onDestroy(); Log.e(TAG, "onDestroy"); } }这样就完成了利用Messenger实现进程间通信的功能。如果需要实现服务端能够回应客户端,那么客户端就应该和服务端一样,需要新建一个Handler,并通过这个Handler新建一个新的Messenger,将这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数在服务端新建一个Messenger对象,发送Message类型的参数就可以回应客户端。
实现上述功能客户端需要添加的代码是:
private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler()); private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch(msg.what){ case TO_HOLLE: Log.e(TAG, "receiver msg from Service:" + msg.getData().getString("reply")); break; default: super.handleMessage(msg); } } }和
msg.replyTo = mGetReplyMessenger;
服务端需要添加的代码是:
Messenger client = msg.replyTo; Message replyMessage = Message.obtain(null, TO_HOLLE); Bundle bundle = new Bundle(); bundle.putString("reply", "嗯, 你的消息我已经收到, 稍后会回复你"); replyMessage.setData(bundle); try { client.send(replyMessage); } catch (RemoteException e) { e.printStackTrace(); }服务端总的完整代码就是:
/** * Created by su on 2017/10/26. */ public class MessengerService extends Service { private static final int SAY_HOLLE = 0; private static final int TO_HOLLE = 1; private static final String TAG = "MessengerService"; private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch(msg.what){ case SAY_HOLLE: Log.e(TAG, "receive msg from client:" + msg.getData().getString("msg")); Messenger client = msg.replyTo; Message replyMessage = Message.obtain(null, TO_HOLLE); Bundle bundle = new Bundle(); bundle.putString("reply", "嗯, 你的消息我已经收到, 稍后会回复你"); replyMessage.setData(bundle); try { client.send(replyMessage); } catch (RemoteException e) { e.printStackTrace(); } break; default: super.handleMessage(msg); } } } private final Messenger mMessenger = new Messenger(new MessengerHandler()); @Nullable @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } }客户端代码是:
public class MainActivity extends AppCompatActivity { private static final int SAY_HOLLE = 0; private static final int TO_HOLLE = 1; private static final String TAG = "MainActivity"; private Messenger mService; private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler()); private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch(msg.what){ case TO_HOLLE: Log.e(TAG, "receiver msg from Service:" + msg.getData().getString("reply")); break; default: super.handleMessage(msg); } } } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = new Messenger(service); Message msg = Message.obtain(null, SAY_HOLLE,0,0); Bundle data = new Bundle(); data.putString("msg", "hello, this is client."); msg.setData(data); // msg.replyTo = mGetReplyMessenger; try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e(TAG, "onCreate"); Intent intent = new Intent(this, MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { unbindService(mConnection); super.onDestroy(); Log.e(TAG, "onDestroy"); } }最后在logcat观察打印输出的结果时,由于服务端和客户端在一个应用的不同进程,客户端在默认的包名进程下,这样不加设置的话只能看到客户端的log打印输出结果,如果要查看服务端的log打印结果,应该在log上设置过滤器,这样才能查看服务端的日志打印结果。如:
这样在logcat中观察服务端打印的信息就如下图所示: