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

文章目录

    需求

    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 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式