Android MQTT开发之 Hivemq MQTT Client
使用一个开源库:hivemq-mqtt-client,这是Java生态的一个MQTT客户端框架,需要Java 8,Android上使用的话问题不大,需要一些额外的配置,下面列出了相关的配置,尤其是 packagingOptions,不然编译不过,因为框架使用了Java8新增的语言特性,所以 minSdk 设置为24,即Android7.0,如果要兼容Android7.0以下系统,可以参考这份详细文档配置一下语法脱糖的SDK: Installation on Android
android {defaultConfig {minSdk 24}compileOptions {sourceCompatibility JavaVersion.VERSION_8targetCompatibility JavaVersion.VERSION_8}kotlinOptions {jvmTarget = '8'}packagingOptions {resources {excludes += ['META-INF/INDEX.LIST', 'META-INF/io.netty.versions.properties']}}
}dependencies {implementation 'com.hivemq:hivemq-mqtt-client:1.3.3'
}
刚开始在自动连接这块花了好多时间,最后才发现是设置用户名和密码的地方不对,一定要在设置自动重连(初始化Client)的地方设置,而不是连接的时候!下面是一个简单的使用示例代码
MqttManager.kt
import android.util.Log
import com.hivemq.client.mqtt.datatypes.MqttQos
import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext
import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener
import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext
import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client
import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAckReasonCode
import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish
import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck
import java.util.UUID
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors
import java.util.function.Consumeropen class MqttListener {open fun onConnected() {}open fun onDisconnected() {}open fun onSubscribed(vararg topics: String) {}open fun onReceiveMessage(topic: String, data: ByteArray) {}open fun onSendMessage(topic: String, data: ByteArray) {}
}/*
文档
https://github.com/hivemq/hivemq-mqtt-client
https://hivemq.github.io/hivemq-mqtt-client/docs/installation/android/
*/
class MqttManager private constructor() : MqttClientConnectedListener, MqttClientDisconnectedListener {private val executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()) {Thread(it).apply { isDaemon = true }}private val mqttAsynClient: Mqtt5AsyncClient = Mqtt5Client.builder().identifier(UUID.randomUUID().toString()).serverHost(SERVER_HOST).serverPort(SERVER_PORT).addConnectedListener(this).addDisconnectedListener(this).simpleAuth()//在初始化的时候设置账号密码,重连才能成功.username(USERNAME).password(PASSWORD.toByteArray()).applySimpleAuth().automaticReconnectWithDefaultConfig()//自动重连.buildAsync()private val listeners = mutableListOf<MqttListener>()private val subTopicsget() = arrayOf("top1", "top2", "top3")fun addMqttListener(listener: MqttListener) {if (!listeners.contains(listener)) {listeners.add(listener)}}fun removeMqttListener(listener: MqttListener) {listeners.remove(listener)}override fun onConnected(context: MqttClientConnectedContext) {Log.i(TAG, "onConnected()")for (l in listeners) {l.onConnected()}subscribeAll()}private fun subscribeAll() {CompletableFuture.supplyAsync({val futures = subTopics.map(::subscribe).map {it.thenCompose {CompletableFuture.supplyAsync({val success = !it.reasonString.isPresentif (success) {Log.i(TAG, "subscribe success")} else {Log.e(TAG, "subscribe() - reasonCodes=[${it.reasonCodes.joinToString(", ")}]" +", reasonString=${it.reasonString}")}success}, executor)}}.toTypedArray()CompletableFuture.allOf(*futures).join()//等待所有订阅结果if(futures.all { it.get() }) {Log.i(TAG, "subscribeAll() - 全部订阅成功")}for (l in listeners) {l.onSubscribed(*subTopics)}}, executor)}override fun onDisconnected(context: MqttClientDisconnectedContext) {Log.e(TAG, "onDisconnected() - isConnected=${mqttAsynClient.state.isConnected}" +", isConnectedOrReconnect=${mqttAsynClient.state.isConnectedOrReconnect}")for (l in listeners) {l.onDisconnected()}}fun connect() {mqttAsynClient.connectWith().cleanStart(true).keepAlive(30).send().thenAccept {if (it.reasonCode == Mqtt5ConnAckReasonCode.SUCCESS) {Log.i(TAG, "connect() - SUCCESS")} else {Log.e(TAG, "connect() - ${it.reasonCode}")}}}fun disconnect() {mqttAsynClient.disconnect().thenAccept {Log.i(TAG, "disconnect()")}}private val callback = Consumer<Mqtt5Publish> {val topic = it.topic.toString()val data = it.payloadAsBytesprocessReceivedMessage(topic, data)}private fun processReceivedMessage(topic: String, data: ByteArray) {//处理接收的数据for (l in listeners) {l.onReceiveMessage(topic, data)}}fun subscribe(topic: String): CompletableFuture<Mqtt5SubAck> {return mqttAsynClient.subscribeWith().topicFilter(topic).noLocal(true)// we do not want to receive our own message.qos(MqttQos.AT_MOST_ONCE).callback(callback).executor(executor).send()}fun unsubscribe(topic: String) {mqttAsynClient.unsubscribeWith().topicFilter(topic).send().thenAccept {Log.i(TAG, "unsubscribe() - $it")}}/*** 发送数据*/fun publish(topic: String, payload: ByteArray) {mqttAsynClient.publishWith().topic(topic).qos(MqttQos.AT_MOST_ONCE).payload(payload).send().thenAccept { mqtt5PublishResult ->mqtt5PublishResult.publish.let { mqtt5Publish ->
// val topic = mqtt5Publish.topic.toString()val data = mqtt5Publish.payloadAsBytesfor (l in listeners) {l.onSendMessage(topic, data)}}}}companion object {private const val TAG = "MqttManager"private const val SERVER_HOST = "example.com"private const val SERVER_PORT = 1883 // 1883即TCP协议,host不要再加上"tcp://",否则连不成功private const val USERNAME = "admin"private const val PASSWORD = "123456"val instance = MqttManager()}
}
相关文章:
Android MQTT开发之 Hivemq MQTT Client
使用一个开源库:hivemq-mqtt-client,这是Java生态的一个MQTT客户端框架,需要Java 8,Android上使用的话问题不大,需要一些额外的配置,下面列出了相关的配置,尤其是 packagingOptions,…...
【Maven教程】(十一):使用 Maven 构建 Web应用 —— 使用 jetty-maven-plugin 进行测试、使用 Cargo 实现自动化部署~
Maven 使用 Maven 构建 Web应用 1️⃣ Web 项目的目录结构2️⃣ account-service2.1 account-service的 POM2.2 account-service 的主代码 3️⃣ account-web3.1 account-web 的POM3.2 account-web 的主代码 4️⃣ 使用 jetty-maven-plugin 进行测试5️⃣ 使用 Cargo 实现自动…...
番外 2 : LoadRunner 的安装以及配置
LoadRunner 的安装以及配置教程 一 . 配置 IE 浏览器二 . 安装 LoadRunner 工具三 . 修改默认浏览器的配置四 . 设置 LoadRunner 能够获取本地资源 Hello , 大家好 , 又给大家带来新的专栏喽 ~ 这个专栏是专门为零基础小白从 0 到 1 了解软件测试基础理论设计的 , 虽然还不足以…...
win10正确配置tensorRT环境
目的 使用tensorRT进行网络模型部署,加快推理速度 方法 安装tensorRT的过程需要对各种组件的版本进行匹配 前置安装套件有: 1、CUDA 2、cuDNN 3、pyCUDA 4、tensorflow或pytorch 主要记录tensorRT安装: tensorRT安装配置查询 步骤: 1、去tensorRT官网…...
C++初阶-模板初阶
模板初阶 一、泛型编程二、函数模板2.1函数模板概念2.2函数模板格式2.3函数模板的原理2.4函数模板的原理2.5模板参数的匹配原则 三、类模板3.1类模板的定义格式3.2类模板的实例化 一、泛型编程 如何实现一个通用的交换函数呢? void Swap(int& left, int& …...
基于Python实现汽车销售数据可视化【500010086】
导入模块 import numpy as np import pandas as pd import plotly.graph_objects as go import plotly.express as px获取数据 df1 pd.read_excel(r"./data/中国汽车总体销量.xlsx") print(df1.head(5))df1.info()df1[年份] df1[时间].dt.year df1[月份] df1[时…...
dist.init_process_group() 卡住超时导致报错
在跑模型是遇到一个问题: import torch.distributed as dist dist.init_process_group(backend"nccl", init_methodtcp://localhost:%d % tcp_port, ranklocal_rank, world_sizenum_gpus)程序卡在这一步一动不动。. 解决办法一: 我看网上有人…...
RESTFul API:真是让人又爱又恨
RESTFul API是一种广泛使用的Web服务设计风格,它以资源为中心,通过HTTP方法来操作这些资源。然而,尽管RESTFul架构风格在许多情况下都非常有用,但在实际应用中,我们也发现了一些不足之处。本文将详细阐述这些问题&…...
【洛谷 P1478】陶陶摘苹果(升级版)题解(多重集合+贪心算法)
陶陶摘苹果(升级版) 题目描述 又是一年秋季时,陶陶家的苹果树结了 n n n 个果子。陶陶又跑去摘苹果,这次他有一个 a a a 公分的椅子。当他手够不着时,他会站到椅子上再试试。 这次与 NOIp2005 普及组第一题不同的…...
使用WebSocket实现网页聊天室
一、引言 1. 问题引入 Hypertext Transfer Protocol (HTTP) 协议 一种无状态的、应用层的、以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动. 因为http 通信只能由客户端发起,服务器返回查询结果…...
《如何控制 LLM 的输出格式和解析其输出结果?》
内容来源:dotey 《如何控制 LLM 的输出格式和解析其输出结果?》 https://baoyu.io/blog/prompt-engineering/how-to-parse-the-output-from-llm 现在很多人对于如何使用像 ChatGPT 这样的 LLM 已经比较有经验了,可以使用各种不同的 Prompt …...
《网络协议》07. 其他协议
title: 《网络协议》07. 其他协议 date: 2022-10-07 18:24:02 updated: 2023-11-15 08:00:52 categories: 学习记录:网络协议 excerpt: IPv6、WebSocket、WebService(SOAP,WSDL)、HTTPDNS、FTP、邮件(SMTP,…...
高压放大器设计要求有哪些内容
设计高压放大器时,需要考虑一系列要求以确保其性能和可靠性。以下是设计高压放大器时的一些重要要求。 输入输出电压范围:高压放大器应具备足够的输入和输出电压范围,以适应特定应用的需求。这包括设计合适的电源供应和电路配置,以…...
1700亿烧光,利润暴跌78%!外媒:中芯国际不是麒麟9000S的代工厂
作为芯片代工领域的领导者,台积电在全球半导体市场上占据着重要的地位。然而,由于美国对华为的制裁,台积电关闭了对华为麒麟芯片的代工,这也引发了外界对于芯片代工模式的讨论。与此同时,中芯国际作为大陆规模最大、技…...
简单理解路由重分发(用两路由器来理解)
相关命令: default-information originate //*重分发默认路由 redistribute rip subnets //*重分发rip redistribute ospf 1 metric 3 //*重分发ospf(其中:1是ospf进程id 3是跳数) redistribute sta…...
什么是等保测评?
随着近几年随着网络技术的发展,互联网应用的普及和丰富,互联网安全问题也日益严重,利用信息技术进行的高科技犯罪事件呈现增长态势。从2004年度CNCERT的信息网络安全工作报告中我们看到,信息网络安全事故在逐年上升,20…...
21、Flink 的table API与DataStream API 集成(1)- 介绍及入门示例、集成说明
Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…...
(免费领源码)Java#SpringBoot#mysql高校实验室资产管理系统85189-计算机毕业设计项目选题推荐
摘 要 随着计算机技术的发展,特别是计算机网络技术与数据库技术的发展,使人们的生活与工作方式发生了很大的改观。本课题研究的高校实验室资产管理系统,主要功能模块包括后台首页,轮播图,公告管理,资源管理…...
高效能人士的七个习惯
今天小编给大家推荐最近读的一本书,史蒂芬柯维的《高效能人士的七个习惯》,分别是积极主动、以始为终、要事第一、双赢思维、知己解彼、综合高效及不断更新。 一、个人领域:从依赖到独立 习惯一:积极主动——个人愿景的原则付诸行…...
【前端】使用json-server报错
当我们使用json-server模仿后端接口时需要运行json-server --watch index.json这个命令生成增删改查接口但是可能会报这个错误,如图 这时我们运行 npm i json-server -g命令即可,然后再重新运行json-server --watch index.json就行了...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
