前言:由于公司是做家校安全方面的,所以就有了学生考勤的需求,并要求可进行内外网进行切换。服务器端接收到学生的考勤刷卡信息后采用MQTT协议推送消息到客户端,客户端(TV)接收到推送消息后获取消息内容,将学生考勤刷卡信息展示到TV上。消息推送方式有持久连接(XMPP协议,MQTT,C2DM等)和轮询等方式。本文将介绍基于Paho的轻量级的MQTT协议在Android客户端的实现方式。
原理:MQTT:Message Queuing Telemetry Transport(队列消息遥测传输),MQTT协议是一个轻量级的消息发布/订阅协议,服务器端和客户端通过心跳包的方式进行连接,当服务器端有消息时,客户端通过订阅的相关主题(topic)接收服务器端传输的消息进行处理。
1.导入依赖
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.0'
2.自定义MQTTService
MQTTService继承自Service(四大组件都需在清单文件中配置,稍后再说),重写onStartCommand、onBind等方法
(1)onStartCommand中初始化相关操作
private void init() {
Log.d("", "clientId:" + clientId);
// 服务器地址(协议+地址+端口号)
//String uri = AppConstant.host; String uri = AppConstant.getHost();
Log.d("", "uri:" + uri);
//基于paho的mqtt的MqttAndroidClient(实际上它继承自BroadcastReceiver并实现了IMqttAsyncClient)
client = new MqttAndroidClient(this, uri, clientId);
SpUtil.getInstance(Utils.getContext()).putClientId(clientId);
// 设置MQTT监听并且接受消息
client.setCallback(mqttCallback);
//mqtt连接的参数设置
conOpt = new MqttConnectOptions();
// 清除缓存
conOpt.setCleanSession(true);
// 设置超时时间(单位:秒)
conOpt.setConnectionTimeout(10);
// 心跳包发送间隔(单位:秒)
conOpt.setKeepAliveInterval(20);
//设置用户名及密码
if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(passWord)) {
conOpt.setUserName(userName);
conOpt.setPassword(passWord.toCharArray());
}
//连接
doClientConnection();
}
注:clientId可以用时间戳也可以用MqttClient.generateClientId()获取
2.mqttCallBack的监听接口
// MQTT监听并且接受服务器传来的消息
private MqttCallback mqttCallback = new MqttCallback() {
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String str1 = new String(message.getPayload());
Log.i(TAG, "===========messageArrived:" + str1);
MQTTMessage msg = new MQTTMessage();
//topic 订阅的主题
msg.setTopic(topic);
//服务器传递的数据
msg.setMsg(str1);
//EventBus实现事件的传递
EventBus.getDefault().post(msg);
}
@Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
}
@Override
public void connectionLost(Throwable arg0) {
// 重连机制
doClientConnection();
}
}
3.连接MQTT服务器(doClientConnection)
private void doClientConnection() {
//判断当前client及网络是否连接
if (!client.isConnected() && netIsConnect()) {
try {
//iMqttActionListener监听服务器及客户端是否订阅成功
client.connect(conOpt, null, iMqttActionListener);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
4.iMqttActionListener
// MQTT是否与服务器连接成功
private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken arg0) {
Log.i(TAG, "连接成功 ");
EventBus.getDefault().post(new MQTTConnStatus(true));
}
@Override
public void onFailure(IMqttToken arg0, Throwable arg1) {
arg1.printStackTrace();
// 连接失败,重连
EventBus.getDefault().post(new MQTTConnStatus(false));
}
}
5.定义客户端订阅(subscribe)主题(topic)的相关方法
//主题订阅
public static boolean subscribe(String[] topic) {
int[] qosArray = new int[topic.length];
for (int i = 0; i < qosArray.length; i++) {
//VALUE_QOS为连接次数,默认为1次
qosArray[i] = VALUE_QOS;
}
return subscribe(topic, qosArray); }
/**
* 主题订阅
* @param topic 主题
* @param qos 连接次数
* @return
*/
public static boolean subscribe(String[] topic, int[] qos) {
try {
//调用client的方法订阅主题及设置每次连接的次数
client.subscribe(topic, qos);
} catch (MqttException e) {
e.printStackTrace();
return false;
}
return true; }
3.AndroidMaifest配置
四大主件(Activity、Service、ContentProvider、BroadcastReceiver)在使用时均需在清单文件中进行配置,不然运行时会报错。
配置:
<!-- paho的MqttService -->
<service android:name="org.eclipse.paho.android.service.MqttService" />
<!-- 自定义的service -->
<service android:name=".MQTTService" />
4.Activity中使用
(1)开启服务(startService)
startService(serviceIntent = new Intent(this, MQTTService.class));
(2)订阅主题(subscribe)
private void sub(String[] topic) {
if (MQTTService.subscribe(topic)) {
Log.d("", "订阅成功");
} else {
Log.d("", "订阅失败");
}
}
Paho的官网地址:http://www.eclipse.org/paho/
基于Paho的MQTT协议推送消息的Android端就实现了,不足之处,欢迎斧正!!!
网友评论