Android MQTT的发布与订阅
一、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的发布与订阅的更多相关文章
- MQTT介绍(3)java模拟MQTT的发布,订阅
MQTT目录: MQTT简单介绍 window安装MQTT服务器和client java模拟MQTT的发布,订阅 在此强调一下mqtt的使用场景: 1.不可靠.网络带宽小的网络 2.运行的设备CPU. ...
- 转MQTT--Python进行发布、订阅测试
前言 使用python编写程序进行测试MQTT的发布和订阅功能.首先要安装:pip install paho-mqtt 测试发布(pub) 我的MQTT部署在阿里云的服务器上面,所以我在本机上编写 ...
- MQTT 消息 发布 订阅
当连接向一个mqtt服务器时,clientId必须是唯一的.设置一样,导致client.setCallback总是走到 connectionLost回调.报connection reset.调查一天才 ...
- (转)SqlServer 数据库同步的两种方式 (发布、订阅),主从数据库之间的同步
最近在琢磨主从数据库之间的同步,公司正好也需要,在园子里找了一下,看到这篇博文比较详细,比较简单,本人亲自按步骤来过,现在分享给大家. 在这里要提醒大家的是(为了更好的理解,以下是本人自己理解,如有错 ...
- (原)3.2 Zookeeper应用 - 数据的发布与订阅
本文为原创文章,转载请注明出处,谢谢 数据的发布与订阅 1.应用 服务端监听数据改变,客户端创建/更新节点数据,客户端提供数据,服务端处理 2.原理 客户端监控节点数据改变事件(例如配置信息,下图的c ...
- MSSQL复制中的发布与订阅
准备条件 1.2台服务器 2.WINDOWS SERVER 2008 64bit + 3.SQL SERVER 2008 R2 + 4.MSSQLSERVER服务与MSSQLAGENT服务正常运行中 ...
- 知方可补不足~SQL2008中的发布与订阅模式
回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...
- RabbitMQ官方中文入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)
发布/订阅 在上篇教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式被称为“ ...
- 【SQL Sever】实现SQL Sever的发布。订阅。 双机热备
实现SQL Sever的发布和订阅 最大的好处就是: 可以实现读写分离,增删改操作在主数据库服务器上进行,查询在备份数据库服务器上进行.一方面提高软件执行效率,另一方面也减轻主库压力. 本次实现发布 ...
随机推荐
- [WPF]使用CheckAccess检测是否在控件的ui线程上执行
private void Parallel(object sender, RoutedEventArgs e) { Task.Run(() => ChangeColour(Brushes.Red ...
- sql server 函数详解(3)数据类型转换函数和文本图像函数
数据类型转换函数 文本和图像函数 --在同时处理不同数据类型的值时,SQL Server一般会自动进行隐士类型转换.对于数据类型相近的值是有效的,比如int和float,但是对于其它数据类型,例如整型 ...
- Scala学习笔记(3)
数组 ----------------------------------- 0.若长度固定则用Array,若长度可能变化则使用ArrayBuffer 1.提供初始值的时候不要使用new. 2.用() ...
- poj 1664 放苹果(dfs)
放苹果 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 30284 Accepted: 19098 Description ...
- oracle数据库应用总结
1------->>>>>>>>>>>>>>>>>>>>>>> ...
- dataTable 、dataView、Dataset 区别
dataTable .dataView.Dataset 区别的经典回答 1.DataView是DataTable的表示,DataTable表里的记录是没有顺序的,但显示可以有不同顺序(DataVIew ...
- Codeforces 899 1-N两非空集合最小差 末尾最多9对数计算 pair/链表加优先队列最少次数清空
A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...
- web框架-(五)Ajax
Ajax即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,AJAX = 异步 JavaScript和X ...
- 清北学堂提高组突破营游记day6
还有一天就结束了..QWQ 好快啊. 昨天没讲完的博弈论DP: 一个标准的博弈论dp,一般问的是是否先手赢. 博弈论最关键的问题:dp过程. 对于一个问题,一定有很多状态,每个状态可以转移到其他的一些 ...
- ASP.NET 中 取得 Repeater 里的checkbox值
前言:这两天在维护ASP.NET的项目,需要做一个checkbox来选择数据进行导出,下面提供两种解决思路 1.ASP:CheckBox asp:CheckBox自带控件,没有Value值 <a ...