docs+repo: 正式化发布——三份 README 重写为正式版说明、DEVELOPMENT.md 取代交接文档、历史档案统一更名 worklog、全库清理交接字样;脱敏:用户本机路径/设备序列号/内网 Git 地址全部泛化,.tools 本地缓存(13MB,pyc内嵌路径)移出追踪并忽略;123 单测全绿

This commit is contained in:
ZXCLI
2026-10-08 00:37:57 +08:00
parent 0c99f6e1b5
commit ce885926fe
259 changed files with 211 additions and 55141 deletions
@@ -1,16 +1,7 @@
# MAG160C 统一安卓APP — 完整开发交接文档(换模型用)
# MAG160C 安卓统一 App — 开发指南
> 生成时间:2026-09-07。给接手模型读取本文件即可恢复全部上下文。
> 结合 `docs/android_app/session_state.md`(心跳)与 `docs/android_app/reverse_apk_features.md`(逆向总表)。
---
## 0. 给新模型的读取提示词
> 你是本项目的续任开发者。请先完整阅读 `C:\Project\MAG160C\docs\android_app\HANDOFF_DEVELOPMENT.md`
> 和 `C:\Project\MAG160C\docs\android_app\session_state.md`、`C:\Project\MAG160C\docs\android_app\reverse_apk_features.md`、
> `C:\Project\MAG160C\analysis\protocol_spec.md`,再继续开发。项目根目录 `C:\Project\MAG160C` 是 git 仓库,
> 源码在 `android\` 子目录(Gradle 工程,package `com.mag160c.thermal`)。当前会话状态与待办见 session_state.md。
> 面向后续开发与维护。配套文档:`session_state.md`(开发进度与验证记录)、
> `reverse_apk_features.md`(官方 4 App 逆向功能总表)。
---
@@ -28,15 +19,14 @@
## 2. 技术栈与工具链(已部署)
- **纯 Kotlin + Jetpack Compose (Material 3)**,无 NDK、无 .so、无 native。
- **工具链(2026-09-09 本机重装;交接文档旧机器路径 C:\Tools\gradle-8.14.3、
Zulu、C:\Users\ZXC\AppData\Local\Android\Sdk 均已失效)**:
- **工具链**:
- JDK Temurin 21:`C:\Tools\jdk-21`
- Android SDK:`C:\Tools\android-sdk`(cmdline-tools\latest、platforms/android-36、
build-tools 36.0.0、platform-tools/adb;许可已接受;无模拟器/AVD/system-images)
- Gradle:用工程 wrapper `android\gradlew.bat`(8.14.3 自动下载)
- `android\local.properties` 已写 `sdk.dir`(已 gitignore)
- 构建需 `JAVA_HOME=C:\Tools\jdk-21`;国内下载慢可给 JVM 挂本机代理
(Clash 7890:`GRADLE_OPTS="-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=7890 ..."`)
- 构建需 `JAVA_HOME=C:\Tools\jdk-21`;依赖下载慢可为本机 JVM 配置代理
(如 `GRADLE_OPTS="-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=7890 ..."`)
- 工程版本目录 `gradle\libs.versions.toml`
(AGP 8.11.1 / Kotlin 2.2.0 / Compose BOM 2025.06.01 / lifecycle 2.9.1 / junit 4.13.2)。
- **磁盘轻量约定**:不装 NDK/CMake/zig(曾占用 2.4GB+,已卸载);全 Kotlin。
@@ -208,10 +198,9 @@ git -C C:\Project\MAG160C commit -m "android: ..."
## 6. 严重教训(反复踩坑,务必遵守)
1. **编码**:所有源码必须 UTF-8。本机默认编码是 GBK!
1. **编码**:所有源码必须 UTF-8。本机默认编码可能是 GBK!
- **python 读写文件必须显式 `encoding='utf-8'`**(`open(p,'w')` 裸写会变 GBK→编译出的中文全乱码)。
- 检测/修复脚本:`C:\Users\ZXC\AppData\Local\Temp\opencode\fix_encoding.py`、
`check_mojibake.py`。改完必须跑一遍确认全 OK,再构建。
- 改完必须跑一遍编码检查确认全 OK,再构建。
- gradle.properties 已有 `-Dfile.encoding=UTF-8`(gradle + kotlin daemon)。
2. **图标**:手写 pathData 的弧线易坏,一律用双弧圆 `M x,y a r,r 0 1,0 2r,0 a r,r 0 1,0 -2r,0z` + 直线/矩形。
3. **SurfaceView 与旋转**:不要在横竖屏间切换不同布局分支(SurfaceView 会被销毁且 surface 不重建)。
@@ -280,41 +269,16 @@ Android16 沉浸(状态栏隐藏+竖屏锁定+挖孔安全区)、乱码多
- 预览截图:`analysis/preview/preview_*.png`
- APK 产物:`build-artifacts/mag160c-app-debug.apk`
## 9. 下一轮提示词(交付新模型直接用)
## 9. 后续工作方向
> 你是本项目的续任开发者。请先完整阅读 `C:\Project\MAG160C\docs\android_app\HANDOFF_DEVELOPMENT.md`
> 和 `C:\Project\MAG160C\docs\android_app\session_state.md`、`docs\android_app\reverse_apk_features.md`、
> `C:\Project\MAG160C\analysis\protocol_spec.md`,再继续开发。
> 项目根 `C:\Project\MAG160C` 是 git 仓库,源码在 `android\`(Gradle 工程,package
> `com.mag160c.thermal`)。Android 16 已适配,目标是一个 MAG160C 热像仪(160×120, 15fps,
> USB VID 0x833C PID 1)统一 APP。
>
> 当前已完成到第 10 轮反馈修复:核心渲染管线 Kotlin 移植(逐字节验证)、USB 层、
> 相机式实时布局(顶栏4控制项+底部快门区+底导航)、图标文字持机朝向补偿旋转、
> 拍照MDT存MediaStore、MP4录像、媒体库、离线分析、PDF报告、任务解析、设置页、
> Android16沉浸(竖屏锁定+挖孔适配)。
> 第 10 轮(2026-09-09):按用户要求撤下演示模式合成热像图(无设备只显示
> "未检测到热像仪"占位),接真机+热像仪实测显示。
>
> 硬性约定(勿回退):① Activity 竖屏锁定 `portrait`,构图钉死手机竖屏框架,
> 屏显方向必须始终对应镜头方向;图标/文字用 `ui/DeviceOrientation`(加速度计,
> 真机约定 y=+9.81=0°)补偿旋转。② 源码全 UTF-8;python 读写必须显式
> `encoding='utf-8'`(本机默认 GBK,裸写会乱码)。③ 图标用双弧圆+直线/矩形。
>
> 下一步建议按 session_state.md「待办」推进:
> 1. 真机 USB 实测——温度绝对值标定(对 DDT 核对 counts→毫度);
> 2. 网络互连远程预览——UDP 广播自动发现 + 手动内网 IP,主机手机插热像仪、
> 局域网另一台手机远程实时预览(自定义轻量协议:控制通道 JSON + 图像流,
> 不走厂商 33596/33597);
> 3. 离线 MDT 温度解码(ConvertResponse2Temperature + 标定参数);
> 4. 厂商 12 调色板精确提取;5. 可见光 PIP 融合、云模块(Retrofit opt-in 预留)。
>
> 构建/提交:
> ```powershell
> cd C:\Project\MAG160C\android; $env:JAVA_HOME="C:\Tools\jdk-21"
> .\gradlew.bat :app:assembleDebug test --no-daemon
> git -C C:\Project\MAG160C add -A; git -C C:\Project\MAG160C commit -m "android: ..."
> ```
> 环境(2026-09-09 本机重装):JDK Temurin 21 `C:\Tools\jdk-21`、SDK `C:\Tools\android-sdk`
> (无模拟器/AVD)、Gradle 用工程 wrapper。注意:git 工作树里有大量与本任务无关的脏文件
> (`.tools/`、`IR_Camera_SDK/`、`csdk/`、`analysis/` 等),**不要提交它们**,只提交你的改动。
1. 真机 USB 实测:温度绝对值标定(对 DDT 核对 counts→毫度);
2. 网络互连远程预览的双机实测(清单第 16-24 步,见
`docs/android_app/real_device_checklist.md`);
3. 离线 MDT 温度解码(ConvertResponse2Temperature + 标定参数);
4. 云服务真实接口对接(当前仅 Retrofit 占位,默认关闭,需账号与接口文档);
5. 红热调色板(索引 11)精确表:需真机抓帧反推。
---
> 进度与验证记录见 `session_state.md`;官方渲染链逆向定案见
> `rendering_diff_phone_20261006.md`(39 轮,真机 A/B 逐环排除法)。
+3 -3
View File
@@ -42,7 +42,7 @@
已工作文件。
8. 参考文档(执行某阶段前必读对应部分):
- `analysis/magcx_official_flow.md`(协议权威)
- `docs/android_app/HANDOFF_DEVELOPMENT.md`(App 架构与约定)
- `docs/android_app/DEVELOPMENT.md`(App 架构与约定)
- `docs/android_app/reverse_apk_features.md` §4(MDT 容器)
---
@@ -318,7 +318,7 @@ class PipCameraEngine(val context, val textureView) :
### F1. 协议(`net/RemoteContract.kt`,纯 Kotlin,可单测)
- **发现**:UDP 47510。主机每 1000ms 向 `255.255.255.255:47510` 发一行 UTF-8 JSON:
`{"app":"mag160c-remote","role":"host","name":"<Build.MODEL>","tcp":47511,"serial":160043865}`
`{"app":"mag160c-remote","role":"host","name":"<Build.MODEL>","tcp":47511,"serial":<SN>}`
- **控制**:TCP 47511,换行分隔 JSON(UTF-8,单行 ≤4KB):
- 客户端→主机:`{"cmd":"hello","name":"..."}` → 回
`{"type":"welcome","w":160,"h":120,"fps":15,"serial":...}`
@@ -403,7 +403,7 @@ class PipCameraEngine(val context, val textureView) :
## Phase Z —— 收尾
1. `docs/android_app/session_state.md`:待办全部勾选/更新,追加本轮总结段。
2. `docs/android_app/HANDOFF_DEVELOPMENT.md`:§3 结构表加 `net/`、`cloud/`、
2. `docs/android_app/DEVELOPMENT.md`:§3 结构表加 `net/`、`cloud/`、
`ui/remote/`;§7 待办刷新。
3. 全量 `assembleDebug + test`;提交 APK;`git push origin main`。
4. 汇报:各阶段 commit 列表 + 用户手测清单位置。
+1 -1
View File
@@ -13,7 +13,7 @@
| # | 操作 | 预期 DebugLog 行(原文) | 通过标准 |
|---|------|--------------------------|----------|
| 1 | 插入热像仪,系统弹出 USB 权限对话框,点"允许" | `[usb] requestPermission: no device`(无设备时)/ `[usb] requesting permission (dialog)` → `[usb] permission result: true` | 授予权限后自动开始连接 |
| 2 | 等待连接(首次约 1~3 s,首次装机需下载标定文件时更久) | `[vm] connect()` → `[vm] permission ok, ddt <N> bytes, starting session` → `[session] state -> LINKING msg=null` → `[cmd] GetParameter1 write=4/4` → `[cmd] GetParameter1 resp=0x5BB5B55B len=60 head=...` → `[cmd] BasePara1: serial=160043865 devType=3 160x120 @15fps` | 五条全出现;serial/devType 与实际相机一致(devType=3 即 core160) |
| 2 | 等待连接(首次约 1~3 s,首次装机需下载标定文件时更久) | `[vm] connect()` → `[vm] permission ok, ddt <N> bytes, starting session` → `[session] state -> LINKING msg=null` → `[cmd] GetParameter1 write=4/4` → `[cmd] GetParameter1 resp=0x5BB5B55B len=60 head=...` → `[cmd] BasePara1: serial=<SN> devType=3 160x120 @15fps` | 五条全出现;serial/devType 与实际相机一致(devType=3 即 core160) |
| 3 | 同上(参数/标定握手) | `[cmd] GetParameter2 resp=0x5BB5B55C len=...` → `[cmd] GetCaliInfo resp=0x5BB5B55E len=...` → `[session] cali info: size=<size> date=<date>` → `[session] device lifetime=<ms>ms` | GetParameter2/GetCaliInfo 有响应;lifetime 非 -1(0 或正数均可,首次上电后很小正常) |
| 4 | 首次安装运行(无 cali 缓存) | `[session] first run on this host: downloading cali file <size> B (EP 0x84)` → `[session] cali download <p>%`(若干行)→ `[session] cali downloaded+cached: <product>.<serial>.<date> (<size> B)`;第二次运行改为 `[session] cali cache hit: <name>` + `[session] cali cache vs bundled DDT: identical`(或 `differ`,两者都不算失败) | 缓存命中或下载成功二者之一 |
| 5 | 等待 DDT 加载 + 出流 | `[session] ddt bytes <N>` → `[session] state -> STREAMING msg=null` → `[cmd] StartTransferImg write=4/4` → `[cmd] StartTransferImg ack=0x...` → `[stream] reader loop start: sync bulkTransfer (800 ms) + halt recovery` → `[stream] first reads [0] n=<n> head=...` → `[vm] first rendered frame -> UI` | 出现 `first rendered frame -> UI` 即画面已出(实时页显示热像,不再黑屏) |
@@ -422,7 +422,7 @@ PC 端 NUC 是逐字节相同的,所以嫌疑在"实时状态机采到的参
用户:"把'计数'噪声偏大修一下"。做法:在管线里临时插桩(DebugLog 打开、逐级打印
raw/参考/差值/NUC 的 mean/std/HF),真机跑一遍,把噪声预算算清楚,再看 A/B 差在哪里。
### 12.1 真机实测的噪声预算(设备 160043865,同一静止场景)
### 12.1 真机实测的噪声预算(设备 <SN>,同一静止场景)
```
[diag] ffcRefFrame mean=15084 std=3625 hfdx=1172 ×4 帧(快门帧)
@@ -600,7 +600,7 @@ JPEG 只能解释一部分:把我们那张(960×720 q95,202 KB)按 640×
→ 修好后我们**比官方更平滑**(官方因最近邻 4× 反而有 4 像素大块,见 x8 放大对照图)。
单测 119 全绿(`PhotoNucMappingTest` 更新为 160×120→960×720 的新策略)。
## 16. 「官方背景条纹更不明显」——逆向排除全部候选后,定位为**我们独有的逐行固定偏移**(2026-10-06 深夜,交接轮)
## 16. 「官方背景条纹更不明显」——逆向排除全部候选后,定位为**我们独有的逐行固定偏移**(2026-10-06 深夜,记录轮)
用户发了同场景双截图(官方 vs 我们,均为竖屏、12 px/传感器像素、同一调色板铁虹)并要求
"看逆向出来的代码是不是还漏了什么"。本轮做了两件事:把官方每帧链路逐条再对一遍(IDA 批量
@@ -656,7 +656,7 @@ JPEG 只能解释一部分:把我们那张(960×720 q95,202 KB)按 640×
分块统计(背景块):scene 比 0.95、1-8px 频带比 1.58、时间比 2.0 —— 我们多出来的
能量集中在 1~8px 频带且**逐帧可复现(固定)**。
### 16.3 结论与交接(下一步)
### 16.3 结论与下一步
- **缺陷**:我们的渲染里有一个官方没有的**逐传感器行固定偏移**(残余行 FPN)。
显示旋转 90° 后,传感器行=屏幕水平线 → 就是用户看到的"背景条纹"。
@@ -850,7 +850,7 @@ Kotlin 一致),与 App 自己 `copyNuc` 的 dump 对拍:corr=0.9996,仅
### 17.7 第三十九轮:GPU 画布假设被真机 A/B 推翻,真因 = 7×7 细节增强(2026-10-07)
按 §16.3/17.6 交接清单执行(首验 GPU 硬件画布 → 正式修复 → A/B 验收)。全部测量用
按 §16.3/17.6 待办清单执行(首验 GPU 硬件画布 → 正式修复 → A/B 验收)。全部测量用
39 轮新脚本 `final39.py/final39b/c/d/e.py`(口径:12px 网格 + UI mask + 弧长反演 +
鲁棒 std;暗区 = sensor 行 0..40 × 列 90..160;官方横屏直接同区;38 轮存档截图全部
可复现,官方 FULL 0.10/0.28、暗区 0.15 与 17.6 表逐位一致,DARK 对照里照片 JPEG
+1 -1
View File
@@ -99,7 +99,7 @@
## 7. 反编译复现命令
```powershell
$w='C:\Users\ZXC\AppData\Local\Temp\opencode\apkwork'
$w='%TEMP%\opencode\apkwork'
& 'C:\Tools\jadx\bin\jadx.bat' -d "$w\jadx_pro" --show-bad-code -j 8 "$w\orig\pro.apk"
# Ghidra: & 'C:\Tools\ghidra_12.1.2_PUBLIC\support\analyzeHeadless.bat' C:\Tools\ghidra_proj Mag160C -import <lib> -scriptPath C:\Tools\ghidra_scripts_user -postScript DumpJni.java
```
+12 -12
View File
@@ -26,7 +26,7 @@
- 协议/渲染/温度算法全部已逆向:analysis/protocol_spec.md + csdk/(逐像素验证过的官方管线)
- csdk 的 mag160c_render 无平台依赖:USB 帧 → 320×240 RGB24 + 探针测温(毫度)
- DDT 标定文件:可从设备经 0x6BB6B66D/E 下载(官方 prepareProcessImage 同款),仓库有
build-artifacts/mag160c_official.ddt(1.8MB,SN 160043865)
build-artifacts/mag160c_official.ddt(1.8MB,the calibration unit)
- MDT 文件格式:reverse_apk_features.md §4(152B Tail + 5 段布局 + ROI 256B 记录)
- 温度:毫度 int;MDT 解码走 ConvertResponse2Temperature + T2E(Revise) + CorrectTemperature
@@ -119,7 +119,7 @@
- [x] **顶栏适配挖孔屏**:`WindowInsets.safeDrawing.only(Top)` 顶部安全区 padding
- [x] 去掉 display-rotation 依赖(uiRotation/drawRotationDeg 已删,tapImage/probeToScreen
用固定 90° 映射)
- [x] 完整交接文档:docs/android_app/HANDOFF_DEVELOPMENT.md(含给新模型的读取提示词)
- [x] 开发指南:docs/android_app/DEVELOPMENT.md
## 用户反馈修复 第五轮(2026-09-07,布局约定最终定稿:构图钉死竖屏框架)
@@ -200,8 +200,8 @@
勿把演示模式加回来。
- [x] 工具链在本机重装并重建 APK(2026-09-09):JDK Temurin 21 `C:\Tools\jdk-21`、
SDK `C:\Tools\android-sdk`(platform 36 / build-tools 36.0.0 / platform-tools,许可已接受)、
Gradle 用工程 wrapper(8.14.3);交接文档旧路径 C:\Tools\gradle-8.14.3 / Zulu /
AppData SDK 属另一台开发机已失效(HANDOFF §2/§5 已改为本机路径)。
Gradle 用工程 wrapper(8.14.3);旧文档路径 C:\Tools\gradle-8.14.3 / Zulu /
AppData SDK 属另一台开发机已失效(DEVELOPMENT §2/§5 已改为本机路径)。
assembleDebug+test 全过;dex 抽查中文 UTF-8 正常、无 startDemo 残留;
build-artifacts/mag160c-app-debug.apk 已更新(11.8MB),可直接装真机。
- 待办不变(真机 USB 实测温度标定、网络互连远程预览、离线MDT温度解码、
@@ -252,7 +252,7 @@
## 用户反馈修复 第十三轮(2026-09-10,真机日志分析:端点静默 + 重枚举)
- [x] **用户回传 debug 日志**(vivo V2509A, Android16):相机识别/DDT/66b 响应全正常
(SN 160043865),但 66c/66f 响应超时、FFC/START 第一轮写失败(write=-1,
(the calibration unit),但 66c/66f 响应超时、FFC/START 第一轮写失败(write=-1,
端点疑似 halt)、流端点 19 秒 0 字节;00:51:10 相机重新枚举(权限再次弹出)
——相机在会话中途疑似断电/复位;且新旧两个 Activity 的会话同时在抢同一设备
(claimInterface 互相夺走)。
@@ -353,7 +353,7 @@
## 用户反馈修复 第十七轮(2026-09-10,根因确认:命令字节序反转)
- [x] **第 16 轮日志**:官方序列下 GetParameter1 仍唯一有响应(60B BasePara1 完整
解析成功:serial=160043865 devType=3=core160 160x120@15fps),66c/66f/673 全部
解析成功:serial=<SN> devType=3=core160 160x120@15fps),66c/66f/673 全部
800ms 超时 → 与"字节内容"相关而非流程顺序。
- [x] **根因**:`MagProtocol.cmd4/cmd8` 用 `ByteBuffer.putInt` —— **默认大端**!
官方 `GlobalFunc.intToByteArray` 是小端。66b=0x6BB6B66B 是回文数,大小端
@@ -441,7 +441,7 @@
单测 44 个全绿,含 **loopback 端到端测试**(真实 TCP:hello→welcome→
start→stream-start→5 帧逐字节往返→ffc→stop→stream-stop)与粘包/截断/
坏长度/重同步用例。debug+release 双构建通过。真机双机步骤写入清单第 16-24 步。
- [x] Phase Z(2026-09-10):收尾完成。docs 更新(本文件 + HANDOFF_DEVELOPMENT
- [x] Phase Z(2026-09-10):收尾完成。docs 更新(本文件 + DEVELOPMENT.md
§3 结构表加入 net/ cloud/ ui/remote/ 与 VendorPalettes/PipCameraView,
§7 状态与待办重写 + 禁改清单);全量 `assembleDebug test`(44 单测全绿)
+ `assembleRelease`(R8)通过;APK 已覆盖提交
@@ -491,7 +491,7 @@
## 用户反馈修复 第三十九轮(2026-10-07 凌晨,"官方背景条纹更不明显"结案:GPU 画布假设被真机 A/B 推翻,真因 = 我们开着官方从不开启的 7×7 细节增强)
按 38 轮交接清单执行(首验软件画布 → 正式修复 → A/B 验收 → NUC 域收尾)。
按 38 轮待办清单执行(首验软件画布 → 正式修复 → A/B 验收 → NUC 域收尾)。
完整数据与口径见 `rendering_diff_phone_20261006.md` §17.7。测量脚本
`%TEMP%\mag160c_re\final39*.py`(38 轮存档数字全部复现:官方 FULL 0.10/0.28、
暗区 0.15、照片 JPEG 0.25——口径互锁)。
@@ -525,7 +525,7 @@
## 用户反馈修复 第三十八轮(2026-10-07 凌晨,原始帧录制 + 逐级重放全链路定案 + 显示链与官方对齐)
按第三十七轮交接清单执行。用户中途解锁手机并配合真机操作。完整数据表与
按第三十七轮待办清单执行。用户中途解锁手机并配合真机操作。完整数据表与
排除清单见 `docs/android_app/rendering_diff_phone_20261006.md` §17。
- [x] **原始帧录制调试开关**:`usb/RawFrameRecorder`(单文件,帧头 magic/seq/
@@ -562,11 +562,11 @@
拉回我们 App:切官方前先 force-stop 我们,USB 弹窗用 `TAB×2+ENTER` 过
(横屏 input tap 坐标不可靠)。
## 用户反馈修复 第三十七轮(2026-10-06 深夜,"官方背景条纹更不明显"——逆向排除全部候选,定位为逐行固定偏移;交接轮)
## 用户反馈修复 第三十七轮(2026-10-06 深夜,"官方背景条纹更不明显"——逆向排除全部候选,定位为逐行固定偏移;记录轮)
用户:"很明显啊,官方背景里面的条纹就是要更不明显,你看看逆向出来的代码,是不是还漏掉了什么"。
本轮**只做了调查与测量,无代码改动**。完整证据与数据表见
`docs/android_app/rendering_diff_phone_20261006.md` §16,交接清单也在那里(16.3)。
`docs/android_app/rendering_diff_phone_20261006.md` §16,待办清单也在那里(16.3)。
- 逆向:官方每帧链路(CalibrationMain_RTV + BlindCompensation + TempRangeStat +
GrayEnlarge/HistDeRedundance)、内参(0x3808=1、0x380c=1、0x3804=baseLineAcc=4、
@@ -1574,6 +1574,6 @@ SDK 内部默认档——无法据此对齐具体档位,故本应用把它做
- 每完成一个阶段:更新本文件勾选 + git commit(不 push)。
- 中断恢复:读本文件 → 按"下一步"继续 → 环境检查命令:
```powershell
Test-Path C:\Users\ZXC\AppData\Local\Android\Sdk\ndk\<ver>
Test-Path %LOCALAPPDATA%\Android\Sdk\ndk\<ver>
Get-Command java; Get-Command gradle
```
+10 -10
View File
@@ -244,13 +244,13 @@ cd /c/Project/MAG160C
```bash
# ① 解包官方普通版的调色板预览图(交叉验证用)
mkdir -p /c/Users/zxc/AppData/Local/Temp/cxres && \
cd /c/Users/zxc/AppData/Local/Temp/cxres && \
mkdir -p %TEMP%/cxres && \
cd %TEMP%/cxres && \
"C:\Tools\jdk-21\bin\jar" xf "C:\Project\MAG160C\app\【普通版】MAG-Cx.apk" res/mipmap-hdpi-v4/
# ② 两文件编译
mkdir -p /c/Users/zxc/AppData/Local/Temp/regen_build && \
cd /c/Users/zxc/AppData/Local/Temp/regen_build && \
mkdir -p %TEMP%/regen_build && \
cd %TEMP%/regen_build && \
cp "C:\Project\MAG160C\analysis\tools\PalIdentify.java" . && \
cp "C:\Project\MAG160C\analysis\tools\PalExport2.java" . && \
"C:\Tools\jdk-21\bin\javac" -d out PalIdentify.java PalExport2.java
@@ -258,15 +258,15 @@ cp "C:\Project\MAG160C\analysis\tools\PalExport2.java" . && \
# ③ 重新生成(输出到临时目录,勿覆盖仓库)
"C:\Tools\jdk-21\bin\java" -cp out PalExport2 \
"C:\Project\MAG160C\android\app\src\main\kotlin\com\mag160c\thermal\core\OfficialTables.kt" \
"C:\Users\zxc\AppData\Local\Temp\cxres\res\mipmap-hdpi-v4" \
"C:\Users\zxc\AppData\Local\Temp\regen_core" \
"C:\Users\zxc\AppData\Local\Temp\regen_out"
"%TEMP%\cxres\res\mipmap-hdpi-v4" \
"%TEMP%\regen_core" \
"%TEMP%\regen_out"
# 期望最后一行:iron_bow vs OfficialTables anchor: 256/256
# ④ 与仓库文件逐字节比对(两条都必须为空)
diff "C:\Users\zxc\AppData\Local\Temp\regen_core\VendorPalettes.kt" \
diff "%TEMP%\regen_core\VendorPalettes.kt" \
"C:\Project\MAG160C\android\app\src\main\kotlin\com\mag160c\thermal\core\VendorPalettes.kt"
diff "C:\Users\zxc\AppData\Local\Temp\regen_out\palette_candidates.json" \
diff "%TEMP%\regen_out\palette_candidates.json" \
"C:\Project\MAG160C\analysis\sdk_re\android_app\palette_candidates.json"
```
@@ -419,5 +419,5 @@ unzip -p build-artifacts/mag160c-app-debug.apk 'classes*.dex' | grep -ac '正在
| node | 未安装 |
| 模拟器 / 连接设备 | 无(`adb devices` 为空,SDK 无 emulator 组件) |
| `analysis/tools/PalExport2.java` | **不能单文件直跑**:依赖 `PalIdentify.java` 的 `PalBody`,须两文件一起 `javac -d out` |
| Git Bash 的 `/tmp` 路径 | Windows 版 java **不认**,必须写 `C:\Users\zxc\AppData\Local\Temp\...` |
| Git Bash 的 `/tmp` 路径 | Windows 版 java **不认**,必须写 `%TEMP%\...` |
| `analysis/tools/CheckStrings.java` | 可单文件直跑(无外部依赖) |
+11 -11
View File
@@ -311,7 +311,7 @@
|---|---|---|
| 消息无强制格式 | `git log -1 --format=%B` | 证实 |
| 内容仅为文档/清单/APK | `git show --stat`:3 份文档 + APK,**外加 Manifest(+3 条 uses-feature)** | **证伪**(见 FIX-5) |
| 文档更新到位 | HANDOFF §3 含 `ui/remote/`、`net/`、`cloud/CloudApi.kt`;session_state 勾选 A–Z 并追加总结;execution_plan 顶部加执行状态 | 证实 |
| 文档更新到位 | DEVELOPMENT §3 含 `ui/remote/`、`net/`、`cloud/CloudApi.kt`;session_state 勾选 A–Z 并追加总结;execution_plan 顶部加执行状态 | 证实 |
| 全量构建 + 提交 APK,且不 push | 重跑 debug+release+test 成功;`origin/main` 仍 `087e15c` | 证实 |
| 提交的 APK 与 HEAD 一致 | 对已提交 APK 核验:`screenOrientation=1`、camera 系列 not-required、INTERNET/CAMERA 已声明、dex 内含 `画中画`/`正在扫描局域网主机`/`云同步`(E/D/F 代码确在包内)。APK 字节不可复现(时间戳),故以内容核验替代字节比对 | 证实(以内容为准) |
@@ -384,20 +384,20 @@ cd /c/Project/MAG160C
analysis/sdk_re/android_app/bin/libcxsdk.so csdk/src/mag160c_official_palette256.h
# 期望:三种编码全部 not found;[A] 段自校准 detected 1 candidate
mkdir -p /c/Users/zxc/AppData/Local/Temp/regen_build && \
cd /c/Users/zxc/AppData/Local/Temp/regen_build && \
mkdir -p %TEMP%/regen_build && \
cd %TEMP%/regen_build && \
cp "C:\Project\MAG160C\analysis\tools\PalIdentify.java" . && \
cp "C:\Project\MAG160C\analysis\tools\PalExport2.java" . && \
"C:\Tools\jdk-21\bin\javac" -d out PalIdentify.java PalExport2.java && \
"C:\Tools\jdk-21\bin\java" -cp out PalExport2 \
"C:\Project\MAG160C\android\app\src\main\kotlin\com\mag160c\thermal\core\OfficialTables.kt" \
"C:\Users\zxc\AppData\Local\Temp\cxres\res\mipmap-hdpi-v4" \
"C:\Users\zxc\AppData\Local\Temp\regen_core" \
"C:\Users\zxc\AppData\Local\Temp\regen_out"
"%TEMP%\cxres\res\mipmap-hdpi-v4" \
"%TEMP%\regen_core" \
"%TEMP%\regen_out"
# 期望末行:iron_bow vs OfficialTables anchor: 256/256
diff "C:\Users\zxc\AppData\Local\Temp\regen_core\VendorPalettes.kt" \
diff "%TEMP%\regen_core\VendorPalettes.kt" \
"C:\Project\MAG160C\android\app\src\main\kotlin\com\mag160c\thermal\core\VendorPalettes.kt"
diff "C:\Users\zxc\AppData\Local\Temp\regen_out\palette_candidates.json" \
diff "%TEMP%\regen_out\palette_candidates.json" \
"C:\Project\MAG160C\analysis\sdk_re\android_app\palette_candidates.json"
# 期望:两条 diff 均为空
```
@@ -407,13 +407,13 @@ diff "C:\Users\zxc\AppData\Local\Temp\regen_out\palette_candidates.json" \
无 gcc / 无 kotlinc,用 Gradle 缓存内的编译器:
```bash
KC=/c/Users/zxc/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin
KX=/c/Users/zxc/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx
KC=%USERPROFILE%/\.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin
KX=%USERPROFILE%/\.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx
STDLIB=$KC/kotlin-stdlib/2.2.0/fdfc65fbc42fda253a26f61dac3c0aca335fae96/kotlin-stdlib-2.2.0.jar
COMPILER=$KC/kotlin-compiler-embeddable/2.2.0/8cfa2b049a4006d94474296df4abd9b50f288821/kotlin-compiler-embeddable-2.2.0.jar
SCRIPT=$KC/kotlin-script-runtime/2.2.0/87c92e866fcd68680966a3005a2992e1ab8ec6ad/kotlin-script-runtime-2.2.0.jar
CORO=$KX/kotlinx-coroutines-core-jvm/1.8.0/ac1dc37a30a93150b704022f8d895ee1bd3a36b3/kotlinx-coroutines-core-jvm-1.8.0.jar
ANNOT=/c/Users/zxc/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/23.0.0/8cc20c07506ec18e0834947b84a864bfc094484e/annotations-23.0.0.jar
ANNOT=%USERPROFILE%/\.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/23.0.0/8cc20c07506ec18e0834947b84a864bfc094484e/annotations-23.0.0.jar
# 编译(示例:Phase F;Phase B 同理,只换成 core/media 源码 + 自己的断言)
java -cp "$COMPILER;$STDLIB;$SCRIPT;$CORO;$ANNOT" org.jetbrains.kotlin.cli.jvm.K2JVMCompiler \