Files
ring-health-app/docs/verification-m1.md
T

155 lines
11 KiB
Markdown
Raw 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.
# M1 静态页面验收记录
## 环境
- 记录日期:2026-09-10
- 构建版本:0.1.0 (versionCode 1)
- 构建机:Windows 11,JDK 17.0.12,Android SDK `D:\Android\Sdk`
- **验收设备:Android 模拟器**(非真机)
- AVD `ringtest`,外形 `pixel_7`,镜像 `system-images;android-36;google_apis;x86_64`
- 1080×2400 @ 420dpi;系统栏 inset:状态栏 136 px、导航栏 63 px
> **本次与上一次记录的差别:** 上一版这份文件里,人工验收**整张表都是「未执行 —— 无设备」**。
> 2026-09-10 当天下载并装好了模拟器(见文末「模拟器是怎么装上的」),因此**下面这张表已经真的跑过了**。
> 但仍有一处必须说清楚:**跑的是模拟器,不是真机**。模拟器能证明界面渲染正确、导航不崩,
> 但证明不了真机上的性能、厂商 ROM 差异、以及 M2 之后才涉及的蓝牙权限行为。
## 自动化验证(已执行)
- 单元测试:`./gradlew :app:testDebugUnitTest` —— **21 项全绿**
(`FormattersTest` 7 + `MockDataProviderTest` 5 + `HomeViewModelTest` 1 + `WorkoutViewModelTest` 1
+ `DeviceViewModelTest` 2 + `MetricDetailViewModelTest` 3 + `RoutesTest` 2)
- 构建:`./gradlew :app:assembleDebug` —— `BUILD SUCCESSFUL`,
产物 `app/build/outputs/apk/debug/app-debug.apk`(18,907,725 字节)
- 安装并启动:`adb install -r` + `am start` —— 成功,进程存活,`logcat -b crash` 全程为空
- **未执行**:各页面的 `@Preview` 在 Android Studio 中渲染。本机没有 IDE GUI 自动化手段,
这一项仍是未执行的 —— 不过它原本的作用(没有设备时唯一的界面检查手段)已被下面的模拟器实测取代
## 人工验收(模拟器实测,逐项已执行)
| 项 | 结果 | 证据 |
|---|---|---|
| 应用启动无崩溃 | ✅ | 进程 pid 存活,`mCurrentFocus` 为 `MainActivity`,crash buffer 空 |
| 四个 Tab 显示为 健康 / 运动 / 设备 / 我的 | ✅ | 四个 Tab 文案与图标正确,选中态为淡紫底 + 绿色文字 |
| 四个 Tab 可自由切换 | ✅ | 逐个点过,无闪烁、无崩溃 |
| 首页:设备状态条 | ✅ | 「RingHealth 智能戒指 · 已连接 / 电量 78%」 |
| 首页:步数大环 8,426 / 目标 10,000 | ✅ | 环按 84% 填充,另有「6.21 公里 / 327 千卡」 |
| 首页:六个指标卡,血压显示「未开启」 | ✅ | 心率 72 次/分、睡眠 7小时32分、血氧 98%、压力 34 正常、体温 36.5 °C、血压 未开启 |
| 首页:点指标卡进详情,标题为该指标中文名 | ✅ | 点「睡眠」→ 标题「睡眠」;点「心率」→ 标题「心率」 |
| 详情页:近 7 天 7 根柱 / 近 30 天 30 根柱 | ✅ | 切换后柱子数量与统计值都变了(心率:78.0/95.1/58.0 → 77.0/96.0/59.8) |
| 睡眠详情额外显示分期卡片,其他指标没有 | ✅ | 睡眠有「睡眠分期」卡(深睡/浅睡/清醒 + 入睡/起床),心率页没有该卡 |
| 睡眠入睡/起床时间读起来像「一晚」 | ✅ | 入睡 22:08 / 起床 06:08,正好相隔 8 小时(`DEMO_SLEEP_WINDOW_MILLIS` 生效) |
| 详情页:返回后回到首页 | ✅ | `keyevent 4` 后回到健康首页 |
| 运动页:开始运动 + 5 条记录 | ✅ | 5 条:户外跑步/健走/骑行/自由训练/户外跑步 |
| 运动页「查看全部」进历史页,底部导航栏仍可见 | ✅ | 历史页 5 条记录,底部四 Tab 正常显示 |
| 设备页:戒指卡片 电量 78% / 固件 1.0.5 | ✅ | 另显示「已连接」与蓝牙图标 |
| 设备页「更多设置」开关可切换,返回后状态保持 | ✅ | 打开「压力监测」→ 返回设备页 → 再进入,开关仍为开 |
| 我的页 | ✅ | 头像卡与分组入口正常 |
| 全程无崩溃 | ✅ | `logcat -b crash` 自始至终为空 |
### 补充实测:终审修复轮的六项改动
这六项原先只有代码阅读作为依据,现在逐项在模拟器上确认:
| 改动 | 实测结果 |
|---|---|
| 详情页按指标取色 | ✅ 睡眠=蓝、心率=红,与首页各卡的 tint 一致 |
| 血压卡不可点击 | ✅ 点血压卡后与点击前**逐像素一致**,未发生跳转 |
| 压力卡 `unit` 接线 | ✅ 卡片显示「34 **正常**」,即 `stressLevelLabelRes` 真的接上了 |
| 周/月 chips 常驻 | ✅ 两个范围的详情页都始终显示 chips |
| `consumeWindowInsets` 顶栏内边距 | ✅ **量了像素**:状态栏 136 px,顶栏白底 136→303 px,即**正好 168 px = 64 dp**(Material 3 `TopAppBar` 标准高度),标题文字中心在顶栏内 86 px ≈ 32 dp,**正中**。若 insets 被叠加,顶栏会变成 88 dp 且标题偏下 —— 实测不是 |
| README 注明 `installDebug` 需设备 | ✅ 文档项 |
> `consumeWindowInsets` 这一项此前被反复标注「推理得出、未经设备验证」,**现在验证过了**。
> 顺带确认:状态栏上方那条灰带就是状态栏本身(136 px),不是多余留白。
## 本轮新发现的观察(非缺陷,记录备查)
1. **设备设置页与运动历史页没有 `TopAppBar`,也就没有返回箭头** —— 标题(「功能设置」)是普通
标题文字。返回只能靠系统返回手势,或点底部「设备」Tab。功能上可用,但与详情页(有 `←`)
不一致。**是否补一个顶栏,留给 M2 一起定。**
2. **运动记录的日期随运行时间变化** —— 两次截图里同一批记录显示 06:08 与 06:10。
因为 Mock 的时间戳是相对「此刻」生成的。这**削弱了设计文档 §8「每次运行截图一致」的说法**:
数据形状是确定性的,但日期不是。若将来要做截图对比测试,需要连时间源一起固定。
3. **趋势图把最后一根柱子画成深色**(其余为其 30% 透明度)—— 这是**有意的**,
`MetricBarChart(highlightLast = true)` 即「高亮今天」,KDoc 里写明了。
记录在此只是为了说明:实测看到的「只有最后一根是深色」不是渲染错误。
## 已知限制(阶段一有意为之)
- 数据全部为 Mock,不连蓝牙、不连后端
- 血压恒为「未开启」占位(`HealthSummary.bloodPressure = null`)
- 设备设置页的开关只改内存状态,**重启即重置**(对应 M2 的协议 0502/0504);
本次只验证了跨页面保持,没有验证跨进程重启
- 睡眠分期条与入睡/起床时间是演示值(固定比例 + 最后一个数据点往前 8 小时),无真实分期数据
- 详情页统计摘要一律保留一位小数(步数因此显示为「平均 7512.3」这类精度过剩的形式)
- 仅浅色模式
- 血压卡**不可点击**(`value == null` 时 `onClick` 传 `null`)
- 详情页的**周/月切换常驻**,空数据时只把切换条下方的图表与统计换成一行空态文案
### 仍然没有验证到的
- **详情页的空数据态**:当前 Mock 恒返回 7 或 30 个点,该分支不可达,**本次没有、也无法触达**。
它仍然是只有代码推理保证的防御性代码。
- **旋转屏幕 / 深色系统设置下不崩溃**:本次未测。
- **`@Preview` 渲染**:未测(见上)。
- **真机**:未测。模拟器不能替代真机验收。
### 与设计文档 §6 的偏差(有意收窄,非遗漏)
- **设备页少了四项**:查找戒指(050B)、智能提醒/闹钟占位、固件升级占位(OTA 17xx)、佩戴检测。
阶段一没有真实协议可对接,摆一排点不动的入口不如不摆(ledger R27)。**这些能力仍属产品范围,
将于后续里程碑回归**;设计文档 §6 的设备页一行已用删除线标注。**本次实测确认设备页确实没有这四项。**
- **详情页由「四个专属设计」收敛为一个模板**:四条路由合并为 `detail/{metric}`,七个指标共用
同一模板。**仅睡眠保留了专属区块**。未实现的是:步数的大环、心率的折线/静息-运动区间、
血氧的正常范围说明文案。详见设计文档 §6 下的注记。
### M2 接入时的已知接缝(交接用,本阶段不修)
`RingDeviceRepository` 目前**不足以承载 M2 的设备控制**:
- `refreshDeviceState()` **零调用者** —— 接口定义了,UI 从不触发。M2 需要接上「下拉刷新」或
进入设备页时刷新,否则真机断连后界面不会更新。
- `setFunctionEnabled` 是**非 `suspend`** 的 —— Mock 只改内存态所以无所谓,但 M2 写向 BLE
必然是挂起操作,接口签名届时需要改,连带 `DeviceViewModel` 的调用点。
- 预计 M2 的改动面:`domain/repository/Repositories.kt`、`data/mock/*`、`di/AppContainer.kt`、
`AndroidManifest.xml`(BLE 权限)、`app/build.gradle.kts` + `gradle/libs.versions.toml`
(厂商 Java 依赖,**很可能需要 Jetifier**)、`feature/device/DeviceScreen.kt`。
完整清单见实施计划的「M2 交接提示」一节。
## 覆盖缺口声明(已大幅收窄,但仍非零)
M1 的运行时行为**已在 Android 模拟器上完整走查过一遍**(上表逐项打勾),不再是「只有编译期保证」。
但仍有三个缺口,**不要把它们读成「已验证」**:
1. **跑的是模拟器不是真机** —— 真机上的厂商 ROM、性能、字体缩放、刘海/挖孔适配均未检验。
2. **空数据态与旋转/深色模式未触达**(见上)。
3. **`@Preview` 未渲染** —— 不过它原本的替代作用已被模拟器实测覆盖。
首次拿到真机时,请至少重跑上表中的「启动无崩溃」「四 Tab 切换」「详情页顶栏内边距」三项。
## 附:模拟器是怎么装上的(含一个踩过的坑)
本机原先 `D:\Android\Sdk` 下没有 `emulator/` 也没有 `system-images/`,本次新装:
```bash
# 1) 装包(注意坑:见下)
/d/Android/Sdk/cmdline-tools/latest/bin/sdkmanager.bat \
--sdk_root=D:/Android/Sdk "emulator" "system-images;android-36;google_apis;x86_64"
# 2) 建 AVD(avdmanager 不认 --sdk_root,只认环境变量)
export ANDROID_SDK_ROOT='D:\Android\Sdk' ANDROID_AVD_HOME='D:\Android\avd'
echo no | /d/Android/Sdk/cmdline-tools/latest/bin/avdmanager.bat create avd \
-n ringtest -k "system-images;android-36;google_apis;x86_64" -d pixel_7
# 3) 启动
/d/Android/Sdk/emulator/emulator.exe -avd ringtest
```
**坑:`--sdk_root` 一定要写正斜杠。** 写成 `D:\Android\Sdk` 时,Git Bash 会把反斜杠吃掉,
变成 Windows 的**盘符相对路径** `D:AndroidSdk` —— 这不是绝对路径,而是「D 盘当前目录下的
AndroidSdk」。结果 sdkmanager 把 5.3 GB 的包装进了 `cmdline-tools\latest\bin\AndroidSdk\`。
同盘移动是瞬时的,已搬回 `D:\Android\Sdk\`。**在 Git Bash 里给 Windows 工具传路径,一律用正斜杠。**
另外 `ANDROID_AVD_HOME` 已设为用户级变量 `D:\Android\avd`(AVD 镜像有几个 G,C 盘只剩 29 G)。