Files
youle_app_ohos/feature_capabilities/src/main/ets/providers/NavProvider.ets
T
lanterngamescnandClaude Opus 4.8 e75f567948 修复 SwitchOverGameData 解析失败致无法跳转子游戏
H5 对 SwitchOverGameData 的 data 字段直接传 JSON 对象(如 {webtype:3,...})。
Android org.json getString 会把嵌套对象强制转为 JSON 字符串再交 handler JSON.parse;
而 ArkTS JSON.parse 保留为对象,handler 再 JSON.parse(对象) 得到 "[object Object]"
→ Invalid Token、解析失败、不发 SWITCH_GAME、不跳转。

- MessageCodec.toArray:新增 coerceToString,对 data/responseData 复刻 org.json
  getString 语义(对象/数组→紧凑 JSON 串,数字/布尔→字符串)。
- NavProvider:webtype 统一 String() 化,避免下游 `webtype !== '2'` 对数字恒真
  把竖屏子游戏错误强制横屏。

对应契约 §11.1 路径A、§2.4 Message。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 01:55:40 +08:00

80 lines
3.5 KiB
Plaintext
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.
/**
* 导航能力(契约 §8.8/§8.9/§8.10/§11T-M3-06)。
* - OpenurlTitleData:打开通用网页容器(路径 B,§11.2),关闭回传 → 上层 getWebdata。
* - SwitchOverGameData:容器内切换子游戏(路径 A,§11.1),同容器 loadUrl。
* - getGameinstall:同步返回子游戏资源是否就绪("1"/"0")。
* - backgameData:子游戏带数据返回大厅。
*
* 容器持 pathStack/WebviewController,本 Provider 经 EventBus 发导航事件,由 BridgeGameContainer 执行。
*/
import { common } from '@kit.AbilityKit';
import { FileSystem } from 'platform';
import { ResourceManager, ConfigManager } from 'domain_resource';
import { BridgeController } from 'feature_bridge';
import { InboundHandlers, OpenUrlTitleDataReq, SwitchOverGameReq } from 'contracts';
import { EventBus, NavEvents, OpenGenericWebPayload, SwitchGamePayload, BackGamePayload, Logger } from 'common';
import { CapabilityContext, CapabilityProvider } from '../core/CapabilityProvider';
export class NavProvider implements CapabilityProvider {
readonly name: string = 'nav';
private readonly log: Logger = Logger.tag('NavProvider');
private context: common.UIAbilityContext | undefined = undefined;
private config: ConfigManager | undefined = undefined;
register(bridge: BridgeController, ctx: CapabilityContext): void {
this.context = ctx.uiAbilityContext;
this.config = ctx.config;
bridge.registerHandler(InboundHandlers.OpenUrlTitleData, (data: string, _cb: (resp: string) => void) => {
this.openUrl(data);
});
bridge.registerHandler(InboundHandlers.SwitchOverGameData, (data: string, _cb: (resp: string) => void) => {
this.switchGame(data);
});
bridge.registerHandler(InboundHandlers.GetGameInstall, (data: string, cb: (resp: string) => void) => {
cb(this.isGameInstalled(data) ? '1' : '0');
});
bridge.registerHandler(InboundHandlers.BackGameData, (data: string, _cb: (resp: string) => void) => {
const payload: BackGamePayload = { data };
EventBus.emit(NavEvents.BACK_GAME, payload);
});
}
private openUrl(data: string): void {
let req: OpenUrlTitleDataReq;
try {
req = JSON.parse(data) as OpenUrlTitleDataReq;
} catch (e) {
this.log.w(`OpenurlTitleData bad json: ${(e as Error).message}`);
return;
}
const payload: OpenGenericWebPayload = { url: req.url, title: req.title, data: req.data, orientation: '' };
EventBus.emit(NavEvents.OPEN_GENERIC_WEB, payload);
}
private switchGame(data: string): void {
let req: SwitchOverGameReq;
try {
req = JSON.parse(data) as SwitchOverGameReq;
} catch (e) {
this.log.w(`SwitchOverGameData bad json: ${(e as Error).message}`);
return;
}
// webtype 契约为 "2"竖/"3"横,但 H5 可能发数字(如 3)。统一转字符串,
// 否则下游 `webtype !== '2'` 的严格比较对数字恒为真,会把竖屏子游戏错误强制横屏。
const payload: SwitchGamePayload = { webtype: String(req.webtype), dir: req.Gamedirectory, data: req.data };
EventBus.emit(NavEvents.SWITCH_GAME, payload);
}
/** 子游戏资源是否就绪:<解压根>/<dir>/index.html 存在。 */
private isGameInstalled(dir: string): boolean {
const ctx = this.context;
const cfg = this.config;
if (ctx === undefined || cfg === undefined || dir === '') {
return false;
}
const urlpath: string = `${ResourceManager.resourceRoot(ctx)}/${cfg.getLocal().gamedir}`;
return FileSystem.exists(`${urlpath}/${dir}/index.html`);
}
}