本文学习目标:
- 学会如何使用Messenger进行跨进程通讯;
- 延伸阅读:
Android 消息处理机制:https://www.jianshu.com/p/02962454adf7
在上一章中介绍了服务使用,服务启动的两种方式,startService()和bindService(),startService启动的服务,跟启动它的应用组件是没有联系的,因此不管是否跨进程,startService都是可以成功的。而在跨进程服务,bindService()会异常,在onServiceConnected方法中报类型转换异常,说明这时候不能使用这个Binder对象进行转换了。这时候,就需要使用Messenger了。
其实Messenger底层也是使用aidl的方式来实现的,只不过其使用handler来处理消息,因为handler是线程安全的,所以Messenger也是线程安全的,自然Messenger只能处理单线程的问题,如果要使用多线程就该使用aidl的方式实现。
其实,Messenger也是通过bindService的方式,只是需要定义不用的IBinder对象。
主要步骤:
- 服务实现Handler,来处理客户端发送的消息Message;
- 根据Handler创建一个Messenger对象;
- 通过onBinder返回Messenger的Binder对象;
- 客户端使用IBinder将Messenger实例化,然后通过Messenger将Message发送给服务;
public class MessengerService extends Service {
public final static String TAG = MessengerService.class.getSimpleName();
public final static int MSG_SAY_HELLO = 1;
public MessengerService() {
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
/**
* 1. 定义一个Handler,用于处理客户端发来的请求
*/
class ProcessHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_SAY_HELLO:
Log.d(TAG, "service receiver from client: say hello");
break;
default:
super.handleMessage(msg);
}
}
}
/**
* 2. 创建一个Messenger并传入Handler实例对象
*/
final Messenger mMessager = new Messenger(new ProcessHandler());
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
// 3.通过onBinder返回Messenger的Binder对象
return mMessager.getBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
}
}
清单定义:
<service
android:name=".MessengerService"
android:enabled="true"
android:exported="true"
android:process=":messengerSer"/>
/**
* 与服务端交互的Messender
*/
Messenger mService = null;
boolean mBound = false;
/**
* ServiceConnection代表与服务的连接,
*/
ServiceConnection cnn2 = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.d("###", "onServiceConnected");
/**
* 3. 通过服务端传递的IBinder对象,创建相应的Messenger
* 然后通过Messenger对象与服务端进行交互
*/
mService = new Messenger(iBinder);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d("###", "onServiceDisconnected");
mService = null;
mBound = false;
}
};
// 绑定服务
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, cnn2, BIND_AUTO_CREATE);
// 解绑服务
unbindService(cnn2);
mBound = false;
// 发送消息
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO);
try {
// 4. 通过Messenger发送消息
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
流程图:
效果:
此时,解决了客户端往服务发送消息。如果客户端需要接收服务的消息呢?
我们需要在客户端定义一个Messenger和Handler,然后发送消息的时候传递这个Messenger。
/**
* 定义客户端的Messenger和Handler
*/
Messenger repo = new Messenger(new ClientHandler());
class ClientHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MessengerService.MSG_REPO_SAY_HELLO:
Log.d("####", "client receive from server say hello");
break;
default:
super.handleMessage(msg);
}
}
}
发送消息的时候,设置replyTo
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO);
msg.replyTo = repo; // 传递Messenger
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
服务在处理Message时候,取出客户端的Messenger,然后发送消息
class ProcessHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_SAY_HELLO:
Log.d(TAG, "service receiver from client: say hello");
Messenger repo = msg.replyTo; // 获取客户端Messenger
Message rmsg = Message.obtain(null, MSG_REPO_SAY_HELLO);
try {
// 发送消息
repo.send(rmsg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
效果:
服务:
客户端: