修复 H5 音效完全不出声 + 子游戏音效路径错(srcIsloop)
真机诊断([SFX-DIAG])锁定两因: 1. AVPlayer.url 不接受 file:// 本地路径,报 `401 ... not fd:// or network address`——所有本地音效播放失败,故"完全没声"。改用 fdSrc(openSync 取 fd), 远程语音(mediaTypeAudio)仍走 url(网络地址可直接用)。 2. 子游戏音效路径写死 local.gamestart(=gamehall),而 sangelaok 等子游戏音效在 各自目录(.../sangelaok/assets/wav/),找不到文件 → 子游戏更是无声。对齐 Android webviewActivity(gamestart)/NewwebviewActivity(gamedirectory):按"本槽内容目录" 定位,经 CapabilityContext.gameContentDir 注入(大厅=gamestart、子游戏=其目录)。 并发模型重写(复刻 Android SoundPool 并发一次性 + MediaPlayer-per-src 循环): - 原单 AVPlayer 每次 release 再建,互相打断、还杀正在循环的 BGM。 - 改为:循环 BGM 每 src 一个播放器(loopPlayers map);一次性音效各自独立瞬时 播放器(oneShots,播完自释),互不打断。isloop<0 停止该 src 循环。 - fd 生命周期:随播放器释放(release 后)关闭,防泄漏;mute(voicePlaying)作用于全部播放器。 链路改动:CapabilityContext 增 gameContentDir;WebSlot.setup 透传; BridgeGameContainer setupLobby 传 gamestart、switchGame 记录子游戏目录供 setupSubgame 传入。 真机验证:大厅(dir=gamehall)与子游戏(dir=sangelaok)音效均 exists=true、无 401, 循环 BGM 与一次性音效正常播放。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d335a589b6
commit
a104394076
@@ -36,6 +36,8 @@ export struct BridgeGameContainer {
|
||||
private cancels: Array<() => void> = [];
|
||||
/** 非空 → 子游戏 Web 显示(路径 A 切换)。 */
|
||||
@State private subgameUrl: string = '';
|
||||
/** 当前子游戏目录名(switchGame 记录,供 setupSubgame 给能力上下文定位资源,如音效)。 */
|
||||
private currentSubgameDir: string = '';
|
||||
/** 子游戏资源下载中(按需下载期间显示启动页同款进度条)。 */
|
||||
@State private subgameDownloading: boolean = false;
|
||||
/** 子游戏下载进度(0~100)。 */
|
||||
@@ -97,12 +99,14 @@ export struct BridgeGameContainer {
|
||||
if (this.slotL === undefined) {
|
||||
this.slotL = new WebSlot('lobby', this.controllerL, true, this.uploadServer);
|
||||
}
|
||||
this.slotL.setup(this.hostCtx!, this.config!, this.kv!, this.resourceRoot());
|
||||
// 大厅内容目录 = gamestart(gamehall):音效等按此定位 <urlpath>/gamehall/assets/wav/*
|
||||
this.slotL.setup(this.hostCtx!, this.config!, this.kv!, this.resourceRoot(), this.config!.getLocal().gamestart);
|
||||
}
|
||||
|
||||
private setupSubgame(): void {
|
||||
this.ensureDeps();
|
||||
this.slotS?.setup(this.hostCtx!, this.config!, this.kv!, this.resourceRoot());
|
||||
// 子游戏内容目录 = 当前进入的子游戏目录(switchGame 时记录),音效定位 <urlpath>/<dir>/assets/wav/*
|
||||
this.slotS?.setup(this.hostCtx!, this.config!, this.kv!, this.resourceRoot(), this.currentSubgameDir);
|
||||
}
|
||||
|
||||
private activeSlot(): WebSlot | undefined {
|
||||
@@ -186,6 +190,7 @@ export struct BridgeGameContainer {
|
||||
const values: AppDataValues = AppDataInjector.buildValues(cfg.getLocal(), '1');
|
||||
AppDataInjector.inject(subDir, values);
|
||||
this.slotL?.deactivate();
|
||||
this.currentSubgameDir = d.dir; // 供 setupSubgame 注入能力上下文(音效资源定位)
|
||||
this.slotS = new WebSlot('subgame', new webview.WebviewController(), true, this.uploadServer);
|
||||
this.applyOrientation(d.webtype !== '2'); // "3" 横 / "2" 竖
|
||||
this.subgamePainted = false; // 子游戏首帧前用启动图盖住,避免 下载完→子游戏上屏 间白屏
|
||||
|
||||
@@ -46,8 +46,10 @@ export class WebSlot {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
/** onControllerAttached:建桥 + 经组装根注册能力(每槽独立一套)。 */
|
||||
setup(hostCtx: common.UIAbilityContext, config: ConfigManager, kv: KvStore, resourceRoot: string): void {
|
||||
/** onControllerAttached:建桥 + 经组装根注册能力(每槽独立一套)。
|
||||
* gameContentDir:本槽加载内容目录名(大厅 gamestart / 子游戏目录),供音效等按槽定位资源。 */
|
||||
setup(hostCtx: common.UIAbilityContext, config: ConfigManager, kv: KvStore, resourceRoot: string,
|
||||
gameContentDir: string): void {
|
||||
try {
|
||||
this.controller.setPathAllowingUniversalAccess([resourceRoot]);
|
||||
} catch (e) {
|
||||
@@ -65,6 +67,7 @@ export class WebSlot {
|
||||
config,
|
||||
kv,
|
||||
uploadServer: this.uploadServer,
|
||||
gameContentDir,
|
||||
log: Logger.tag(`Cap-${this.role}`),
|
||||
captureCanvas: (canvasId: string): Promise<string> => this.captureCanvas(canvasId),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user