Files
opendance-android/project.yaml
T
zijunchiang 6dfd90f7ca fix(reconnect): 上一次会话的关闭码污染下一次会话(v0.2.1)+ 重连链路的真实 WebSocket 集成测试
ReconnectPolicyTest(11 项)验的是**纯函数**「给定关闭码应该怎么退避」,而 ⑦
「连接频繁重连」的缺陷往往出在**调用点**。新增 PoseWebSocketReconnectTest(8 项):
用 MockWebServer.withWebSocketUpgrade 在 JVM 上起**真实** WebSocket 服务端
(能按 §3.2 回 welcome、按 §3.6 回 pong、按指定关闭码关连接),无需设备即可覆盖
「该重连的」与「不该重连的」两条分支。Robolectric 只用来提供 android.os.Build 桩。

它抓到的真实缺陷(本版修复):
  上一次会话的关闭码会污染下一次会话,导致重新开始推流后失去自动重连能力。
  复现:第一次连接被对端以 1001 关闭(按 §7 不重连,正确)→ 用户再点「开始推流」
  → 这一次是网络层失败(服务端还没起来),按 §7 **应当**重连 → 但 connect() 只重置了
  reconnectCounter 与 lastPongAtMs,**没有清 lastCloseCode** → scheduleReconnect()
  仍按 1001 判定 → 直接 stopped,**再也不会自动重连**。
  测试失败信息(修复前):
    ✗ 上一次 1001 关闭后重新连接,遇到网络失败仍应按策略重连
      AssertionError: 当前 state=STOPPED,lastCloseCode=1001,attempts=0

修复(PoseWebSocketClient.kt):
  * connect():清掉会话级关闭状态(lastCloseCode=0、lastCloseReason="");
  * onFailure():记录 recordClose(0, …)(契约 §7 中 0=未收到关闭帧 → 应重连),
    顺带让界面「最近一次断开原因」显示本次失败而不是旧值。

用例清单:握手→streaming 与 welcome 保活参数解析、按协商间隔发 ping 收 pong、
1011 按退避重连且等待落在策略 ±20% 区间、成功后计数清零、1001/1002 不重连、
主动断开不重连、上一次 1001 后再连遇网络失败仍应重连(本次回归锁)、
服务端未启动时 1.5s 内 ≤3 次尝试(退避生效)。

实测:./gradlew :app:testDebugUnitTest → 6 个测试类 / 64 项用例 / 0 失败
(原 56 项);build/verify.sh 全绿(签名、APK 版本元数据 0.2.1/201、native 库体检、
ABI、R8、dex)。版本号 0.2.0/200 → 0.2.1/201。

踩坑:第一版 MockWebServer 夹具的 101 响应没有回显 Sec-WebSocket-Protocol
(RFC 6455 要求),客户端记录的 negotiatedProtocol 为空导致断言失败 —— 那是
**夹具**不合规而非客户端问题,已在夹具里补上。写「真实对端」夹具时要按 RFC/契约
把服务端做对,否则会把夹具缺陷误判成产品缺陷。
2026-09-17 05:44:03 +08:00

105 lines
3.4 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
project: opendance-android-app
version: 0.2.1
repository: opendance-android
default_branch: main
platform: Android 10+(minSdk 29 / targetSdk 34)
contracts_version:
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
# 契约变更流程(文档 7.2):
# 任何跨端契约变更必须先在 opendance-web 修改 contracts/ 并提升版本,
# 再在本项目创建适配任务。本项目内的 contracts/ 只是只读快照。
dependencies:
- name: opendance-windows
kind: websocket-producer
contract: contracts/websocket-keypoints.md
usage: 本端为**发送方**,主动连接 Windows 客户端的 ws://<host>:8765/pose
- name: opendance-web
kind: contract-source
contract: contracts/skeleton-topology.md
usage: 33 点索引顺序与坐标语义(MediaPipe 原生顺序即契约顺序)
tasks:
- id: T-AND-001
file: tasks/001-scaffold.md
scope: Android Studio 项目骨架
status: done
- id: T-AND-002
file: tasks/002-camera-x.md
scope: CameraX 采集
status: done
- id: T-AND-003
file: tasks/003-mediapipe-pose.md
scope: MediaPipe Pose 端侧推理
status: done
- id: T-AND-004
file: tasks/004-keypoint-serializer.md
scope: 33 点 -> 239 字节帧
status: done
- id: T-AND-005
file: tasks/005-websocket-client.md
scope: WebSocket 推流 + 自动重连
status: done
- id: T-AND-006
file: tasks/006-connect-ui.md
scope: 连接页 + 主机发现
status: done
- id: T-AND-007
file: tasks/007-running-ui.md
scope: 运行页 + 状态指示
status: done
- id: T-AND-008
file: tasks/008-about-page.md
scope: 关于页 + 开源声明
status: done
- id: T-AND-009
file: tasks/009-build-apk.md
scope: Android Studio 打包
status: done
- id: T-AND-010
file: tasks/010-about-version.md
scope: 「关于」清单展示当前版本号 + 契约版本单一来源
status: done
- id: T-AND-011
file: tasks/011-reconnect.md
scope: 连接状态机 / 保活 / 去重与 Windows 端对齐
status: done
- id: T-AND-012
file: tasks/012-mediapipe-crash.md
scope: MediaPipe 初始化崩溃修复 + 诊断
status: done
- id: T-AND-013
file: tasks/013-apk-version.md
scope: APK 产物版本元数据(AndroidManifest 的 versionName/versionCode)校验 + 打包脚本 die 未定义修复
status: done
- id: T-AND-014
file: tasks/014-release-acceptance.md
scope: 发布包级端到端验收(读 zip 内 APK:版本元数据 / ABI+MediaPipe native / 模型资源 / R8 / 契约快照)
status: done
- id: T-AND-015
file: tasks/015-native-libs.md
scope: APK native 库体检(ELF 类型 / DT_NEEDED 闭包 / 16 KB 页对齐),纯标准库实现
status: done
- id: T-AND-016
file: tasks/016-reconnect-integration.md
scope: JVM 内以真实 WebSocket(MockWebServer)验证重连链路 + 修「上一次关闭码污染下一次会话」
status: done
deliverable:
artifact: opendance-android-v0.2.1.apk
packaging: Gradle 命令行 / Android Studio
includes:
- app-release.apk
- THIRD_PARTY.md
- README.txt
- contracts/ # 契约快照
release_rules:
- release 包只含 arm64-v8a / armeabi-v7a(真机 ABI)
- 版本号单一来源:versionName(= project.yaml 的 version)与 BuildConfig 契约版本