一、MQTT介绍

链接1(菜鸟教程):https://www.runoob.com/w3cnote/mqtt-intro.html

连接2(MQTT中文网):http://mqtt.p2hp.com/

连接3(Android开发之Mqtt的使用):https://blog.csdn.net/asjqkkkk/article/details/80714234

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)。一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议。构建于TCP/IP协议上,由IBM在1999年发布。

二、程序示例

 public class MqttManager {

     private static boolean initFirst = true;//是否第一次初始化mqtt标识符
private static String host = "tcp://47.106.172.221:8081";
private static String userName; //mqtt用户名
private static String passWord; //mqtt登陆密码
private static MqttManager manager;
private static MqttClient mqttClient;
private static MqttConnectOptions options;
private static String topic;//订阅的主题
private static String clientId; //客户端id private static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
KLog.d(msg.obj);
EventBus.getDefault()
.post(new MessageEventBean(AppConstants.MQTT_EVENT_TYPE, (String) msg.obj));
} else if (msg.what == 2) {
KLog.d("连接成功");
try {
KLog.d("订阅的主题:" + topic);
mqttClient.subscribe(topic, 0); } catch (Exception e) {
e.printStackTrace();
}
} else if (msg.what == 3) {
KLog.d("连接失败,系统正在重连");
}
}
}; private MqttManager() { }
private static MqttCallback myMqttCallback = new MqttCallback(){ @Override
public void messageArrived(String topic, MqttMessage message){
//subscribe后得到的消息会执行到这里面
KLog.d("messageArrived topic:"+topic);
Message msg = new Message();
msg.what = 1;
msg.obj = message.toString();
handler.sendMessage(msg);
}
@Override
public void connectionLost(Throwable cause) {
KLog.d("connectionLost cause = "+cause);
//连接丢失后,一般在这里面进行重连
try{
KLog.d("mqtt重连");
manager.startReconnect();
}catch (Exception e){
KLog.d("Exception = "+ e);
e.printStackTrace();
}
} @Override
public void deliveryComplete(IMqttDeliveryToken token) {
//publish后会执行到这里
KLog.d("deliveryComplete");
}
};
private ScheduledExecutorService scheduler; public static MqttManager getInstance() {
if (manager == null) {
manager = new MqttManager();
}
return manager;
} public void initConnection() {
if (initFirst){
KLog.d("第一次调用initConnection");
try {
clientId = Preferences.getUserAccount() + System.currentTimeMillis();//客户端标识符(本机mac地址+当前时间ms)
userName = Preferences.getUserAccount();//用户名
passWord = Preferences.getUserToken();//密码
topic = userName;
//host为主机名;clientid即连接MQTT的客户端ID,是客户端的唯一标识符;MemoryPersistence设置clientid的保存形式,默认为以内存保存
mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
//MQTT的连接设置
options = new MqttConnectOptions();
//设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(true);
//断开后,是否自动连接
options.setAutomaticReconnect(true);
//设置连接的用户名
options.setUserName(userName);
//设置连接的密码
options.setPassword(passWord.toCharArray());
// 设置超时时间 单位为秒
options.setConnectionTimeout(10);
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*(20)秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options.setKeepAliveInterval(20);
//setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
// options.setWill(topic,"close".getBytes(),2,true);
//设置回调
mqttClient.setCallback(myMqttCallback);
KLog.d("clientId: "+clientId +", userName: "+userName+", passWord: "+passWord+", topic: "+topic);
//设置标识符状态
initFirst = false;
//mqtt第一次连接
manager.startReconnect();
} catch (Exception e) {
KLog.d("initConnection Exception: " + e);
e.printStackTrace();
}
}else {
KLog.d("网络重连后调用initConnection");
manager.startReconnect();
}
} public void startReconnect() { if (NetworkUtils.isConnected()){ if (!mqttClient.isConnected()) {
//重新连接
connect();
KLog.d("mqtt连接结束");
}else {
KLog.d("mqttClient.isConnected");
}
// scheduler = Executors.newSingleThreadScheduledExecutor();
// scheduler.scheduleAtFixedRate(new Runnable() {
// @Override
// public void run() {
//
// if (!mqttClient.isConnected()) {
// connect();
// KLog.d("mqtt连接结束");
// }
// }
// }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
}else {
KLog.d("网络不可用");
// scheduler.shutdown();
} } public void sendMsg(String msg) {
KLog.d("sendMsg");
if (mqttClient != null && mqttClient.isConnected()) {
try {
KLog.d("发送的主题:" + Preferences.getUserAccount());
String topic = Preferences.getUserAccount();
KLog.d(topic);
byte[] msgBytes = msg.getBytes();
KLog.d("0000");
mqttClient.publish(topic, msgBytes, 0, false);
KLog.d("11111111111111111");
} catch (MqttException e) {
KLog.d(e);
}
}
} //发布的主题设为pubTopic = "owh" + Preferences.getUserAccount();
//发布主题(发布主题和订阅主题应设为不同值)
public void publish(String topicName, String payload) {
if (mqttClient != null && mqttClient.isConnected()) {
// 创建和配置一个消息
MqttMessage message = new MqttMessage(payload.getBytes());
message.setPayload(payload.getBytes());
message.setQos(0);
try {
KLog.d("1111");
mqttClient.publish(topicName, message);
KLog.d("2222");
} catch (MqttException e) {
KLog.d("publish : " + e.toString());
}
}
} private void connect() { ThreadPoolManager.getInstance().execute(new Runnable() {
@Override
public void run() {
try {
mqttClient.connect(options);
Message msg = Message.obtain();
msg.what = 2;
handler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what = 3;
handler.sendMessage(msg);
}
}
}); // new Thread(new Runnable() {
//
// @Override
// public void run() {
// try {
// mqttClient.connect(options);
// Message msg = new Message();
// msg.what = 2;
// handler.sendMessage(msg);
// } catch (Exception e) {
// e.printStackTrace();
// Message msg = new Message();
// msg.what = 3;
// handler.sendMessage(msg);
// }
// }
// }).start();
} //断开连接
public static void mqttDisconnect(){
if(mqttClient !=null && mqttClient.isConnected()){
try{
mqttClient.disconnect();
}catch (MqttException e){
KLog.d("mqtt disconnect error");
e.printStackTrace();
}
}
} }

三、注意事项

1、MQTT的客户端id(clientId)须唯一。在此项目中clientId = 本机mac地址 + 当前时间(ms)。

2、一个客户端的一个MQTT连接最好只new一个对象,避免一台设备产生多个客户端账号。

当多个发布(/订阅)的clientId相同时,会发生Mqtt反复重连的现象,无法正常发送或接收消息。

当多个发布(/订阅)的clientId不同时,会造成一台设备多个Mqtt账号同时在线,占用了多余的服务器资源。

3、一个客户端的发布Topic和订阅Topic不应相同。

Android MQTT的发布与订阅的更多相关文章

  1. MQTT介绍(3)java模拟MQTT的发布,订阅

    MQTT目录: MQTT简单介绍 window安装MQTT服务器和client java模拟MQTT的发布,订阅 在此强调一下mqtt的使用场景: 1.不可靠.网络带宽小的网络 2.运行的设备CPU. ...

  2. 转MQTT--Python进行发布、订阅测试

    前言  使用python编写程序进行测试MQTT的发布和订阅功能.首先要安装:pip install paho-mqtt 测试发布(pub)  我的MQTT部署在阿里云的服务器上面,所以我在本机上编写 ...

  3. MQTT 消息 发布 订阅

    当连接向一个mqtt服务器时,clientId必须是唯一的.设置一样,导致client.setCallback总是走到 connectionLost回调.报connection reset.调查一天才 ...

  4. (转)SqlServer 数据库同步的两种方式 (发布、订阅),主从数据库之间的同步

    最近在琢磨主从数据库之间的同步,公司正好也需要,在园子里找了一下,看到这篇博文比较详细,比较简单,本人亲自按步骤来过,现在分享给大家. 在这里要提醒大家的是(为了更好的理解,以下是本人自己理解,如有错 ...

  5. (原)3.2 Zookeeper应用 - 数据的发布与订阅

    本文为原创文章,转载请注明出处,谢谢 数据的发布与订阅 1.应用 服务端监听数据改变,客户端创建/更新节点数据,客户端提供数据,服务端处理 2.原理 客户端监控节点数据改变事件(例如配置信息,下图的c ...

  6. MSSQL复制中的发布与订阅

    准备条件 1.2台服务器 2.WINDOWS SERVER 2008 64bit + 3.SQL SERVER 2008 R2 + 4.MSSQLSERVER服务与MSSQLAGENT服务正常运行中 ...

  7. 知方可补不足~SQL2008中的发布与订阅模式

    回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...

  8. RabbitMQ官方中文入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)

    发布/订阅 在上篇教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式被称为“ ...

  9. 【SQL Sever】实现SQL Sever的发布。订阅。 双机热备

    实现SQL Sever的发布和订阅  最大的好处就是: 可以实现读写分离,增删改操作在主数据库服务器上进行,查询在备份数据库服务器上进行.一方面提高软件执行效率,另一方面也减轻主库压力. 本次实现发布 ...

随机推荐

  1. 解决IOS把数字渲染为电话号码,颜色为蓝色解决方案

    可将telephone=no,则手机号码不被显示为拨号链接<meta name="format-detection" content="telephone=no&q ...

  2. [.net core]9.中间件的具体实现

    查看Startup.cs的configure方法 public void Configure(IApplicationBuilder app, IHostingEnvironment env) { i ...

  3. 087、日志管理之 Docker logs (2019-05-09)

    参考https://www.cnblogs.com/CloudMan6/p/7749304.html   高效的监控和日志管理对保持生产系统只需稳定的运行以及排查问题至关重要.   在微服务架构中,由 ...

  4. js中过滤在输入框中过滤掉特殊表情

    在页面输入text 时,经常会出现某些特殊符号例如:❤

  5. 原型链—— javascript

    目录 js面向对象编程 js原型链 共享方法 原型继承 class继承 js面向对象编程 js面向对象编程不同于 java 的类和对象 JavaScript 不区分类和实例的概念,而是通过原型(pro ...

  6. java 序列化原来如此

    上次面试的时候 ,如何实现java 类的序列化,当时感觉这个问题很简单,我的回答是实现serizlizable 接口就好了,可以实现对象的持久化,看了看书,原来这样: public class Ser ...

  7. Android 关于悬浮窗权限的问题

    正常情况下的处理: dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)以及在清单文件中添加 <use ...

  8. error: (-215) !empty() in function detectMultiScale

    tips: pip install opencv-python or https://www.lfd.uci.edu/~gohlke/pythonlibs/ 原因确实是找不到 opencv 的 xml ...

  9. 【c#】ADO操作Access的mdb数据库只能读不能修改的解决方法

    在使用ACCESS数据库时连接字符串如 string strcon=@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\Access操作\简易 ...

  10. C#文件路径操作总结

    一.获取当前文件的路径 1.   System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName     获取模块的完整路径,包括 ...