android 实现mqtt消息推送,以及不停断线重连的问题解决

该博客分享了在Android项目中使用MQTT进行消息推送的代码实现。包括添加依赖、编辑AndroidManifest.xml,新建MyMqttService类实现连接服务器、断线重连、订阅消息、处理消息、发布消息等操作,还设置了自动重连等连接选项。

前段时间项目用到mqtt的消息推送,整理一下代码,代码的原型是网上找的,具体哪个地址已经忘记了。

代码的实现是新建了一个MyMqttService,全部功能都在里面实现,包括连服务器,断线重连,订阅消息,处理消息,发布消息等基本操作。

首先添加依赖:

[html]  view plain  copy
  1. dependencies {  
  2.     implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'  
  3.     implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'  
  4. }  

然后编辑AndroidManifest.xml,先添加权限:

[html]  view plain  copy
  1. <uses-permission android:name="android.permission.INTERNET" />  
  2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  3. <uses-permission android:name="android.permission.WAKE_LOCK" />  

再注册service:

[html]  view plain  copy
  1. <service android:name="org.eclipse.paho.android.service.MqttService" />  
  2. <service  
  3.     android:name=".service.MyMqttService"  
  4.     android:enabled="true"  
  5.     android:exported="true"/>  

接着进入正文MyMqttService.java,功能见注释吧:

[java]  view plain  copy
  1. package com.example.nan.mqtt.service;  
  2.   
  3. import android.app.Notification;  
  4. import android.app.NotificationManager;  
  5. import android.app.PendingIntent;  
  6. import android.app.Service;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.graphics.BitmapFactory;  
  10. import android.os.Bundle;  
  11. import android.os.IBinder;  
  12. import android.support.v4.app.NotificationCompat;  
  13. import android.util.Log;  
  14.   
  15. import com.google.gson.Gson;  
  16. import com.google.gson.reflect.TypeToken;  
  17.   
  18. import org.eclipse.paho.android.service.MqttAndroidClient;  
  19. import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions;  
  20. import org.eclipse.paho.client.mqttv3.IMqttActionListener;  
  21. import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;  
  22. import org.eclipse.paho.client.mqttv3.IMqttToken;  
  23. import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;  
  24. import org.eclipse.paho.client.mqttv3.MqttConnectOptions;  
  25. import org.eclipse.paho.client.mqttv3.MqttException;  
  26. import org.eclipse.paho.client.mqttv3.MqttMessage;  
  27. import org.json.JSONObject;  
  28.   
  29. /** 
  30.  * @author nan 
  31.  */  
  32. public class MyMqttService extends Service {  
  33.   
  34.     private static final String TAG = "nlgMqttService";  
  35.     private static final String TOPIC_TO_QA = "/s2c/task_quality/";  
  36.   
  37.     private static final String publishTopic = "exampleAndroidPublishTopic";  
  38.   
  39.     private MqttAndroidClient mqttAndroidClient;  
  40.     private NotificationManager mNotificationManager;  
  41.   
  42.   
  43.     public MyMqttService() {  
  44.     }  
  45.   
  46.     @Override  
  47.     public IBinder onBind(Intent intent) {  
  48.         // TODO: Return the communication channel to the service.  
  49.         throw new UnsupportedOperationException("Not yet implemented");  
  50.     }  
  51.   
  52.     @Override  
  53.     public void onCreate() {  
  54.         super.onCreate();  
  55.         Log.d(TAG, "MqttService onCreate executed");  
  56.         //mqtt服务器的地址  
  57.         final String serverUri = "tcp://192.168.10.10:1883";  
  58.         //新建Client,以设备ID作为client ID  
  59.         mqttAndroidClient = new MqttAndroidClient(MyMqttService.this, serverUri, getIMEI());  
  60.         mqttAndroidClient.setCallback(new MqttCallbackExtended() {  
  61.             @Override  
  62.             public void connectComplete(boolean reconnect, String serverURI) {  
  63.         //连接成功  
  64.                 if (reconnect) {  
  65.                     Log.d(TAG, "connectComplete: " + serverURI);  
  66.                     // Because Clean Session is true, we need to re-subscribe  
  67.                     subscribeAllTopics();  
  68.                 } else {  
  69.                     Log.d(TAG, "connectComplete: " + serverURI);  
  70.                 }  
  71.             }  
  72.   
  73.             @Override  
  74.             public void connectionLost(Throwable cause) {  
  75.         //连接断开  
  76.                 Log.d(TAG, "connectionLost: connection was lost");  
  77.             }  
  78.   
  79.             @Override  
  80.             public void messageArrived(String topic, MqttMessage message) {  
  81.         //订阅的消息送达,推送notify  
  82.                 String payload = new String(message.getPayload());  
  83.                 Log.d(TAG, "Topic: " + topic + " ==> Payload: " + payload);  
  84.                 if(mNotificationManager == null) {  
  85.                     mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  86.                 }  
  87.                 int roleId = SinSimApp.getApp().getRole();  
  88.                 Gson gson = new Gson();  
  89.                 ServerToClientMsg msg = gson.fromJson(payload, new TypeToken<ServerToClientMsg>(){}.getType());  
  90.                 if(msg != null) {  
  91.             //接受消息  
  92.             if(topic != null) {  
  93.             if(topic.equals(TOPIC_TO_QA)) {  
  94.                 Intent intent = new Intent(MyMqttService.this, ProcessToCheckoutActivity.class);  
  95.                 PendingIntent pi = PendingIntent.getActivity(MyMqttService.this0, intent, 0);  
  96.                 NotificationCompat.Builder builder = new NotificationCompat.Builder(MyMqttService.this, TOPIC_TO_QA);  
  97.                 Notification notify = builder.setSmallIcon(R.mipmap.to_quality)  
  98.                         .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.to_quality))  
  99.                         .setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_VIBRATE)//响铃震动  
  100.                         .setContentTitle("快递来了")  
  101.                         .setAutoCancel(true)  
  102.                         .setContentIntent(pi)  
  103.                         .setVisibility(Notification.VISIBILITY_PUBLIC)  
  104.                         .setContentText("你的快递单号:" + msg.getOrderNum())  
  105.                         //不设置此项不会悬挂,false 不会出现悬挂  
  106.                         .build();  
  107.                 mNotificationManager.notify(2,notify);  
  108.             }   
  109.                     }  
  110.                 }  
  111.             }  
  112.   
  113.             @Override  
  114.             public void deliveryComplete(IMqttDeliveryToken token) {  
  115.                 //即服务器成功delivery消息  
  116.             }  
  117.         });  
  118.     //新建连接设置  
  119.         MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();  
  120.         //断开后,是否自动连接  
  121.         mqttConnectOptions.setAutomaticReconnect(true);  
  122.         //是否清空客户端的连接记录。若为true,则断开后,broker将自动清除该客户端连接信息  
  123.         mqttConnectOptions.setCleanSession(false);  
  124.         //设置超时时间,单位为秒  
  125.         //mqttConnectOptions.setConnectionTimeout(2);  
  126.         //心跳时间,单位为秒。即多长时间确认一次Client端是否在线  
  127.         //mqttConnectOptions.setKeepAliveInterval(2);  
  128.         //允许同时发送几条消息(未收到broker确认信息)  
  129.         //mqttConnectOptions.setMaxInflight(10);  
  130.         //选择MQTT版本  
  131.         mqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);  
  132.         try {  
  133.             Log.d(TAG, "onCreate: Connecting to " + serverUri);  
  134.         //开始连接  
  135.             mqttAndroidClient.connect(mqttConnectOptions, nullnew IMqttActionListener() {  
  136.                 @Override  
  137.                 public void onSuccess(IMqttToken asyncActionToken) {  
  138.                     Log.d(TAG, "onSuccess: Success to connect to " + serverUri);  
  139.                     DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();  
  140.                     disconnectedBufferOptions.setBufferEnabled(true);  
  141.                     disconnectedBufferOptions.setBufferSize(100);  
  142.                     disconnectedBufferOptions.setPersistBuffer(false);  
  143.                     disconnectedBufferOptions.setDeleteOldestMessages(false);  
  144.                     mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);  
  145.             //成功连接以后开始订阅  
  146.                     subscribeAllTopics();  
  147.                 }  
  148.   
  149.                 @Override  
  150.                 public void onFailure(IMqttToken asyncActionToken, Throwable exception) {  
  151.                     //连接失败  
  152.             Log.d(TAG, "onFailure: Failed to connect to " + serverUri);  
  153.                     exception.printStackTrace();  
  154.                 }  
  155.             });  
  156.         } catch (MqttException ex) {  
  157.             ex.printStackTrace();  
  158.         }  
  159.   
  160.     //service绑定notification  
  161.         Intent intent = new Intent(this, SplashActivity.class);  
  162.         intent.putExtra(SinSimApp.FROM_NOTIFICATION, true);  
  163.         //这边设置“FLAG_UPDATE_CURRENT”是为了让后面的Activity接收pendingIntent中Extra的数据  
  164.         PendingIntent pi = PendingIntent.getActivity(this0, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
  165.         Notification notification = new NotificationCompat.Builder(this)  
  166.                 .setContentTitle("mqtt快递")  
  167.                 .setContentText("mqtt快递管理系统")  
  168.                 .setWhen(System.currentTimeMillis())  
  169.                 .setSmallIcon(R.mipmap.ic_launcher)  
  170.                 .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))  
  171.                 .setContentIntent(pi)  
  172.                 .build();  
  173.         startForeground(1, notification);  
  174.     }  
  175.   
  176.     //订阅所有消息  
  177.     private void subscribeAllTopics() {  
  178.     subscribeToTopic(TOPIC_TO_QA);  
  179.     }  
  180.   
  181.     /** 
  182.      * 订阅消息 
  183.      */  
  184.     public void subscribeToTopic(String subscriptionTopic) {  
  185.         try {  
  186.             mqttAndroidClient.subscribe(subscriptionTopic, 2nullnew IMqttActionListener() {  
  187.                 @Override  
  188.                 public void onSuccess(IMqttToken asyncActionToken) {  
  189.                     Log.d(TAG, "onSuccess: Success to Subscribed!");  
  190.                 }  
  191.   
  192.                 @Override  
  193.                 public void onFailure(IMqttToken asyncActionToken, Throwable exception) {  
  194.                     Log.d(TAG, "onFailure: Failed to subscribe");  
  195.                 }  
  196.             });  
  197.         } catch (MqttException ex) {  
  198.             Log.d(TAG, "subscribeToTopic: Exception whilst subscribing");  
  199.             ex.printStackTrace();  
  200.         }  
  201.     }  
  202.   
  203.     /** 
  204.      * 发布消息 
  205.      */  
  206.     public void publishMessage(String msg) {  
  207.         try {  
  208.             MqttMessage message = new MqttMessage();  
  209.             message.setPayload(msg.getBytes());  
  210.             mqttAndroidClient.publish(publishTopic, message);  
  211.             Log.d(TAG, "publishMessage: Message Published: " + msg);  
  212.         } catch (MqttException e) {  
  213.             Log.d(TAG, "publishMessage: Error Publishing: " + e.getMessage());  
  214.             e.printStackTrace();  
  215.         }  
  216.     }  
  217.   
  218.     @Override  
  219.     public int onStartCommand(Intent intent, int flags, int startId) {  
  220.         Log.d(TAG, "MqttService onStartCommand executed");  
  221.         return super.onStartCommand(intent, flags, startId);  
  222.     }  
  223.   
  224.     @Override  
  225.     public void onDestroy() {  
  226.         super.onDestroy();  
  227.         try {  
  228.             if(mqttAndroidClient!=null){  
  229.         //服务退出时client断开连接  
  230.                 mqttAndroidClient.disconnect();  
  231.             }  
  232.         } catch (MqttException e) {  
  233.             e.printStackTrace();  
  234.         }  
  235.         Log.d(TAG, "MqttService onDestroy executed");  
  236.     }  
  237. }  
调试过程中出现过一个小插曲:服务在有些时候会不停的断线重连。断线重连的设置是开了的:
[java]  view plain  copy
  1. mqttConnectOptions.setAutomaticReconnect(true);  
但是断开的原因找不到,当时还没有重写onDestory方法,就算退出应用也还在重连,一度怀疑service的开启与关闭的问题,还系统的重新学习了一下service的使用,学完以后也没有啥进展,然后重学mqtt的调用流程发挥了效果,在onDestory里面调用了disconnect()方法,完了以后在退出应用以后就不会重连了,但是重新开还是继续不停重连。到了晚上,奇怪的事情发生了,当夜深人静,独自加班的时候,居然再也复现不了了。为什么呢,心想可能平时给八阿哥上的香起了效果,那就开心的回家吧。下班的路上虽然开心的吃了块鸡排,但心里的结还是没有打开,为什么呢,是道德的沦丧还是人性的扭曲,让我独自加班还不饿给我复现问题。突然灵光一现,想到今天特么加班就我一个人,也就是一个人玩就是好的,玩的人多就会有问题,那么答案就来了,跟唯一性有关的只有clientID了,特么老子把clientID设置成用户id了,测试用的用户id就注册了3个,好几个人来回切着用,不出问题才怪。于是我默默的把clientID改成了设备id,困扰2天的问题就这么解决了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值