前言:由于公司是做家校安全方面的,所以就有了学生考勤的需求,并要求可进行内外网进行切换。服务器端接收到学生的考勤刷卡信息后采用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端就实现了,不足之处,欢迎斧正!!!