android: LAN remote preview (UDP discovery + raw-frame TCP stream, client-side rendering)

This commit is contained in:
ZXCLI
2026-09-11 00:54:13 +08:00
parent f8b3200464
commit 512508e629
18 changed files with 2113 additions and 15 deletions
+21 -1
View File
@@ -28,8 +28,28 @@
| 14 | 拖动 PIP 小窗到其它角落;单击小窗(循环 96/128/160dp);双击小窗关闭 | `[pip] released`(双击关闭时) | 小窗跟手移动且不出界;单击在三档宽度间循环;双击后小窗消失,顶栏恢复"画中画"未开启态;日志有 `released` |
| 15 | PIP 开启时按 Home 回到桌面再返回 | `[pip] released`(进入后台时) | 返回后若 PIP 仍为开启态,画面重新出现(重新 open);无崩溃 |
## 相机(PIP)失败时的表现(设计如此,不算 bug
## 远程预览(Phase F,需要两台设备
两台安卓设备(或一台手机 + 一个模拟器)连**同一个 Wi-Fi**。以下称 A=插热像仪的
主机手机,B=远程查看的手机。
| # | 操作 | 预期 DebugLog 行(原文) | 通过标准 |
|---|------|--------------------------|----------|
| 16 | A:插热像仪,确认实时页已出图(清单前 6 步) | `[session] state -> STREAMING` | A 本地画面正常 |
| 17 | A:设置页 → "远程预览服务端"(点一下) | `[remote] host started (name=<机型> serial=0)` | 该行文案变为"已开启" |
| 18 | A:若第 17 步弹"先连接热像仪" | (无日志) | 说明 USB 会话不活跃:先回到实时页确认出流 |
| 19 | B:设置页 → "远程预览客户端" → "查找主机" | (B 端)列表出现 A 的主机名 | 10 秒内列出 A(卡片显示 `<主机名>``<IP>:47511`);未列出可用"手动添加"填 A 的 IP |
| 20 | B:点该卡片(或手动 IP 后点"连接" | A 端:`[remote] client connected from <B的IP>`B 端:`[remote] client connected to <A的IP>:47511``[remote] line: {"type":"welcome",...}``[remote] line: {"type":"stream-start"}``[remote] first remote frame` | B 显示 A 的热像实时画面(同一构图:竖屏 3:4、顶栏 4 项、右侧色标条) |
| 21 | B:顶栏点变倍/追踪/调色板 | (无日志,全部本地) | 立即生效、无卡顿(调色板/变倍不下发到 A) |
| 22 | B:顶栏点 FFC | A 端出现一次快门校正;B 画面随之更新 | FFC 经 A 的热像仪执行 |
| 23 | B:点底部红色"断开"圆钮 | A 端:`[remote] client <IP> disconnected (frames=<N>)` | B 返回主机列表并弹出"已断开"提示;A 服务端保持"已开启"待重连 |
| 24 | A:设置页再点"远程预览服务端"关闭 | `[remote] host stopped` | 文案变回"已关闭";A 本地热像画面不受影响 |
远程预览失败时的表现(设计如此):连不上主机时 B 显示"无法连接主机"并返回列表;
中途断网/主机退出时 B 显示"连接已断开";A 端相机与本地画面**始终不受网络影响**;
日志中 `frames=…` 每 300 帧记一次。
## 相机(PIP)失败时的表现(设计如此,不算 bug)
PIP 的相机是可选功能,任何相机异常都只记日志并关闭小窗,**不影响热像主画面**:
- 无相机硬件 / 权限被拒 → `[pip] no camera available` / `[pip] camera permission not granted`
+17 -1
View File
@@ -423,7 +423,23 @@
拖动/单击换档/双击关闭;PIP 关闭、离页、ON_STOP 三处释放相机;
运行时权限用 rememberLauncherForActivityResult。真机项已写入
real_device_checklist.md(第 13-15 步 + 失败表现)。APK 已更新。
- [ ] Phase F:网络互连远程预览
- [x] Phase F(2026-09-10):网络互连远程预览。net/RemoteContract.kt(协议常量+
手写扁平 JSON 助手,**无 Android 依赖**便于 JVM 单测 + FramePacketReader
流式重组);net/RemoteHost.ktUDP 47510 每秒广播 + TCP 47511 单客户端;
**单一协程拥有 socket**,控制回复与帧记录不会交错;帧队列 DROP_OLDEST 不拖慢
相机);net/RemoteClient.ktdiscover 去重 3sconnect 行模式→收到
stream-start 后切帧模式,同一 chunk 内混合也能正确切分;10s 无数据判死);
IrSession 加 rawHook(与 recorderHook 并列);LiveViewModel 接 rawHook →
remoteHost.offerFrame + setRemoteHostEnabled(需活跃 USB 会话);
设置页新增"远程预览服务端"/"远程预览客户端"两行(前置校验弹"先连接热像仪");
ui/remote/ 三文件:RemoteClientListScreen56dp 标题栏/64dp 卡片/重新扫描/
手动添加/空态)、RemoteViewerViewModel(本地 RenderPipeline + 内置 DDT
渲染)、RemoteViewerScreen + RemoteRendererHost(与 LiveRenderer 同构图,
未改冻结文件)、AppRoot 加两个全屏目的地。Manifest 加 INTERNET。
单测 44 个全绿,含 **loopback 端到端测试**(真实 TCPhello→welcome→
start→stream-start→5 帧逐字节往返→ffc→stop→stream-stop)与粘包/截断/
坏长度/重同步用例。debug+release 双构建通过。真机双机步骤写入清单第 16-24 步。
- [ ] Phase Z:收尾(文档/全量构建/APK)
## 里程碑日志