修正 app_data.js 三处字段与 Android 不一致(H5 零改动)

§4.2 配置项接口逻辑审计发现 app_data.js 注入有三处偏离原 Android
inith5data(weclomeactivity1/NewwebviewActivity 两处实测一致):

1. app_version:Android 硬编码 `var app_version=1;`(数字常量,"初始化框架
   加载方式"标志,非资源版本);原实现误用 res.localVersion()(如 "261" 且成
   字符串)。改为固定数字字面量 1。契约文档 §6 此处亦误录为"version.xml 的
   version",一并纠正。
2. app_gamename:Android 取 getAllFilename("gamestart")(即 'gamehall');原
   实现误用 version.xml 的 <game name>(如"友乐游戏")。改为 config.gamestart。
3. app_getwifisignalLevel:Android 硬编码 `=1`(数字);原实现为字符串 '0'。
   改为固定数字字面量 1。

buildValues 签名随之简化为 (config, launchtype),去掉不再需要的 version/
gameName 入参;大厅(StartupOrchestrator '0')、子游戏(BridgeGameContainer '1')
两调用点同步更新。buildJs 对 app_version/app_getwifisignalLevel 输出数字字面量
(无引号),其余字符串字段保持引号,逐字对齐 Android。

其余审计结论一致:11 个本地配置键读取一致(servertype/gameserver 契约标
"无代码读取"已正确省略);桥 handler getmarketname→market、getOther→other、
getothername→按名取配置(lookupConfig 全键 + 未知返回'')均与 Android getAllFilename
对齐。真机回归:大厅 V1.261 正常加载渲染。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-27 09:31:22 +08:00
co-authored by Claude Opus 4.8
parent 600378f723
commit d335a589b6
4 changed files with 33 additions and 24 deletions
@@ -406,22 +406,24 @@ gameconfig 值 = "tsgames.daoqi88.cn-config-update_jsonv2" // 生产端点
```
文件内容为一组全局 JS 变量声明(H5 直接引用),字段如下:
| 全局变量 | 来源 | 含义 |
| 全局变量 | 来源 | 含义 / 输出形态 |
|---|---|---|
| `app_version` | version.xml 的 version | 资源版本号 |
| `app_version` | **固定数字 `1`** | "初始化框架加载方式"标志(Android 硬编码 `var app_version=1;`,**非**资源版本号);**数字字面量、无引号** |
| `app_gameconfig` | `gameconfig` 配置 | 远程配置地址标识 |
| `app_gamedir` | `gamedir` 配置 | 资源父目录名 |
| `app_gamestart` | `gamestart` 配置 | 游戏目录名(gamehall |
| `app_agent` | `agent` 配置 | 代理商 ID |
| `app_appversion` | `appversion` 配置 | App 版本号 |
| `app_market` | `market` 配置 | 市场 ID |
| `app_appversion` | `appversion` 配置 | App 版本号(字符串) |
| `app_market` | `market` 配置 | 市场 ID(字符串) |
| `app_channel` | `channel` 配置 | 渠道 ID |
| `app_invitationcode` | `tuiguang` 配置 | 推广/邀请码 |
| `app_Launchtype` | 固定 `'0'`(大厅) | 启动类型 |
| `app_gamename` | 资源/配置 | 游戏名 |
| `app_getwifisignalLevel` | 运行时 | WiFi 信号等级初值 |
| `app_invitationcode` | `tuiguang` 配置 | 推广/邀请码(空则 `''` |
| `app_Launchtype` | 固定 `'0'`(大厅)/ `'1'`(子游戏) | 启动类型(字符串) |
| `app_gamename` | **`gamestart` 配置**getAllFilename("gamestart"),即 `gamehall`) | 游戏名;**注意:源是 gamestart 配置值,非 version.xml 的 `<game name>`** |
| `app_getwifisignalLevel` | **固定数字 `1`** | WiFi 信号等级初值(Android 硬编码 `var app_getwifisignalLevel=1;`);**数字字面量、无引号** |
> 新平台只需在加载大厅页面前,保证大厅目录下存在等价的 `app_data.js`(同名全局变量、同含义取值)。内部如何生成文件不限。
>
> ⚠ **纠错(以 Android `inith5data` 实测为准)**:本表早期把 `app_version` 误录为"version.xml 的 version(资源版本号)"`app_gamename` 误录为"资源/配置"`app_getwifisignalLevel` 误录为"运行时"。**实际**`app_version` 与 `app_getwifisignalLevel` 均为 Android 硬编码常量 `1`(数字字面量,无引号),`app_gamename` 取 `gamestart` 配置值(非 version.xml name)。大厅(`weclomeactivity1`)与子游戏(`NewwebviewActivity`)两处 `inith5data` 字段完全一致,仅 `app_Launchtype` 分别为 `'0'`/`'1'`。
---
@@ -11,9 +11,9 @@ import { FileSystem } from 'platform';
import { Logger } from 'common';
import { AppConfig } from '../config/AppConfig';
/** app_data.js 全局变量取值(§6)。 */
/** app_data.js 全局变量取值(§6)。逐字对齐 Android weclomeactivity1/NewwebviewActivity.inith5data。 */
export interface AppDataValues {
/** version.xml 的 version(资源版本号)。 */
/** 固定 '1'Android 硬编码 `var app_version=1;`"初始化框架加载方式"标志,**非**资源版本号;输出为数字字面量)。 */
app_version: string;
/** gameconfig 配置(远程配置地址标识)。 */
app_gameconfig: string;
@@ -31,21 +31,25 @@ export interface AppDataValues {
app_channel: string;
/** tuiguang 配置(推广/邀请码)。 */
app_invitationcode: string;
/** 固定 '0'(大厅启动类型)。 */
/** 启动类型:大厅 '0' / 子游戏 '1'。 */
app_Launchtype: string;
/** 游戏名。 */
/** 游戏名Android 取 `gamestart` 配置(getAllFilename("gamestart"),即 'gamehall'),**非** version.xml name。 */
app_gamename: string;
/** WiFi 信号等级初值。 */
/** 固定 '1'Android 硬编码 `var app_getwifisignalLevel=1;`;输出为数字字面量)。 */
app_getwifisignalLevel: string;
}
export class AppDataInjector {
private static readonly log: Logger = Logger.tag('AppDataInjector');
/** 由本地配置 + 资源版本 + 启动类型 + 游戏名构建 app_data 值(大厅 launchtype='0' / 子游戏 '1')。 */
static buildValues(config: AppConfig, version: string, launchtype: string, gameName: string = ''): AppDataValues {
/**
* 由本地配置 + 启动类型构建 app_data 值(大厅 launchtype='0' / 子游戏 '1')。
* 🔴 逐字对齐 Androidapp_version / app_getwifisignalLevel 为硬编码常量 1(非资源版本/非运行时探测);
* app_gamename 取 `gamestart` 配置(非 version.xml name)。其余字段来自本地配置同名项。
*/
static buildValues(config: AppConfig, launchtype: string): AppDataValues {
return {
app_version: version,
app_version: '1',
app_gameconfig: config.gameconfig,
app_gamedir: config.gamedir,
app_gamestart: config.gamestart,
@@ -55,16 +59,19 @@ export class AppDataInjector {
app_channel: config.channel,
app_invitationcode: config.tuiguang,
app_Launchtype: launchtype,
// app_gamename 源为 version.xml 的子 <game name>ResourceManager.localGameName 提供)
app_gamename: gameName,
app_getwifisignalLevel: '0',
app_gamename: config.gamestart,
app_getwifisignalLevel: '1',
};
}
/** 生成 app_data.js 文本(一组全局 var 声明)。 */
/**
* 生成 app_data.js 文本(一组全局 var 声明)。
* app_version / app_getwifisignalLevel 输出为**数字字面量**(无引号,对齐 Android `var app_version=1;`);
* 其余为字符串字面量(JSON.stringify 加引号,等价 Android 的单引号字符串)。
*/
static buildJs(v: AppDataValues): string {
const lines: string[] = [
`var app_version=${JSON.stringify(v.app_version)};`,
`var app_version=${v.app_version};`,
`var app_gameconfig=${JSON.stringify(v.app_gameconfig)};`,
`var app_gamedir=${JSON.stringify(v.app_gamedir)};`,
`var app_gamestart=${JSON.stringify(v.app_gamestart)};`,
@@ -75,7 +82,7 @@ export class AppDataInjector {
`var app_invitationcode=${JSON.stringify(v.app_invitationcode)};`,
`var app_Launchtype=${JSON.stringify(v.app_Launchtype)};`,
`var app_gamename=${JSON.stringify(v.app_gamename)};`,
`var app_getwifisignalLevel=${JSON.stringify(v.app_getwifisignalLevel)};`,
`var app_getwifisignalLevel=${v.app_getwifisignalLevel};`,
];
return lines.join('\n') + '\n';
}
@@ -155,7 +155,7 @@ export class StartupOrchestrator {
// 6) 注入 app_data.js(务必在进大厅之前)。大厅 launchtype='0'
this.stage(StartupStage.INJECT_APP_DATA, 92);
const values: AppDataValues = AppDataInjector.buildValues(local, `${resource.localVersion()}`, '0', resource.localGameName());
const values: AppDataValues = AppDataInjector.buildValues(local, '0');
AppDataInjector.inject(resource.paths().gameDir, values);
// 7) 进大厅
@@ -183,7 +183,7 @@ export struct BridgeGameContainer {
}
const subDir: string = `${res.paths().urlpath}/${d.dir}`;
// 子游戏目录自带 app_data.jsH5 同步读),launchtype='1'
const values: AppDataValues = AppDataInjector.buildValues(cfg.getLocal(), `${res.localVersion()}`, '1', res.localGameName());
const values: AppDataValues = AppDataInjector.buildValues(cfg.getLocal(), '1');
AppDataInjector.inject(subDir, values);
this.slotL?.deactivate();
this.slotS = new WebSlot('subgame', new webview.WebviewController(), true, this.uploadServer);