# iot_app_demo **Repository Path**: nnddkj/iot_app_demo ## Basic Information - **Project Name**: iot_app_demo - **Description**: 基于okhttp最新版本进行封装一个Library库,实现socket、websocket、mqtt物联网功能封装和测试工具软件 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-14 - **Last Updated**: 2026-08-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # IotLibrary 使用说明文档 > 物联网通信功能封装库(Android Library),基于 **OkHttp 最新稳定版 5.3.0** 封装 > 独立实现 **TCP / UDP / WebSocket / MQTT** 四大通信模块,各模块互不影响。 > 支持 **Java** 与 **Kotlin** 调用,支持 **普通项目** 与 **MVVM 架构** 项目使用。 - 库版本:1.0.0 - 兼容范围:**Android 5.0 (API 21) ~ Android 17 (API 37)** - 开发者:宁工 联系电话:17776688224 在找工作,有内推最好了 --- ## 目录 1. [库结构说明](#1-库结构说明) 2. [快速开始(引入库)](#2-快速开始引入库) 3. [初始化](#3-初始化) 4. [TCP 客户端使用](#4-tcp-客户端使用) 5. [TCP 服务端(硬件调试工具)](#5-tcp-服务端硬件调试工具) 6. [UDP 客户端使用](#6-udp-客户端使用) 7. [WebSocket 客户端使用](#7-websocket-客户端使用) 8. [WebSocket 服务端(硬件调试工具)](#8-websocket-服务端硬件调试工具) 9. [MQTT 客户端使用](#9-mqtt-客户端使用) 10. [MVVM 架构中使用](#10-mvvm-架构中使用) 11. [通用工具类使用](#11-通用工具类使用) 12. [权限与兼容性说明](#12-权限与兼容性说明) 13. [测试工具 App 使用说明](#13-测试工具-app-使用说明) 14. [常见问题 FAQ](#14-常见问题-faq) --- ## 1. 库结构说明 ``` iotlibrary/src/main/java/com/nyw/iotlibrary/ ├── IotLibrary.kt # 库门面入口:初始化 + 统一创建各模块对象 ├── core/ # 公共基础 │ ├── IotConfig.kt # 全局配置(日志开关、回调线程) │ ├── IotLog.kt # 统一日志 │ ├── IotExecutor.kt # 线程池 + 主线程分发 │ ├── IotConstants.kt # 常量 / 状态枚举 │ └── IotUtils.kt # HEX 转换等工具 ├── socket/ # TCP 模块(独立,socket 即 TCP 实现) │ ├── SocketClient.kt # TCP 客户端(createSocketClient / createTcpClient) │ ├── SocketConfig.kt # TCP 客户端配置(Builder) │ ├── SocketListener.kt # TCP 客户端回调 │ └── SocketServer.kt # TCP 服务端(含配置与回调) ├── udp/ # UDP 模块(独立) │ ├── UdpClient.kt # UDP 客户端(单播/广播/组播) │ ├── UdpConfig.kt # UDP 配置(Builder) │ └── UdpListener.kt # UDP 回调 ├── websocket/ # WebSocket 模块(独立) │ ├── WebSocketClient.kt # WebSocket 客户端(基于 OkHttp 5.3.0) │ ├── WebSocketConfig.kt # WebSocket 客户端配置(Builder) │ ├── WebSocketListener.kt # WebSocket 客户端回调 │ └── WebSocketServer.kt # WebSocket 服务端(含配置与回调) ├── mqtt/ # MQTT 模块(独立) │ ├── MqttClient.kt # MQTT 客户端(基于 Eclipse Paho) │ ├── MqttConfig.kt # MQTT 配置(Builder) │ └── MqttListener.kt # MQTT 回调 └── mvvm/ └── IotViewModel.kt # MVVM 基类(自动管理/释放连接) ``` **设计原则:** - 各模块**完全独立**:TCP / UDP / WebSocket / MQTT 可单独创建、单独配置、单独使用,互不影响; - 配置对外暴露:所有配置项均通过 `Builder` 链式设置; - Java/Kotlin 双友好:配置使用 Builder 模式,回调使用接口(Java 匿名内部类 / Kotlin object 均可); - 回调默认在主线程执行,UI 可直接更新(可通过全局配置关闭)。 > 说明:TCP 客户端由 `socket` 模块提供,可通过门面 `createTcpClient`(等价于 `createSocketClient`)创建; > UDP 由独立 `udp` 模块提供,可通过门面 `createUdpClient` 创建。 --- ## 2. 快速开始(引入库) ### 方式一:工程模块引用(当前项目方式) 在 `settings.gradle.kts` 中注册模块: ```kotlin include(":app") include(":iotlibrary") ``` 在 App 的 `build.gradle.kts` 中添加依赖: ```kotlin dependencies { implementation(project(":iotlibrary")) } ``` ### 方式二:AAR 引用(独立发布时) 将 `iotlibrary` 打包产出的 `iotlibrary-release.aar` 放入 App 的 `libs` 目录: ```kotlin dependencies { implementation(files("libs/iotlibrary-release.aar")) } ``` ### 方式三:Maven 仓库引用(发布到私服后) ```kotlin dependencies { implementation("com.nyw:iotlibrary:1.0.0") } ``` > 库内部依赖:`okhttp:5.3.0`、`org.eclipse.paho.client.mqttv3:1.2.5`、`lifecycle-viewmodel:2.8.7`(已随 AAR 传递)。 --- ## 3. 初始化 在 `Application.onCreate()` 中调用一次即可(可选): ```kotlin // Kotlin IotLibrary.init(debug = true, callbackOnMainThread = true) ``` ```java // Java IotLibrary.init(true, true); ``` | 参数 | 说明 | |---|---| | `debug` | 是否输出调试日志(生产环境建议 false) | | `callbackOnMainThread` | 回调是否统一分发到主线程(UI 项目建议 true) | > 不调用 init 也可以正常使用,使用默认配置(debug=false,主线程回调)。 --- ## 4. TCP 客户端使用 > TCP 客户端由 `socket` 模块提供。门面方法 `createTcpClient(...)` 与 `createSocketClient(...)` 完全等价,可按语义偏好选择。 ### Kotlin 用法 ```kotlin // 1. 构建配置 val config = SocketConfig.Builder("192.168.1.100", 8080) .connectTimeout(10_000) // 连接超时 10 秒 .autoReconnect(true) // 自动重连 .reconnectInterval(3_000) // 每 3 秒重连一次 .enableHeartbeat(true) // 开启心跳 .heartbeatInterval(5_000) // 心跳间隔 5 秒 .heartbeatData(byteArrayOf(0x01)) .maxReconnectTimes(0) // 0 表示无限重连 .build() // 2. 创建客户端 val client = IotLibrary.createSocketClient(config, object : SocketListener { override fun onConnected(address: String) { /* 连接成功 */ } override fun onReceive(bytes: ByteArray) { /* 收到字节 */ } override fun onReceiveText(text: String) { /* 收到文本 */ } override fun onDisconnected(reason: DisconnectReason, message: String) { /* 断开 */ } override fun onReconnecting(times: Int) { /* 重连中 */ } }) // 3. 使用 client.connect() client.sendText("AT+STATUS\r\n") client.send(byteArrayOf(0x01, 0x02)) client.disconnect() ``` ### Java 用法 ```java SocketConfig config = new SocketConfig.Builder("192.168.1.100", 8080) .autoReconnect(true) .build(); SocketClient client = IotLibrary.createSocketClient(config, new SocketListener() { @Override public void onConnected(String address) { } @Override public void onReceiveText(String text) { } }); client.connect(); client.sendText("hello"); client.disconnect(); ``` ### SocketConfig 配置项 | 配置项 | 说明 | 默认值 | |---|---|---| | `host` / `port` | 服务器地址 / 端口(必填) | - | | `connectTimeout` | 连接超时(毫秒) | 10000 | | `readTimeout` | 读超时(毫秒,0=不设置) | 0 | | `writeTimeout` | 写超时(毫秒,0=不设置) | 0 | | `enableHeartbeat` | 是否发送心跳 | false | | `heartbeatInterval` | 心跳间隔(毫秒) | 5000 | | `heartbeatData` | 心跳数据 | 0x01 | | `autoReconnect` | 自动重连 | true | | `reconnectInterval` | 重连间隔(毫秒) | 3000 | | `maxReconnectTimes` | 最大重连次数(0=无限) | 0 | | `charset` | 文本字符集 | UTF-8 | | `tcpNoDelay` | TCP_NODELAY 小包低延迟 | true | | `bufferSize` | 接收缓冲区 | 4096 | --- ## 5. TCP 服务端(硬件调试工具) > 场景:手机开启 TCP 服务端,硬件设备(单片机/网关等)作为 TCP 客户端主动连接。 ```kotlin // Kotlin val server = IotLibrary.createSocketServer( SocketServerConfig(port = 8080), object : SocketServerListener { override fun onStarted(port: Int, ip: String) { } // ip 为手机局域网地址 override fun onClientConnected(clientId: String, address: String) { } override fun onReceiveTextFromClient(clientId: String, address: String, text: String) { } override fun onClientDisconnected(clientId: String, address: String) { } } ) server.start() // 启动 server.broadcastText("hello") // 广播 server.sendTextToClient("C1", "hi") // 指定客户端发送 server.getClientIds() // 客户端列表 server.stop() // 停止 ``` ### Java 用法 ```java SocketServer server = IotLibrary.createSocketServer( new SocketServerConfig(8080), new SocketServerListener() { @Override public void onStarted(int port, String ip) { } @Override public void onReceiveTextFromClient(String clientId, String address, String text) { } }); server.start(); server.broadcastText("hello"); server.stop(); ``` ### SocketServerConfig 配置项 | 配置项 | 说明 | 默认值 | |---|---|---| | `port` | 监听端口(必填) | - | | `charset` | 文本字符集 | UTF-8 | | `bufferSize` | 接收缓冲区大小 | 4096 | > 服务端其他方法:`sendTextToClient(clientId, text)`、`sendToClient(clientId, bytes)`、`getClientIds()`、`stop()`。 --- ## 6. UDP 客户端使用 UDP 为**无连接**传输协议,面向数据报,支持**单播 / 广播 / 组播**,适合设备发现、状态上报等场景。 Library 的 `udp` 模块独立封装,文本 / HEX 字节均可收发,字符集可配置。 ```kotlin // Kotlin // 1. 构建配置 val config = UdpConfig.Builder() .localPort(0) // 本地端口,0=系统自动分配 .receive(true) // 开启接收 .broadcast(true) // 允许发送广播 .charset("UTF-8") .build() // 2. 创建并启动 UDP(门面方法内部已调用 start) val udp = IotLibrary.createUdpClient(config, object : UdpListener { override fun onStarted(localPort: Int) { /* 已启动,localPort 为实际绑定端口 */ } override fun onReceive(bytes: ByteArray, sourceIp: String, sourcePort: Int) { /* 收到字节 */ } override fun onReceiveText(text: String, sourceIp: String, sourcePort: Int) { /* 收到文本 */ } override fun onSendSuccess(address: String, bytes: ByteArray) { /* 发送成功 */ } override fun onError(error: Exception) { /* 异常 */ } }) // 3. 使用 udp.sendText("192.168.1.100", 9000, "hello") // 单播文本 udp.send("192.168.1.100", 9000, byteArrayOf(0x01, 0x02)) // 单播字节 udp.broadcastText("255.255.255.255", 9000, "find") // 广播文本(需 broadcast(true)) udp.broadcast("255.255.255.255", 9000, byteArrayOf(0x01)) // 广播字节 udp.joinMulticast("239.0.0.1", 9000) // 加入组播组 udp.sendToMulticast(byteArrayOf(0x01)) // 向组播组发送 udp.release() // 释放(关闭 socket、停止接收线程) ``` ### Java 用法 ```java UdpConfig config = new UdpConfig.Builder() .localPort(9000) .receive(true) .broadcast(true) .build(); UdpClient udp = IotLibrary.createUdpClient(config, new UdpListener() { @Override public void onStarted(int localPort) { } @Override public void onReceive(byte[] bytes, String sourceIp, int sourcePort) { } @Override public void onReceiveText(String text, String sourceIp, int sourcePort) { } }); udp.sendText("192.168.1.100", 9000, "hello"); udp.release(); ``` ### UdpConfig 配置项 | 配置项 | 说明 | 默认值 | |---|---|---| | `localPort` | 本地绑定端口(0=系统自动分配) | 0 | | `receive` | 是否开启接收数据 | true | | `broadcast` | 是否允许发送广播(SO_BROADCAST) | false | | `bufferSize` | 接收缓冲区大小 | 4096 | | `charset` | 文本字符集 | UTF-8 | > 其他常用方法:`stop()`(停止并关闭 socket,可再次 start)、`getBoundPort()`(获取当前绑定端口)、`isRunning()`(是否运行中)、`isMulticastAddress(ip)`(判断是否为合法组播地址)。 > 注意:UDP 是无连接协议,网络不通通常不会立即报错;如需可靠传输请使用 TCP 模块。 --- ## 7. WebSocket 客户端使用 基于 **OkHttp 5.3.0**,支持 `ws://` 与 `wss://`。 ```kotlin // Kotlin val ws = IotLibrary.createWebSocketClient( WebSocketConfig.Builder("ws://192.168.1.100:8080/ws") .connectTimeout(10_000) .pingInterval(10_000) // OkHttp 内置 Ping 心跳(毫秒) .autoReconnect(true) .addHeader("token", "abc123") // 附加请求头 .build(), object : WebSocketListener { override fun onConnected() { } override fun onMessage(text: String) { } override fun onMessage(bytes: ByteArray) { } override fun onClosed(reason: DisconnectReason, code: Int, message: String) { } override fun onReconnecting(times: Int) { } } ) ws.connect() ws.sendText("{\"cmd\":\"status\"}") ws.sendBytes(byteArrayOf(0x01, 0x02)) ws.disconnect(1000, "手动关闭") ``` ### WebSocketConfig 配置项 | 配置项 | 说明 | 默认值 | |---|---|---| | `url` | WebSocket 地址(必填) | - | | `connectTimeout` | 连接超时(毫秒) | 10000 | | `pingInterval` | OkHttp 心跳 Ping(毫秒,0=关闭) | 0 | | `autoReconnect` | 自动重连 | true | | `reconnectInterval` | 重连间隔(毫秒) | 3000 | | `maxReconnectTimes` | 最大重连次数(0=无限) | 0 | | `headers` | 附加请求头 | 空 | | `useCompression` | gzip 解压 | true | --- ## 8. WebSocket 服务端(硬件调试工具) > 场景:手机开启 WebSocket 服务端,硬件设备(如支持 WebSocket 的模组)主动连接。 > 原生实现 RFC 6455 握手与帧协议,无额外依赖,兼容 API 21+。 ```kotlin // Kotlin val server = IotLibrary.createWebSocketServer( WebSocketServerConfig(port = 8080), object : WebSocketServerListener { override fun onStarted(port: Int, ip: String) { } override fun onClientConnected(clientId: String, address: String) { } override fun onMessage(clientId: String, address: String, text: String) { } override fun onMessageBytes(clientId: String, address: String, bytes: ByteArray) { } } ) server.start() server.broadcastText("hello") server.broadcastBytes(byteArrayOf(0x01)) server.sendTextToClient("C1", "hi") server.stop() ``` ### Java 用法 ```java WebSocketServer server = IotLibrary.createWebSocketServer( new WebSocketServerConfig(8080), new WebSocketServerListener() { @Override public void onStarted(int port, String ip) { } @Override public void onMessage(String clientId, String address, String text) { } }); server.start(); server.broadcastText("hello"); server.stop(); ``` ### WebSocketServerConfig 配置项 | 配置项 | 说明 | 默认值 | |---|---|---| | `port` | 监听端口(必填) | - | | `charset` | 文本字符集 | UTF-8 | > 服务端其他方法:`broadcastBytes(bytes)`、`sendTextToClient(clientId, text)`、`sendBytesToClient(clientId, bytes)`、`getClientIds()`、`stop()`。 --- ## 9. MQTT 客户端使用 基于 **Eclipse Paho MQTT v3**(MQTT 3.1.1),支持 QoS 0/1/2、保留消息、遗嘱消息、自动重连。 ```kotlin // Kotlin val mqtt = IotLibrary.createMqttClient( MqttConfig.Builder("tcp://broker.emqx.io:1883") .clientId("device_001") // 留空自动生成 .username("admin") // 可选 .password("123456") // 可选 .cleanSession(true) .keepAlive(60) // 心跳保活(秒) .connectTimeout(10) // 连接超时(秒) .autoReconnect(true) // Paho 自动重连 .lastWillTopic("device/001/offline") // 遗嘱主题(可选) .lastWillMessage("device offline") .lastWillQos(1) .lastWillRetained(false) .build(), object : MqttListener { override fun onConnected() { } override fun onReconnected(serverUri: String) { } override fun onMessage(topic: String, payload: ByteArray, text: String, qos: Int, retained: Boolean) { } override fun onSubscribed(topic: String, qos: Int) { } override fun onDisconnected(message: String) { } } ) mqtt.connect() mqtt.subscribe("device/+/data", 1) // 订阅(支持通配符) mqtt.publish("device/001/cmd", "reboot", 1, false) // 发布 mqtt.unsubscribe("device/+/data") mqtt.disconnect() ``` ### MqttConfig 配置项 | 配置项 | 说明 | 默认值 | |---|---|---| | `brokerUrl` | Broker 地址(必填,如 `tcp://host:1883` / `ssl://host:8883`) | - | | `clientId` | 客户端 ID(空=自动生成) | 自动 | | `username` / `password` | 认证信息(可选) | 空 | | `cleanSession` | 清空会话 | true | | `keepAlive` | 心跳保活(秒) | 60 | | `connectTimeout` | 连接超时(秒) | 10 | | `autoReconnect` | 自动重连(Paho 内置) | true | | `lastWillTopic/Message/Qos/Retained` | 遗嘱消息(可选) | 关闭 | > MQTT 连接、订阅、发布均为后台线程执行,不会阻塞 UI。 --- ## 10. MVVM 架构中使用 Library 提供 `IotViewModel` 基类(依赖 `androidx.lifecycle:lifecycle-viewmodel`): - 通过 `createXxx()` 创建通信对象并自动登记(`createSocketClient` / `createSocketServer` / `createWebSocketClient` / `createWebSocketServer` / `createMqttClient` / `createUdpClient`); - ViewModel 销毁(`onCleared`)时**自动断开/释放**所有连接; - 支持子类通过 getter 手动控制:`getSocketClients()` / `getSocketServers()` / `getWebSocketClients()` / `getWebSocketServers()` / `getMqttClients()` / `getUdpClients()`。 ```kotlin // ViewModel 层 class DeviceViewModel : IotViewModel() { private val _status = MutableLiveData("未连接") val status: LiveData = _status fun connect(host: String, port: Int) { createSocketClient( SocketConfig.Builder(host, port).autoReconnect(true).build(), object : SocketListener { override fun onConnected(address: String) { _status.value = "已连接 $address" } } ).connect() } } // UI 层(Activity / Fragment) class DeviceActivity : AppCompatActivity() { private val viewModel: DeviceViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { // ... viewModel.status.observe(this) { text -> textView.text = text } } } ``` ```java // Java MVVM public class DeviceViewModel extends IotViewModel { private MutableLiveData status = new MutableLiveData<>("未连接"); public LiveData getStatus() { return status; } public void connect(String host, int port) { createSocketClient( new SocketConfig.Builder(host, port).build(), new SocketListener() { @Override public void onConnected(String address) { status.setValue("已连接"); } } ).connect(); } } ``` --- ## 11. 通用工具类使用 `core` 包提供与通信收发配合的公共工具,不依赖任何网络模块,可单独使用。 ### IotUtils(HEX 转换 / 字节拼接) ```kotlin // Kotlin val hex = IotUtils.bytesToHex(byteArrayOf(0x01, 0x0A, 0xFF)) // "010AFF" val hexSpace = IotUtils.bytesToHex(byteArrayOf(0x01, 0x0A), withSpace = true) // "01 0A" val bytes = IotUtils.hexToBytes("01 A2 FF") // 支持空格 / 0x 前缀 val data = IotUtils.concat(byteArrayOf(0x01), byteArrayOf(0x02)) // 字节拼接 IotUtils.closeQuietly(socket) // 安全关闭 ``` ```java // Java String hex = IotUtils.bytesToHex(new byte[]{0x01, 0x0A}, false); byte[] bytes = IotUtils.hexToBytes("01 A2 FF"); ``` | 方法 | 说明 | |---|---| | `bytesToHex(bytes, withSpace)` | 字节数组 → HEX 大写字符串;`withSpace=true` 时以空格分隔(如 `01 A2 FF`) | | `hexToBytes(hex)` | HEX 字符串 → 字节数组;支持空格 / `0x` 前缀,非法输入抛 `IllegalArgumentException` | | `concat(vararg arrays)` | 多段字节数组拼接 | | `closeQuietly(closeable)` | 安全关闭资源(不抛异常) | ### IotConstants(常量 / 状态枚举) - `VERSION` / `LIB_NAME`:库版本号与名称; - `DEFAULT_CHARSET`:默认字符集 UTF-8; - `DEFAULT_TIMEOUT`:默认连接超时 10 秒; - `IotState`:连接状态枚举(`IDLE` / `CONNECTING` / `CONNECTED` / `DISCONNECTING` / `DISCONNECTED` / `RECONNECTING`); - `DisconnectReason`:断开原因枚举(`MANUAL` / `CONNECT_FAILED` / `REMOTE_CLOSED` / `TIMEOUT` / `HEARTBEAT_TIMEOUT` / `ERROR`)。 > 各回调中的 `DisconnectReason` 参数即来自 `IotConstants.DisconnectReason`,可用于区分手动断开与异常断开。 --- ## 12. 权限与兼容性说明 ### 权限 Library 清单已声明(合并进宿主 App): ```xml ``` - `INTERNET` 为**普通权限**,安装时自动授予,无需运行时申请(Android 6.0+ 也不会弹窗); - Library 提供了 `IotLibrary.hasInternetPermission(context)` 检查方法。 ### 明文流量(重要) Android 9 (API 28) 起默认禁止明文 HTTP/WebSocket。为保证局域网内 `ws://`(明文 WebSocket)、`tcp://` MQTT、硬件设备直连调试可用, **Library 与测试 App 的清单均声明了 `android:usesCleartextTraffic="true"`**。 生产环境建议改用 `wss://` / `ssl://` 加密连接,或在 App 中使用 `network_security_config.xml` 仅对指定域名放行明文。 ### 版本兼容 | 项目 | 值 | |---|---| | minSdk | **21(Android 5.0)** | | 兼容上限 | Android 17 (API 37) | | Java 版本 | 11(编译),运行时兼容 5.0+ | | 特殊处理 | WebSocketServer Base64 按 API 21/26 分版本实现 | - TCP / UDP / WebSocket / MQTT 均为纯网络 API,无高版本专属系统 API; - 回调线程分发使用 `Handler(Looper.getMainLooper())`,全版本可用; - Library 不持有 Activity/View 引用,配合 `release()` 使用无泄漏风险。 --- ## 13. 测试工具 App 使用说明 工程内 `app` 模块为完整的功能测试工具(含全部测试页面): | 入口 | 功能 | |---|---| | TCP 客户端测试 | 连接服务器、文本/HEX 发送、接收、自动重连观察 | | TCP 服务端 | **手机开 TCP 服务端,硬件设备直连调试**(支持广播) | | UDP 客户端测试 | **单播 / 广播 / 组播收发,文本/HEX,方便设备发现调试** | | WebSocket 客户端测试 | ws/wss 连接、文本收发、自动重连 | | WebSocket 服务端 | **手机开 WebSocket 服务端,硬件设备直连调试**(支持广播) | | MQTT 客户端测试 | 连接 Broker、认证、订阅/退订(通配符)、发布(QoS/保留) | | MVVM 架构使用示例 | ViewModel + LiveData 调用 Library 示例 | | 关于 | 开发者信息 | **硬件联调步骤(TCP):** 1. 打开 App → TCP 服务端页面 → 输入端口 → 点击「启动」; 2. 页面显示本机局域网 IP(如 192.168.1.100:8080); 3. 硬件设备作为 TCP 客户端连接该地址; 4. 在 App 中输入内容点击「广播发送」,即可观察收发数据。 **硬件联调步骤(UDP):** 1. 打开 App → UDP 客户端测试页面 → 设置本地端口(如 9000)并开启接收; 2. 点击「启动」后记录页面显示的实际绑定端口; 3. 若需广播发现设备,勾选「允许广播」,在目标地址填 `255.255.255.255`,点击「广播发送」; 4. 硬件设备收到广播后回复,即可在日志区看到来源 IP/端口与数据。 **开发者信息:宁工 联系电话:17776688224** --- ## 14. 常见问题 FAQ **Q1:连接局域网设备失败?** - 确保手机与设备在同一网段; - Android 9+ 明文流量已默认放行(本库已处理); - 检查防火墙/路由器是否隔离设备间通信。 **Q2:自动重连不生效?** - 确认 `autoReconnect(true)` 已设置; - 手动调用 `disconnect()` 后不会自动重连(设计如此)。 **Q3:MQTT 连不上?** - 确认 Broker 地址格式:`tcp://host:port`; - 使用公共测试 Broker:`tcp://broker.emqx.io:1883`; - 同一 Broker 下 clientId 需唯一,冲突会导致互踢。 **Q4:回调不执行?** - 默认回调在主线程,若在 `onDestroy` 后仍回调属正常(对象未释放); - 若关闭了主线程分发,需自行保证线程安全。 **Q5:内存泄漏?** - Activity/页面销毁时调用 `client.release()`(测试 App 已实现); - MVVM 项目继承 `IotViewModel` 会自动释放。 **Q6:UDP 发送无回应?** - UDP 是无连接协议,发送成功仅代表已交给系统,不代表对方收到; - 确认对方已开启接收且与手机同一网段; - 广播需在配置中开启 `broadcast(true)`;组播需先 `joinMulticast()`。 --- *文档版本:1.1.1(补充通用工具类、服务端配置表与示例) | 开发者:宁工 17776688224*