• v0.2.1 6dfd90f7ca

    zijunchiang released this 2026-09-17 05:44:07 +08:00 | 2 commits to main since this release

    ⚠️ 本版已被 v0.2.2 取代(建议直接用 v0.2.2):
    v0.2.2 修掉了「合规但不回 pong 的接收端被周期性误判为链路已死」——
    契约 §3.6 明确 pong 只用于诊断,而本版会因此每 15 秒主动断链重连,
    正是"频繁重连"的症状(自家 Windows 接收端会回 pong,所以联调时走不到这条路径)。

    OpenDance Studio -- Android 辅助 App v0.2.1

    修复:重连链路的一处真实缺陷 —— 上一次会话的关闭码会污染下一次会话,
    导致重新开始推流后失去自动重连能力。建议所有用户改用本版。

    新增:JVM 内的真实 WebSocket 重连集成测试(无需设备)。

    契约快照不变:rest-api 0.5.0 / websocket-keypoints 0.2.0 / data-models 0.7.0 /
    skeleton-topology 0.2.0 / model-formats 0.5.0 / database 0.4.0
    (与 opendance-web / opendance-windows 逐字节一致)。

    一、修复的缺陷(⑦ 连接与重连)

    现象:第一次连接被对端以 1001 关闭(例如 Windows 端服务重启)之后,
    用户再次点「开始推流」,如果这一次是网络层失败(服务端还没起来 / 被拒),
    客户端不会自动重连,界面停在「已停止」,只能反复手点。

    根因:ReconnectPolicy.shouldReconnect(closeCode) 是按上一次记录的关闭码
    判断该不该重连的(契约 §7:1000/1001/1002 不重连)。而 connect() 只重置了
    重连计数与 pong 时间,没有清 lastCloseCode —— 于是本次会话的网络失败
    (本应记为 0 = 未收到关闭帧 → 应重连)被旧值 1001 判成「对端主动关闭」,
    scheduleReconnect() 直接 stopped。

    修复:

    位置 改动
    connect() 每次新会话清掉关闭状态:lastCloseCode = 0、lastCloseReason = ""
    onFailure() 记录 recordClose(0, …),使契约 §7 的「异常断开 → 应重连」生效,并让界面「最近一次断开原因」显示本次失败而非旧值

    为什么之前没发现:原有 ReconnectPolicyTest(11 项)验的是纯函数
    「给定关闭码应该怎么退避」,而这个缺陷出在调用点(关闭码没被复位)。

    二、新增:真实 WebSocket 重连集成测试(8 项,JVM,无需设备)

    app/src/test/java/com/opendance/studio/PoseWebSocketReconnectTest.kt:
    用 MockWebServer.withWebSocketUpgrade 起真实 WebSocket 服务端
    (能按契约 §3.2 回 welcome、按 §3.6 回 pong、按指定关闭码关连接),
    把真实的 OkHttp WebSocket 接上去,覆盖两条分支:

    • 该重连的:异常关闭码 1011 → 进入 reconnecting,等待时间取自策略并落在
      ±20% 区间,重连成功后计数清零;服务端未启动时 1.5 秒内尝试 ≤3 次(退避生效);
    • 不该重连的:1000 / 1001 / 1002 / 用户主动 disconnect() → stopped
      且不再建立新连接(日志记录「不重连」便于真机排障);
    • 握手:hello 带 deviceId、welcome 的 sessionId 与保活参数解析、
      按协商间隔发送应用层 ping 并收到 pong(协议层 ping 不能替代)。
    $ ./gradlew :app:testDebugUnitTest
    测试类 6 个,用例 64 项,失败 0,跳过 0        # 原 56 项
    

    build/verify.sh 全绿:签名、APK 版本元数据 0.2.1/201、native 库体检
    (ELF 类型 / DT_NEEDED 闭包 / 16 KB 页对齐)、ABI 恰为两个真机 ABI、
    R8 保留 MediaPipe 20169 条、dex 含 PoseLandmarker。

    三、安装

    资产 说明
    opendance-android-v0.2.1.zip APK + README.txt + THIRD_PARTY.md + contracts/ 快照
    SHA256SUMS 裸文件名,下载目录内 sha256sum -c SHA256SUMS 直接校验
    sha256sum -c SHA256SUMS && unzip opendance-android-v0.2.1.zip
    adb install -r opendance-android-v0.2.1/app-release.apk      # Android 10+(minSdk 29)
    

    四、仍未在本环境验证(诚实声明)

    • 真机 30 分钟连续推流、Wi-Fi 抖动 / 切网 / 进程被杀 / Doze 省电等真实断网场景
      仍需设备实测 —— 本版新增的是「重连逻辑与真实 WebSocket 协议交互」的 JVM 级证据,
      它替代不了设备;
    • MediaPipe 在 arm64 真机上的初始化:打包配置一侧已用 native 库体检排除
      (ABI 匹配、依赖闭包完整、16 KB 页对齐),但运行时行为仍需设备。
    Downloads