前天写了一篇关于Binder连接池实现特殊场景的IPC通讯,当然,使用aidl实现IPC和Messenger的使用场景是完全不同的,aidl是可以覆盖Messenger的功能的,因为后者是前者的封装,使用方便但是场景和功能受限;下面就来看看Messenger的具体使用吧;在介绍之前先介绍一个场景:
公司大C想要公司大S合作,想找大S公司给他们提供一些功能服务;在合作关系确认后,大C公司就派出了小c工程师全权负责和大S公司的沟通,大S公司也是一样,派出了小s工程师负责和大C公司的沟通;对于大C公司来说,我们有任何消息直接通知到小s工程师就可以了(让小s工程师带回去就可以),对于大S公司来说,我们有任何消息通知到小c就可以了(让小c工程师带回去就可以了)。
上面说的大C和大S就代表客户端和服务端;小c工程师和小s工程师就代表客户端和服务端传递消息的信使(Messenger)
1,使用步骤
服务端:
第一步:创建自定义Handler,就是小s接收到消息后如何处理(小s的思想和身体)
第二步:拿着小s的思想和身体构建一个小s出来(一个Messenger)
第三步:在大C联系大S公司的时候,把小s的联系方式Binder给出去(getBinder())
服务端就做完了
客户端:
第一步:绑定服务,先找大C公司沟通并确认合作关系
第二步:创建自定义Handler,就是小c收到消息后如何处理(小c的思想和身体)
第三步:拿着小c的思想和身体构建一个小c出来(一个Messenger)
第四步:在获取到小s的联系方式后,主动把自己的联系方式告诉对方(初始化message.replyTo参数)
客户端做完了
之后他们就可以沟通啦!
2,下面来看一个简单的示例
服务端:
MyService.java代码:
package com.hfut.operationmessagerserver;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
/**
* @author why
* @date 2018-7-22 13:50:47
*/
public class MyService extends Service {
private static final String TAG = "MyService";
private final static int MESSAGE_FROM_SERVER=11;
public final static int MESSAGE_FROM_CLIENT1 = 1;
private static int count=0;
private static String[] anwser=new String[]{"我很好,你怎么样?","我今天休息,你们加班了吗?","累的一笔!"};
//由消息处理器实例构建一个Messenger
private final static Messenger messenger=new Messenger(new MyHandler());
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
}
//自定义一个消息处理器
private static class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_FROM_CLIENT1:
Log.i(TAG, "handleMessage: Message from client1:"+msg.getData().get("client1_msg"));
if(count>=3){
count=0;
}
//构建消息内容
Bundle content=new Bundle();
content.putString("server_msg","服务端:"+anwser[count]);
count++;
//创建消息对象
Message message=Message.obtain(null,MESSAGE_FROM_SERVER);
message.setData(content);
//发送消息
try {
msg.replyTo.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
break;
}
super.handleMessage(msg);
}
}
//绑定该服务时返回Messenger中获取的Binder对象实例,建立连接
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return messenger.getBinder();
}
}
主配置AndroidManifest.xml文件代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hfut.operationmessagerserver">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="hfut.com.why"></action>
</intent-filter>
</service>
</application>
</manifest>
客户端:
MainActivity.java代码:
package com.hfut.operationmessengerclient1;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author why
* @date 2018-7-22 14:00:10
*/
public class MainActivity extends AppCompatActivity {
private static int count=0;
String[] question=new String[]{"最近怎么样?","还行吧,就是工资太低了!","别提了,老是加班,你们应该不累吧"};
private static final String TAG = "MainActivity";
private final static int MESSAGE_FROM_CLIENT1 = 1;
private final static int MESSAGE_FROM_SERVER = 11;
//服务端信使
private Messenger messenger;
private ServiceConnection connection;
Timer timer=new Timer();
//客户端信使
private Messenger getReplyMessenger=new Messenger(new Myhandler());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定服务
Intent intent = new Intent();
intent.setPackage("com.hfut.operationmessagerserver");
intent.setAction("hfut.com.why");
connection = new MyServiceConnection();
bindService(intent, connection, BIND_AUTO_CREATE);
}
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//构建通道
messenger = new Messenger(iBinder);
timer.schedule(new TimerTask() {
@Override
public void run() {
sendMessageToServer(messenger);
}
},1000,2000);
System.out.println("绑定服务成功了");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
System.out.println("解绑服务成功了");
}
}
private void sendMessageToServer(Messenger messenger){
//创建消息内容
Bundle content = new Bundle();
if(count>=3){
count=0;
}
content.putString("client1_msg","客户端:"+ question[count]);
count++;
//创建消息对象
Message message = Message.obtain(null, MESSAGE_FROM_CLIENT1);
message.setData(content);
//构建客户端信使
message.replyTo=getReplyMessenger;
//发送消息
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
//自定义处理器,处理服务端过来的消息
private static final class Myhandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_FROM_SERVER:
Log.i(TAG, "handleMessage: " + msg.getData().getString("server_msg"));
break;
default:
break;
}
}
}
@Override
protected void onDestroy() {
if (timer!=null){
timer.cancel();
}
if(connection!=null){
unbindService(connection);
}
super.onDestroy();
}
}
3,运行结果
这里都是最基本的使用,可以进行很多扩展,通常结合aidl使用比较实用,因为这是一种轻量级的IPC方案。不过确实很方便使用起来。这里还特别推荐看一下任玉刚老师《Android开发艺术探索》中的Messenger工作原理图。