在介绍使用Messenger跨进程通信之前先要了解以下问题:多进程是啥?我个人将不同进程简单的理解为不同的应用程序,当然也有例外,比如可以在同一个应用程序中开启两个或多个进程。由于进程之间不能像线程一样共享内存,所以数据通信不能像线程一般进行。在Android中可以使用广播,Messenger,AIDL和Socket进行跨进程通信。本章利用Messenger进行多进程双向通信。
Messenger是通过使用Message来实现跨进程通信,一次实现一个请求的方式,这是它的优点也是缺点。
其底层实现为AIDL(下篇讲解icp通信机制之二),Messenger的优点是:
1.基于Message,方便使用;
2.支持回调的方式,也就是服务端处理完成长任务可以和客户端交互;
3.不需要编写aidl文件。
Messenger使用流程如下:
Service实现:
(记得在mainfest中注册<serviceandroid:name="com.lzy.cn.ble.BleService"android:process=":remote"/>這樣service就是另一個進程了)
具体思路是:
创建一个Handler对象用来处理客户端发送来的消息,再创建一个Messenger对象将上面的Handler对象作为参数传入,这样我们就获得了一个信使。下面就是通过getBinder()把这个信使创建的Binder对象返回给客户端(一旦客户端拿到这个Binder,又可以将它还原为Messenger)。Handler中处理信息为:当得到的Message的what值为MSG_REGISTER時候,用客戶端Messenger引用回復。
public class BleService extends Service { static final int MSG_REGISTER = 1; static final int MSG_UNREGISTER = 2; static final int MSG_TO_CLIENT = 3; private final IncomingHandler mHandler = new IncomingHandler(this); private final Messenger mMessenger = new Messenger(mHandler); private final List<Messenger> mClients = new LinkedList<Messenger>();//维护客户端Messenger的队列 private Messenger clientMessenger = null; @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } private static class IncomingHandler extends Handler { private final WeakReference<BleService> mService; public IncomingHandler(BleService service) { //弱引用可以使我们保持对父类对象的引用,并且不会阻止它被垃圾回收机制回收(静态内部类不持有访问父类属性和方法的能力) mService = new WeakReference<BleService>(service); } @Override public void handleMessage(Message msg) { BleService service = mService.get(); if (service != null) { switch (msg.what) { case MSG_REGISTER://收到客户端注册消息 service.mClients.add(msg.replyTo);//msg.replyTo 为客户端传过来的Messenger对象 service.clientMessenger = msg.replyTo; Message msg1 = Message.obtain(); msg1.what = MSG_TO_CLIENT; Bundle bundle = new Bundle(); bundle.putString("msg", "欢迎客户端注册"); msg1.setData(bundle); try { service.clientMessenger.send(msg1); } catch (RemoteException e) { e.printStackTrace(); } break; case MSG_UNREGISTER://收到客户端取消注册消息 service.mClients.remove(msg.replyTo); Log.d(TAG, "Unegistered"); break; default: super.handleMessage(msg); } } } } }
Activity实现
在客户端中我们应该做的是:通过bindservice拿到服务端传来的Messenger对象,然后创建一个Message对象,为Message写入数据,注意Message中的what要与服务端中Handler对象中的what一致。使用该Messenger通过send()将Message发送给服务端,这样就可以实现客户端与服务端的双向通信了。
public class BleActivity extends Activity { private final Messenger mMessenger = new Messenger(new IncomingHandler(this)); private Intent mServiceIntent; private Messenger mService = null; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = new Messenger(service);//通过IBinder获取服务端的messenger引用 try { Message msg = Message.obtain(null, BleService.MSG_REGISTER); if (msg != null) { msg.replyTo = mMessenger; mService.send(msg);//将自己的Messenger发给服务端引用 } else { mService = null; } } catch (Exception e) { Log.w(TAG, "Error connecting to BleService", e); mService = null; } } @Override public void onServiceDisconnected(ComponentName name) { mService = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ble); mServiceIntent = new Intent(this, BleService.class); } @Override protected void onStart() { super.onStart(); bindService(mServiceIntent, mConnection, BIND_AUTO_CREATE); } @Override protected void onStop() { if (mService != null) { try { Message msg = Message.obtain(null, BleService.MSG_UNREGISTER); if (msg != null) { msg.replyTo = mMessenger; mService.send(msg); } } catch (Exception e) { Log.w(TAG, "Error unregistering with BleService", e); mService = null; } finally { unbindService(mConnection); } } super.onStop(); } private static class IncomingHandler extends Handler { private final WeakReference<BleActivity> mActivity; public IncomingHandler(BleActivity activity) { mActivity = new WeakReference<BleActivity>(activity); } @Override public void handleMessage(Message msg) { BleActivity activity = mActivity.get(); if (activity != null) { switch (msg.what) { case BleService.MSG_TO_CLIENT : Bundle bundle = msg.getData() String textMsg = bundle.getString("msg") Log.i("tag","客户端回復你:"+textMsg ); break; } } super.handleMessage(msg); } } }