From 3efa75193930a3047c80306bf37dc758c3591271 Mon Sep 17 00:00:00 2001 From: TongTongStudio Date: Sun, 9 Aug 2026 20:01:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(mqtt):=20=E5=A2=9E=E5=8A=A0=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=A6=BB=E7=BA=BF=E9=81=97=E8=A8=80=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=8F=8A=E4=B8=BB=E5=8A=A8=E6=96=AD=E5=BC=80=E6=97=B6=E4=B8=8A?= =?UTF-8?q?=E6=8A=A5=E7=A6=BB=E7=BA=BF=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 连接时设置遗嘱消息(will message),主题为设备状态,payload 为包含设备序列号和离线状态的 JSON - 主动断开连接时,先发布一条离线消息,确保服务端即时感知设备下线 - 网络恢复时,自动尝试 MQTT 重连 --- .../com/ttstd/dialer/manager/MqttManager.java | 27 +++++++++++++++++-- .../dialer/service/main/MainService.java | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/ttstd/dialer/manager/MqttManager.java b/app/src/main/java/com/ttstd/dialer/manager/MqttManager.java index 41a8900..a7d556e 100644 --- a/app/src/main/java/com/ttstd/dialer/manager/MqttManager.java +++ b/app/src/main/java/com/ttstd/dialer/manager/MqttManager.java @@ -138,6 +138,17 @@ public class MqttManager { return INSTANCE; } + /** + * 构建设备离线遗言消息 JSON + */ + private byte[] buildWillPayload() { + String sn = DeviceManagerService.getInstance().getSerial(); + if (TextUtils.isEmpty(sn)) { + sn = ""; + } + return ("{\"sn\":\"" + sn + "\",\"status\":\"offline\"}").getBytes(StandardCharsets.UTF_8); + } + /** * 建立 MQTT 连接(异步,断线后自动重连) */ @@ -176,6 +187,12 @@ public class MqttManager { mMqttClient.connectWith() .keepAlive(30) + .willPublish() + .topic(MQTT_TOPIC_STATUS) + .payload(buildWillPayload()) + .qos(com.hivemq.client.mqtt.datatypes.MqttQos.AT_LEAST_ONCE) + .retain(false) + .applyWillPublish() .send() .whenComplete((connAck, throwable) -> { if (throwable != null) { @@ -240,7 +257,7 @@ public class MqttManager { }; /** - * 断开 MQTT 连接(主动断开,不会触发自动重连) + * 断开 MQTT 连接(主动断开,先发离线消息再断连,不会触发遗言) */ public void disconnect() { // 标记主动断开,重连任务与断线监听均据此跳过重连 @@ -248,7 +265,13 @@ public class MqttManager { mReconnectHandler.removeCallbacks(mReconnectRunnable); stopHeartbeat(); try { - if (mMqttClient != null) { + if (mMqttClient != null && mConnected) { + // 主动上报离线消息,确保服务端即时感知设备下线 + String sn = DeviceManagerService.getInstance().getSerial(); + if (!TextUtils.isEmpty(sn)) { + String offlinePayload = "{\"sn\":\"" + sn + "\",\"status\":\"offline\"}"; + publish(MQTT_TOPIC_STATUS, offlinePayload); + } mMqttClient.disconnect(); mMqttClient = null; } diff --git a/app/src/main/java/com/ttstd/dialer/service/main/MainService.java b/app/src/main/java/com/ttstd/dialer/service/main/MainService.java index ccfaf31..9a862b3 100644 --- a/app/src/main/java/com/ttstd/dialer/service/main/MainService.java +++ b/app/src/main/java/com/ttstd/dialer/service/main/MainService.java @@ -28,6 +28,7 @@ import com.ttstd.dialer.base.BaseService; import com.ttstd.dialer.bean.req.SnLocationReq; import com.ttstd.dialer.config.CommonConfig; import com.ttstd.dialer.manager.ContactSyncManager; +import com.ttstd.dialer.manager.MqttManager; import com.ttstd.dialer.utils.ApkUtils; import com.ttstd.dialer.utils.Logger; import com.ttstd.dialer.utils.SystemUtils; @@ -61,6 +62,8 @@ public class MainService extends BaseService implements NetworkUtils.OnNetworkSt public void onConnected(NetworkUtils.NetworkType networkType) { Logger.e(TAG, "onConnected: networkType = " + networkType); ContactSyncManager.getInstance(this).syncPendingContacts(); + // 网络恢复后立刻尝试 MQTT 重连 + MqttManager.getInstance().connect(); } @Nullable