本文例子中的完整代码已上传github:Messenger,如果对您有帮助,给个star吧,不胜感激~☺
Messenger 是基于消息(Message)的进程间通信方式。使用Messenger为服务创建接口,服务可以这种方式定义对应于不同类型Message对象的Handler,此Handler是Messenger的基础,Messenger随后可与客户端分享一个IBinder,从而让客户端能利用Message对象向服务发送命令。客户端还可以自定义Messenger来实现双向通信。
Messenger使用起来比AIDL更简单,如果对AIDL不了解,可以看下这篇:Android进程间通信之AIDL,Messenger的底层其实还是AIDL实现的,Messenger会将所有服务调用排入队列,依次调用;而AIDL接口会同时向服务发送多个请求,所以服务端必须处理好多线程。
Messenger使用步骤:
- 服务端创建一个Handler,用来接收客户端每个调用的回调
- Handler用于创建Messenger对象(对Handler的引用),在Handler中的 handleMessage()方法中处理客户端传过来的Message。
- Messenger创建一个IBinder,服务端通过onBind()方法使其返回客户端
- 客户端使用IBinder将Messenger(引用服务的Handler)实例化,然后使用后者将Message对象发送给服务端。
- 如果客户端想接收服务器的响应,则需要客户端也创建一个Messenger,当客户端收到ServiceConnection中的onServiceConnected()回调时,会向服务端发送一条Message,将客户端的Messenger赋值给Message的replyTo参数。
下面举个栗子,先上效果图:
客户端代码:MessengerActivity.class
首先,编写Messenger准备接收服务器返回的信息:
Messenger messenger = new Messenger(new ClientHandler());
private class ClientHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
//根据msg.what来区分服务器返回的不同信息
case ServerThinking:
showMessage("\n服务器正在绞尽脑汁的思考...");
break;
case MESS_FROM_SERVER:
Bundle bundle = msg.getData();
String responseInfo = bundle.getString(RESPONSE_KEY);
if (!TextUtils.isEmpty(responseInfo)) {
showMessage("\n" + responseInfo, R.color.red_f);
}
break;
}
}
}
然后编写ServiceConnection类用来接收回调并向服务端发送Message:
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接成功
showMessage("\n连接远程服务端成功!", R.color.blue_color);
isBound = true;
mService = new Messenger(service);
String question = "\n客户端:程序猿最讨厌皇帝的第几个儿子?";
Message message = Message.obtain(null, MESS_FROM_CLIENT);
//Messenger用来接收服务端发来的信息
message.replyTo = messenger;
try {
//将Message发送到服务端
mService.send(message);
showMessage(question, R.color.red_f);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//连接失败
mService = null;
isBound = false;
}
};
最后,绑定Service服务端:
Intent intent = new Intent();
intent.setAction("android.mq.messenger.service");
intent.setPackage("org.ninetripods.mq.multiprocess_sever");
bindService(intent, connection, BIND_AUTO_CREATE);
服务端代码:MessengerService.java
private HandlerThread thread;
private Handler serverHandler;
private Messenger messenger;
@Override
public void onCreate() {
super.onCreate();
//创建一个名字为my_thread的线程
thread = new HandlerThread("my_thread");
//启动一个线程
thread.start();
//在这个线程中创建一个handler
serverHandler = new Handler(thread.getLooper()) {
@Override
public void handleMessage(Message msgFromClient) {
super.handleMessage(msgFromClient);
Message replyToClient = Message.obtain(msgFromClient);
switch (msgFromClient.what) {
//根据Message.what来判断执行服务端的哪段代码
case MESS_FROM_CLIENT:
replyToClient.what = ServerThinking;
try {
Thread.sleep(1000);
//向客户端发送Message
msgFromClient.replyTo.send(replyToClient);
Thread.sleep(3 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
replyToClient.what = MESS_FROM_SERVER;
Bundle bundle = new Bundle();
bundle.putString(RESPONSE_KEY, "服务器:我知道答案啦,是第八个儿子,因为他是八阿哥(bug)");
replyToClient.setData(bundle);
try {
//通过Bundle 封装数据并发送到客户端
msgFromClient.replyTo.send(replyToClient);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
//构建一个Messenger
messenger = new Messenger(serverHandler);
}
@Override
public IBinder onBind(Intent intent) {
//通过onBind()返回Binder实例供客户端调用
return messenger.getBinder();
}
最后别忘了声明Service:
<service
android:name=".MessengerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.mq.messenger.service" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
代码看上去还是很简单的,完整代码已上传github:Messenger,如果对您有帮助,给个star吧,不胜感激~☺**(注:项目中有两个项目,请确保先启动Server端,否则看不到效果)**