Android 使用 Kotlin 连接 MQTT_android kotlin mqtt-程序员宅基地

技术标签: mqtt  android  kotlin  

MQTT 是一种轻量级的、灵活的物联网消息交换和数据传递协议,致力于为 IoT 开发人员实现灵活性与硬件/网络资源的平衡。

Kotlin 是一门由 JetBrains 公司开发的编程语言,Kotlin 是基于 JVM 的,所以开发者可以很方便地用它来进行 Android 开发,并且支持 Kotlin 和 Java 的混合编写。而早在 2017 年,Google 就宣布 Kotlin 成为官方开发语言。

本文主要介绍使用 Kotlin 语言在 Android 平台上使用 MQTT。

新建 Kotlin 项目

打开 Android Studio 新建一个项目,选择语言为 Kotlin,Android Studio 会自动创建 Kotlin 相关配置。若要配置现有项目,则可以参考 将 Kotlin 添加到现有应用

添加依赖

打开项目的 build.gradle,添加 Eclipse Paho Java ClientEclipse Paho Android Service 依赖到 dependencies 部分。

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.4'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' 
}

配置 AndroidManifest.xml

Android Service 是 Eclipse 开发的基于 Android 平台的一个后台服务,我们需要将它注册到AndroidManifest.xml 文件,同时,我们需要注册权限。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
   ...
   <service android:name="org.eclipse.paho.android.service.MqttService" />
</application>

创建 MQTT 客户端

private lateinit var mqttClient: MqttAndroidClient
// TAG
companion object {
    
    const val TAG = "AndroidMqttClient"
}

连接 MQTT 服务器

本文将使用 EMQ X MQTT Cloud 运营和维护的免费公共 MQTT 服务器, EMQ X Cloud 是由 EMQ 推出的安全的 MQTT 物联网云服务平台,它提供一站式运维代管、独有隔离环境的 MQTT 5.0 接入服务。

  • Broker: broker.emqx.io
  • TCP Port: 1883
  • Websocket Port: 8083
fun connect(context: Context) {
    
        val serverURI = "tcp://broker.emqx.io:1883"
        mqttClient = MqttAndroidClient(context, serverURI, "kotlin_client")
        mqttClient.setCallback(object : MqttCallback {
    
            override fun messageArrived(topic: String?, message: MqttMessage?) {
    
                Log.d(TAG, "Receive message: ${
      message.toString()} from topic: $topic")
            }

            override fun connectionLost(cause: Throwable?) {
    
                Log.d(TAG, "Connection lost ${
      cause.toString()}")
            }

            override fun deliveryComplete(token: IMqttDeliveryToken?) {
    

            }
        })
        val options = MqttConnectOptions()
        try {
    
            mqttClient.connect(options, null, object : IMqttActionListener {
    
                override fun onSuccess(asyncActionToken: IMqttToken?) {
    
                    Log.d(TAG, "Connection success")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
    
                    Log.d(TAG, "Connection failure")
                }
            })
        } catch (e: MqttException) {
    
            e.printStackTrace()
        }

    }

其中,MqttCallback 接口包含 3 个方法:

  1. messageArrived:收到 broker 新消息
  2. connectionLost:与 broker 连接丢失
  3. deliveryComplete:消息到 broker 传递完成

MqttConnectOptions 用于配置连接设置,包含用户名密码,超时配置等,具体可以查看其方法。

创建 MQTT 订阅

订阅 topic

fun subscribe(topic: String, qos: Int = 1) {
    
        try {
    
            mqttClient.subscribe(topic, qos, null, object : IMqttActionListener {
    
                override fun onSuccess(asyncActionToken: IMqttToken?) {
    
                    Log.d(TAG, "Subscribed to $topic")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
    
                    Log.d(TAG, "Failed to subscribe $topic")
                }
            })
        } catch (e: MqttException) {
    
            e.printStackTrace()
        }
    }

取消订阅

取消订阅 topic

fun unsubscribe(topic: String) {
    
        try {
    
            mqttClient.unsubscribe(topic, null, object : IMqttActionListener {
    
                override fun onSuccess(asyncActionToken: IMqttToken?) {
    
                    Log.d(TAG, "Unsubscribed to $topic")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
    
                    Log.d(TAG, "Failed to unsubscribe $topic")
                }
            })
        } catch (e: MqttException) {
    
            e.printStackTrace()
        }
    }

发布消息

fun publish(topic: String, msg: String, qos: Int = 1, retained: Boolean = false) {
    
        try {
    
            val message = MqttMessage()
            message.payload = msg.toByteArray()
            message.qos = qos
            message.isRetained = retained
            mqttClient.publish(topic, message, null, object : IMqttActionListener {
    
                override fun onSuccess(asyncActionToken: IMqttToken?) {
    
                    Log.d(TAG, "$msg published to $topic")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
    
                    Log.d(TAG, "Failed to publish $msg to $topic")
                }
            })
        } catch (e: MqttException) {
    
            e.printStackTrace()
        }
    }

断开 MQTT 连接

fun disconnect() {
    
        try {
    
            mqttClient.disconnect(null, object : IMqttActionListener {
    
                override fun onSuccess(asyncActionToken: IMqttToken?) {
    
                    Log.d(TAG, "Disconnected")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
    
                    Log.d(TAG, "Failed to disconnect")
                }
            })
        } catch (e: MqttException) {
    
            e.printStackTrace()
        }
    }

测试

首先将 Android 客户端连接到 MQTT 服务器,然后订阅 topic: a/b,可以看到连接成功和成功订阅的日志

在这里插入图片描述

然后我们使用 MQTT 5.0 客户端工具 - MQTT X 进行测试,发布消息到 topic: a/b,客户端可以看到收到消息的日志

在这里插入图片描述
在这里插入图片描述

我们在客户端发布消息到 topic: a/b ,因为我们订阅了该 topic,同时也会收到消息,最后我们断开客户端与 MQTT 服务器的连接,日志如下:

在这里插入图片描述

至此,我们已经完成了Android 上 MQTT 客户端的构建,实现了客户端与 MQTT 服务器的连接、主题订阅、收发消息等功能。

MQTT 可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

而 Kotlin 也是 Google 官方主推的一门语言,结合 MQTT 协议及 MQTT 云服务,我们可以开发更多有趣的应用。

版权声明: 本文为 EMQ 原创,转载请注明出处。

原文链接:https://www.emqx.io/cn/blog/android-connects-mqtt-using-kotlin

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/emqx_broker/article/details/106639723

智能推荐

关于JAVA的CLASSPATH_java classpath默认-程序员宅基地

文章浏览阅读6.6k次。使用java命令运行class文件提示“错误:找不到或无法加载主类“?是否修改了CLASSPATH环境变量!?CLASSPATH有何作用?_java classpath默认

C++--什么是内存泄漏,和内存溢出的区别,常见引起引起内存泄漏的原因,及解决办法-程序员宅基地

文章浏览阅读1.0k次。内存泄露和内存溢出的区别:内存溢出 : out of memory 指程序在申请内存时,没有足够的内存空间供其使用,出现out fo memory 比如申请一个int,但给它存了long才能存下的数那就是内存溢出内存泄露 : memory leak 指程序在申请内存后,无法释放已经申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后的结果很严重,无论多少内存,迟早会被占光即为:不再会被使用的对象的内存不能被回收,就是内存泄露C++没有垃圾回收机制,我们需要关注那些类型的内存泄漏?堆

Fortify扫描漏洞解决方案_fority漏洞扫描开发规范-程序员宅基地

文章浏览阅读8.3k次。Fortify扫描漏洞解决方案:Log Forging漏洞:1.数据从一个不可信赖的数据源进入应用程序。在这种情况下,数据经由getParameter()到后台。2. 数据写入到应用程序或系统日志文件中。这种情况下,数据通过info()记录下来。为了便于以后的审阅、统计数据收集或调试,应用程序通常使用日志文件来储存事件或事务的历史记录。根据应用程序自身的特性,审阅日志文件可在必要..._fority漏洞扫描开发规范

detach,矩阵运算等知识_.detach()-程序员宅基地

文章浏览阅读3k次,点赞2次,收藏5次。pytorch中梯度detach, 矩阵的转置, 求和等_.detach()

川土微电子 | CA-IS3050U隔离式CAN收发器_can隔离收发器原理图-程序员宅基地

文章浏览阅读2.1k次。Pin2pin替代ISO1050CA-IS3050U是一款隔离式控制区域网络(CAN)物理层收发器,符合ISO11898-2标准的技术规范。此器件采用片上二氧化硅(SiO2)电容作为隔离层,在CAN协议控制器和物理层总线之间创建一个完全隔离的接口,与隔离电源一起使用,可隔绝噪声和干扰并防止损坏敏感电路。CA-IS3050U可为CAN协议控制器和物理层总线分别提供差分接收和差分发射能力,信号传输速率最高可达1Mbps。该器件具有限流、过压和接地损耗保护(–40V至40V)以及热关断功能,可防止输出短路_can隔离收发器原理图

如何做研究?_如何做研究相关文章-程序员宅基地

文章浏览阅读662次。【转贴】麻省理工教授箴言:怎样做研究生!麻省理工学院人工智能实验室AI Working Paper 316 1988年10月来自MIT人工智能实验室:如何做研究?作者:人工智能实验室全体研究生编辑:David Chapman版本:1.3时间:1988年9月译者:柳泉波 北京师范大学信息学院2000级博士生摘要 本文的主旨是解释如何做研究。我们提供的这些建议,对做研究本身(阅读、写作和程序设计)_如何做研究相关文章

随便推点

情侣间的计算机游戏,适合情侣玩的双人单机游戏-程序员宅基地

文章浏览阅读9.1k次。对于情侣和夫妻来说,一起玩一款游戏,是放松休闲,沟通情感的好方式。然而当要选择一款游戏时,你和他/她是否也有以下烦恼:(1) 兴趣不一,自己喜欢的游戏,他/她不喜欢,或者他/她觉得太复杂。(2) 时间精力不足,你们并不打算花费大量的时间在升级、打怪上,只想放松地度过一个周末,或者一个晚上。(3) 手头目前只有一台电脑,或者一个手柄。别着急,先考虑下你和他/她的共同点,本篇将会为你推荐最适合你们的单..._情侣游戏电脑

Hadoop元数据存储、加载、恢复_hadoop元数据存储方式-程序员宅基地

文章浏览阅读5k次,点赞2次,收藏11次。1. 元数据加载 为了保证交互速度,HDFS文件系统的metadata是被load到namenode机器的内存中的。并会将内存中的这些数据保存到磁盘进行持久化存储,但对块的位置信息不进行持久化存储,在DataNode向namenode进行注册时动态加载。当NameNode启动时,它从硬盘中读取Editlog和FsImage。将所有Editlog中的事务作用在内存中的FsImage上,以恢..._hadoop元数据存储方式

python爬取m3u8连接的视频-程序员宅基地

文章浏览阅读1.1w次。要求:输入m3u8所在url,且ts视频与其在同一路径下#!/usr/bin/env/python#_*_coding:utf-8_*_#Data:17-10-08#Auther:苏莫#Link:http://blog.csdn.net/lingluofengzang#PythonVersion:python2.7#filename:download_movie.pyimport os

Servlet中url-pattern的匹配规则_为servlet配置一个url-pattern时,可以同时使用路径匹配和扩展名匹配,例如<url-p-程序员宅基地

文章浏览阅读592次。首先需要明确几容易混淆的规则:(1)servlet容器中的匹配规则既不是简单的通配,也不是正则表达式,而是特定的规则。所以不要用通配符或者正则表达式的匹配规则来看待servlet的url-pattern。(2)Servlet 2.5开始,一个servlet可以使用多个url-pattern规则,<servlet-mapping>标签声明了与该servlet相应的匹配规则,每个&..._为servlet配置一个url-pattern时,可以同时使用路径匹配和扩展名匹配,例如

电商十三、pinyougou02.sql的内容④-程序员宅基地

文章浏览阅读2.1k次。<a target=\"blank\" href=\"http://sale.jd.com/act/ZovfiDKYagBQJ.html\">更多推荐请点击!</a>','489.00',NULL,99999,NULL,'http://img12.360buyimg.com/n1/s450x450_jfs/t3034/299/2060854617/119711/577...

让你的CSocket支持超时(TimeOut)_ctimeoutsocket-程序员宅基地

文章浏览阅读3.5k次。1、从CSocket派生一个类CTimeOutSocket2、 修改XX.h文件,该写虚函数“ConnectHelper”class CTimeOutSocket : public CSocket...{// Attributespublic: BOOL m_Kill;// Operationspublic: CTimeOutSocket(); virtual ~C_ctimeoutsocket

推荐文章

热门文章

相关标签