截图来自 Medium_Phone_API_35 模拟器(x86_64,Android 15,1080×2400), 设计稿在
docs/design/screens/。模拟器没有蓝牙,所以真机状态那批里「网络」页永远显示「还差一步 · 打开蓝牙」, 在线节点恒为 0、链路质量为「—」。这不是缺陷,是模拟器的限制(见 STATUS.md K7)。
| 目录 | 怎么来的 | 用来看什么 | |
|---|---|---|---|
| 真机状态 | docs/agent/screens/*.png(28 张) |
adb exec-out screencap,手点过去 |
真身份、真指纹、真蓝牙状态、真权限弹窗——证明这套东西在真设备上确实是这样 |
| 四态渲染 | docs/agent/screens/preview/*.png(48 张) |
ScreenshotCaptureTest 在模拟器上组 12 屏 × 深浅 × 中英 |
排版、配色、中英文换行——和设计稿逐项比的是这一批 |
为什么要第二批:模拟器上没有第二个节点,会话列表、单个会话、地图上的队友、
SOS 接收态这些页面根本进不去,硬点只能截出一堆空页面。四态那批用的是编好的样例数据
(ui/preview/ScreenPreviews.kt,与 ScreenRenderTest 同一份),页面是满的,
四种状态一次齐全。它们不是真机状态,文件名带 preview- 前缀提醒这一点。
重截:
gradlew :app:assembleDevDebug :app:assembleDevDebugAndroidTest
adb install -r -t app/build/outputs/apk/dev/debug/app-dev-x86_64-debug.apk
adb install -r -t app/build/outputs/apk/androidTest/dev/debug/app-dev-debug-androidTest.apk
adb shell am instrument -w -e class com.wildlink.app.ui.ScreenshotCaptureTest com.wildlink.app.dev.test/androidx.test.runner.AndroidJUnitRunner
adb pull /sdcard/Android/data/com.wildlink.app.dev/files/screens docs/agent/screens/preview
(用 am instrument 而不是 connectedAndroidTest:后者跑完会把两个 APK 卸掉,
外部文件目录跟着一起没,截好的图拉不出来。)
preview-<dark|light>-<zh|en>-<屏名>.png,48 张全部存在。
| 屏 | dark-zh | light-zh | dark-en | light-en | 与设计稿的差异 |
|---|---|---|---|---|---|
| Network(网络) | ✅ | ✅ | ✅ | ✅ | 雷达方位仍是均匀撒的(D-2) |
| Chats(会话列表) | ✅ | ✅ | ✅ | ✅ | 一致 |
| Chat(单个会话) | ✅ | ✅ | ✅ | ✅ | 一致 |
| Map(地图) | ✅ | ✅ | ✅ | ✅ | 底图是占位画布(D-7) |
| Record(记录) | ✅ | ✅ | ✅ | ✅ | 一致 |
| Settings(设置) | ✅ | ✅ | ✅ | ✅ | 多一节「后台」(设计稿上没有,阶段 06 新增) |
| BrandGuide(后台限制) | ✅ | ✅ | ✅ | ✅ | 设计稿没有这一屏,样式沿用卡片 + 分区标题 |
| Licenses(开源许可) | ✅ | ✅ | ✅ | ✅ | 同上 |
| Onboard(引导) | ✅ | ✅ | ✅ | ✅ | 一致(指纹为样例值,真机那批是真指纹) |
| Team(组建小队) | ✅ | ✅ | ✅ | ✅ | 二维码按 H7 重做,见下节 |
| Sos(求救发送中) | ✅ | ✅ | ✅ | ✅ | 一致 |
| SosAlert(收到求救) | ✅ | ✅ | ✅ | ✅ | 一致 |
截这一轮改掉的两处:
| # | 现象 | 根因 |
|---|---|---|
| 12 | 地图上贴右边缘的队友,名字被裁掉一半 | 自动取景的 14% 留白只保证点在画面内,标签还要往右伸一截。改成靠右时把标签翻到点的左侧(标记点同理) |
| 13 | 第一批截图里深色主题的消息气泡是浅色、字看不清 | 截图工装没铺底色。accentSoft 是 14% 透明度的橙,压在测试根节点默认的白底上就成了浅桃色。真机上底色由 MainActivity 铺——工装也得铺 |
| 屏 | dark-zh | light-zh | dark-en | light-en |
|---|---|---|---|---|
| Main(网络) | ✅ | ✅ | ✅ | ✅ |
| Chats(会话) | ✅ | ✅ | ✅ | ✅ |
| Chat(单个会话) | ✅ | ✅ | — | — |
| Team(组建小队) | ✅ | ✅ | — | — |
| Settings(设置) | ✅(另有滚动第二屏) | ✅ | — 用四态那批 | ✅(另有滚动第二屏) |
| Licenses / 紧急抹除确认 | ✅ | — | — | — |
| Onboard(引导) | — | ✅ | — | ✅ |
| Map(地图) | ✅ 占位 | ✅ 占位 | — | — |
| Record(记录) | ✅ | ✅ | — | — |
| SOS / SOSAlert | ⏳ 需要第二个节点才能进接收态;四态那批已覆盖版式 |
阶段 06 把 *-Settings.png 全部重截了——旧的那批是阶段 01 的两段选择器占位页,
现在是按设计稿做全的设置页。dark-en-Settings 没有真机那份(重新走一遍引导才能到那个状态),
版式由 preview-dark-en-Settings.png 覆盖。
跑之前这些在 Lint 与单元测试里一个都看不见——它们只有把 App 真装到设备上才会暴露。
| # | 现象 | 根因 | 修法 |
|---|---|---|---|
| 1 | 设置里选了「简体中文」,选中态变了,界面还是英文 | MainActivity 的 configChanges 写了 locale|layoutDirection,系统就不再重建 Activity,Compose 还拿着旧的 Resources |
从 configChanges 里去掉这两项(uiMode 留着,深浅由 Compose 自己切) |
| 2 | 去掉 configChanges 后仍然是英文 |
中文只在无限定符的 values/ 里。每应用语言设成 zh-CN 时系统的语言列表是 [zh-CN, 系统语言],资源解析找不到 values-zh* 就走到下一个语言,values-en 中标 |
tools/make_strings.py 多生成一份 values-zh/;并补 res/xml/locales_config.xml + android:localeConfig |
| 3 | 引导第 2 步的「我的入队码」是一个纯黑方块 | TeamRoute 里 val group = mesh.currentGroup 是普通属性不是 State,LaunchedEffect 建完队之后 qrContent 不会重算,一直是空串;ZXing 对空串抛异常,于是什么都没画,只剩底色 |
把 group 抬进 mutableStateOf,建完队立刻赋值;QrImage 对空内容显式不画 |
| 4 | Chat 屏标题压在状态栏图标底下 | Chat 是全屏路由,不走 AppScaffold,漏了 statusBarsPadding() |
补上(其余全屏路由本来就有) |
| 5 | 会话列表右上角的「+」点了没反应;入队之后再也回不到组队页 | ChatsScreen 的「+」没接回调,showTeam 只在启动时算一次 |
「+」接 onAddTeam,指向 TeamRoute(R1.5 的「中途加入」要用) |
| 6 | 会话列表里符号消息预览成 0x0004 |
previewOf 没有符号码表 |
复用 Chat 屏的 symbolLabel,显示「向北撤」 |
| 7 | 浅色主题下入队二维码是深底浅码(反相),设计稿是深码浅底;反相的码大多数扫码器读不出来 | MyQrCard 写死了「底 = ink、码 = surface」,两个主题都反相 |
改成跟着主题走(底 = surface、码 = ink):浅色深码浅底、深色浅码深底,与两张设计稿分别一致 |
| # | 差异 | 判断 |
|---|---|---|
✅ 已改:进引导页就在本机生成密钥对,卡片显示真指纹;生成前显示 ···· · ···· · ···· · ····(H6) |
||
| D-2 | 「网络」页雷达上的邻居角度是按序号均匀撒的,不是真实方位 | 已知,阶段 05 有位置数据后改(K10) |
| D-3 | 「最远跳数」恒为 0/1 | 已知(K9) |
| D-4 | 未读数恒为 0 | 已知(K13) |
| ✅ 阶段 05 已实现 | ||
| D-7 | 地图页的底图是占位画布(网格 + 示意等高线),不是高德底图 | 模拟器上高德的渲染库不存在(K19/K20),这是唯一能跑的路径。设计稿那张有真底图的地图要真机才比得了(G3) |
| D-8 | 记录页时间线上的「分享了位置」在搜救档下两分钟出现四条 | 是对的(搜救档 30 s 一次),只是演示数据里走得太快。真实徒步下不会这么密 |
| ✅ 已重做(H7):见下节 |
设计稿把二维码画成跟着主题反相(浅色深码浅底、深色浅码深底)。深色那张扫不出来 —— 标准解码器要求深码浅底,系统相机与微信都不会去试反相。而组队是线下当面扫的,扫不出来就等于没有。
重做之后:
| 项 | 之前 | 现在 |
|---|---|---|
| 极性 | 跟主题反相 | 永远深码浅底。深色主题下就是一块白瓷砖 |
| 静区 | MARGIN = 0 |
4 个模块(QR 规范的最小值)。没有静区,很多扫码器根本找不到定位图形 |
| 纠错 | M,但按 512 px 的像素矩阵逐像素画 | M,按模块矩阵画。之前那种画法每个「格子」其实是一个像素,圆角与溢出全乱 |
| 模块 | 直角小方块 | 圆角(半径 25%) |
| 定位图形 | 与数据模块同样画法 | 圆角「回」字:外 7×7 深、内 5×5 浅、心 3×3 深 |
| 中心 | 无 | WildLink 网状标记(一上二下 + 两条斜线,品牌橙),盖住 2.5% 的模块,ECC=M 的 15% 余量足够 |
| 有没有人盯着 | 无 | QrArtTest 八条:画出来 → 光栅化 → ZXing 解回原文。含反证一条(反相的码解不出来,谁改回反相测试就红) |
几何模型 (QrArt) 与画笔 (QrImage) 是分开的,测试和 Compose 用的是同一份几何 ——
所以「画出来的这张扫得出来」是一条能自动跑的断言,不是一句承诺。
真机上再拿另一台手机的系统相机扫一次,记录项在 field-test.md 的 M2b。
| # | 现象 | 根因 |
|---|---|---|
| 8 | 地图是一块黑的,logcat 每 500 ms 抛一次 UnsatisfiedLinkError |
高德 Java 层在 x86_64 上初始化成功,渲染引擎却没有 native 实现。可用性判断只 catch 异常,判成了「可用」。改成先查 nativeLibraryDir 里有没有 libAMapSDK_MAP*.so |
| 9 | 定位一直不启动,地图上没有「我」 | 定位只在前台服务里起,而服务要等蓝牙权限齐了才起。拒了蓝牙的用户连轨迹都记不了 |
| 10 | 记录页统计一直是 0、地图上没有轨迹 | 段落满一小时才切一次,落盘之前 UI 什么都拿不到 |
| 11 | 时间线上每个标记点两行、GPX 里每个航点两份 | 标记点同时要进 waypoints 表与事件流,两条路都必要,缺的是去重 |
gradlew :app:assembleDevDebug
adb install -r -t app/build/outputs/apk/dev/debug/app-dev-debug.apk
adb shell am start -n com.wildlink.app.dev/com.wildlink.app.MainActivity
adb exec-out screencap -p > docs/agent/screens/<主题>-<语言>-<屏名>.png
主题与语言在设置页里切(不要改系统设置——那样测不到 App 自己的切换逻辑, 上面第 1、2 条就是这么找出来的)。