M5 设计验证:file:// 存储共享真机验证通过 + 文档定稿

验证(临时 VerifyStoragePage 真机跑后已回退):
- localStorage:两个不同 file:// 路径(lsA/lsB)+setPathAllowingUniversalAccess 跨页共享 ✓(lsB 读到 lsA 写的值)
- cookie:file:// 不支持 WebView cookie;原 Android cookie 全在 native HTTP 层(Volley),WebView 未开 file-scheme cookie,
  H5 不用 WebView cookie → 非缺口;http(s) cookie 由 WebCookieManager 应用级全局共享
- 结论:采用 file:// + setPathAllowingUniversalAccess + WebCookieManager(全局),无需自定义协议

文档:
- 框架新增 §7.5 双 Web 大厅/子游戏架构定稿(结构隔离/激活协议四联动/onInactive 不停JS的平台限制与 appservice 正解/存储验证结论/状态机/改造清单)
- 01_WBS:M5 标记"设计就绪",记存储验证通过
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-25 23:23:10 +08:00
parent d196b13e39
commit f190fe69e3
2 changed files with 35 additions and 1 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
| **M2** 容器 + 启动 + 资源 | ☑ 完成 | 13 任务全完成;**V2 真机通过(R-02 关闭)**、VersionResolver 单测覆盖 81.8%T-M2-12 机制已验证(真实远程大厅待服务端可用时终验) |
| **M3** 本期能力 | ◐ 进行中 | 16/17 完成(15 Provider+前后台)T-M3-06 NavProvider 随 M4 完成;余 T-M3-17 真机回归(录音 prepareaudio 待服务端) |
| **M4** 通用网页容器 | ☑ 完成 | GenericWebContainer+SettingsProxy(6方法)+getWebdata/gamebackkeydown/backgameData 直调+101回传+返回键;子游戏切换(路径A)/打开通用容器(路径B) |
| **M5** 性能与加固 | ☐ 未开始 | — |
| **M5** 性能与加固 | ◐ 设计就绪 | 双 Web 大厅/子游戏架构定稿(框架 §7.5);**存储共享真机验证通过**file:// localStorage 跨路径共享;cookie 走 WebCookieManager 全局/H5 不用 WebView cookie);待实现 |
| **M6** 暂缓能力集成 | ☐ 未开始 | 按需 |
**M0 任务明细(全部 ☑)**
@@ -564,6 +564,40 @@ H5 以 `file://` 加载并请求本地资源时,ArkWeb 默认按 CORS 拦截
- **实现 API**:运行时 `window.Window.setPreferredOrientation(orientation: window.Orientation)` 动态切换,`window.Orientation``LANDSCAPE` / `PORTRAIT`(编码前用 `devecocli docs` 核对签名)。
- **要点**`module.json5``auto_rotation_landscape` 提供"横屏内跟随传感器旋转(不进竖屏)",运行时 `setPreferredOrientation` 提供"H5 显式切换"——二者叠加既满足横屏项目定位,又守住 H5 零改动。
### 7.5 双 Web 大厅/子游戏架构(M5 定稿,2026-06-25 验证通过)
> 复刻原 Android 双 Activity 语义(webviewActivity 大厅 + NewwebviewActivity 子游戏,靠 Activity 生命周期 onPause/onResume 暂停/恢复),在鸿蒙用**单 Ability + 单页内两个 Web 组件**实现——更轻、切换更快、可离屏预热。M2/M4 的单 WebView `loadUrl` 切换是过渡实现,M5 替换之。
**结构**`BridgeGameContainer``Stack { 大厅Web(常驻) ; if(子游戏!=null) 子游戏Web }`,由 **WebSlotManager** 持两 slot、维护 activeSlot、执行激活协议。每个 slot = 独立 `WebviewController + BridgeController + buildCapabilities()`。子游戏 `SwitchOverGameData` 创建、`backgameData` 销毁(不保活)。大厅常驻无需 NodeController(两 Web 同在一页)。
**需求①——大厅/子游戏接口不串(结构隔离)**:每个 Web 一套独立桥 + 能力实例,`BridgeController#L` 只 runJavaScript 到大厅 Web、`#S` 只到子游戏 Web,**物理不可能串**。唯一共享单例(`WeChatApi`)与 EventBus 导航事件由 WebSlotManager **路由到 activeSlot**
**需求②——同时只有一个激活**(激活=联网+渲染+声音+桥接口可执行)。激活协议四联动:
| 维度 | 激活端 | 非激活端 |
|---|---|---|
| 渲染/动画/定位 | `web.onActive()` + 显示 | `web.onInactive()` + 隐藏 |
| 桥接口 | `bridge.setActive(true)` | `bridge.setActive(false)`:入站忽略、出站抑制 |
| 原生能力监听/播放 | `registrar.forEachForeground()` | `registrar.forEachBackground()`:停传感器/定位/网络监听、停音频 |
| H5 自身联网/心跳/声音 | `callHandler('appservice','1')` | `callHandler('appservice','2')`H5 按契约自行进入后台态 |
> ⚠ **平台限制与正解**ArkWeb `onInactive()` 暂停动画/定位但**不暂停 JS**;能停 JS 定时器的 `pauseAllTimers()` 是**全局**(会停两个 Web,不可用于单 Web)。即鸿蒙**没有"只冻结一个 Web 的 JS/网络"的原生开关**(比 Android WebView.onPause 弱)。正解:原生侧停掉能停的(渲染/能力/桥),**H5 侧用契约现成的 `appservice('2')` 自停网络/声音**——与原 Android 一致、H5 零改动。
**需求③——cookie + localStorage 共享(已真机验证)**
- **localStorage**:✅ **已验证共享**——两个不同 file:// 路径(`filesDir/tsgames/lsA``/lsB`+ `setPathAllowingUniversalAccess([filesDir/tsgames])`,一页写、另一页读到同值。故**沿用 file:// 主选**即满足。
- **cookie**file:// 页面不支持 WebView cookiecookie 绑定 http(s) scheme);但原 Android 的 cookie 全在 native HTTP 层(Volley/java.net.CookieManager),**WebView 从未开 file-scheme cookieH5 不用 WebView cookie**——故非需求缺口。若未来 H5 在 http(s) 用 cookie`WebCookieManager` 为**应用级全局单例**(所有 Web 组件共享)自动满足。
- 结论:**采用 file:// + setPathAllowingUniversalAccess + WebCookieManager(全局)**,无需自定义协议。
**激活状态机**WebSlotManager):
```
进子游戏: deactivate(大厅)[appservice'2'→onInactive→forEachBackground→setActive(false)→隐藏]
→ 注入子游戏 app_data(launchtype'1') → 建子游戏 slot → activate(子游戏)[显示→onActive→forEachForeground→setActive(true)→100%时 appservice'1'+setPostUrl]
返回大厅: destroy(子游戏)[forEachBackground→bridge.dispose→销毁 Web] → activate(大厅)[显示→onActive→forEachForeground→setActive(true)→appservice'1'+getWebdata(data)]
App 前后台: 只对 activeSlot 下发 appservice
```
**改造清单**:新增 `WebSlotManager`(entry)`BridgeController``setActive()``BridgeGameContainer` 改 Stack 双 Web、SWITCH_GAME/BACK_GAME 走 SlotManagerProvider 落实 `onForeground/onBackground`Shake/Location/Network 停起监听、Audio 停起播放);`WeChatApi` resp 路由到 activeSlot。
---
## 8. 启动编排与配置/资源子系统