Android APP 中使用 MQTT 协议进行数据上报

更新日期: 2024-05-16 阅读次数: 1455 字数: 767 分类: Android

需求

Android APP 通过蓝牙读取工业设备上的运行数据,然后通过 MQTT 协议上传到服务器端,再由服务器转发给客户的云平台。

  • 客户端是一个华为鸿蒙系统平板。非纯血鸿蒙版本,还能跑 Android Kotlin 开发 App。
  • 服务器端使用的是开源的 EMQX 的 MQTT broker。

支持 MQTT 的三方库

最终使用的是

https://github.com/hannesa2/paho.mqtt.android

这个是在一个已经废弃的库

https://github.com/eclipse/paho.mqtt.android

的基础上继续维护的一个项目。因为 eclipse 这个库已经不维护了,不支持最新的 Android 版本。

具体原因参考:

  • https://github.com/eclipse/paho.mqtt.android/issues/500
  • https://github.com/eclipse/paho.mqtt.android/issues/493

由于第一个库可用,就没有继续测试 HiveMQ MQTT Client 的方案。从 github 上看,好多开发者用的是 HiveMQ 这个库,而且也支持 EMQX。

EMQX 的官方文档

EMQX 官方有个文章,是介绍关于如何在 Android 上连接 EMQX MQTT 服务的。

https://www.emqx.com/zh/blog/android-connects-mqtt-using-kotlin

但是文章是 2020 年写的,不知道现在还能使用么?我测试了一下,只需要将废弃的 eclipse/paho.mqtt.android 替换成 hannesa2/paho.mqtt.android 即可。

注意:一定要参考这个中文的介绍,这篇文章有个对应的英文版,那个内容不全。

如果继续使用废弃的那个库,会遇到各类异常报错:

java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/content/LocalBroadcastManager

java.lang.SecurityException: Caller com.sunzhongwei.mqtt needs to hold android.permission.SCHEDULE_EXACT_ALARM to set exact alarms.

改不完的问题。

跟文档不同的地方

hannesa2/paho.mqtt.android 这个库文档太少,还是尝试了一下才调试成功。

settings.gradle 中添加仓库:

maven { url 'https://jitpack.io' }

build.gradle 中添加依赖:

implementation 'com.github.hannesa2:paho.mqtt.android:4.2.4'

这里只需要一个依赖,而是那个废弃项目还需要额外的 Android Service 服务依赖。

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。

Dependency 'androidx.work:work-runtime-ktx:2.9.0' requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs. :app is currently compiled against android-33.

需要将 sdk 从 33 升级到 34:

  • compileSdk 34
  • targetSdk 34

其他代码部分,按照文档中的即可,不需要额外的修改。

publish 消息测试

mqttClient.connect(options, null, object : IMqttActionListener {  
    override fun onSuccess(asyncActionToken: IMqttToken?) {  
        Log.d(MQTT_TAG, "Connection success")  
  
        publish("hello/world", "hello gaga", 0)  // 发送消息
    }  
  
    override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {  
        Log.d(MQTT_TAG, "Connection failure")  
    }  
})

在 EMQX 后台就能看到对应的消息了

EMQX 后台消息

心跳测试

从 EMQX 的网页后台看看,建立的 MQTT 连接默认心跳间隔为 60 秒。

将 App 切回系统桌面,或者锁屏。从后台看,连接也是一直保持的,说明后台有个定时任务在自动保持心跳。

只有将 Android 的 Wifi 禁用之后,过一分钟后才会显示 MQTT 连接断开。

默认不会自动重连。需要配置连接参数:

options.isAutomaticReconnect = true

然后就可以自动重试重新连接了。

微信关注我哦 👍

大象工具微信公众号

我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式