Commit Graph
3 Commits
Author SHA1 Message Date
joywayer 90a523736e 3.A/3.F 修复:voicePlaying 入参类型兼容 + mediaTypeAudio canPlay 诊断
## 发现的根因

实测日志 mediaTypeAudio 进入了 native(amrFileCodec frame=107 打印两次确认
转码运行),但缺 gameui_play_voice 触发 log → canPlay=false 被短路。
原因是 voicePlaying handler 解析 H5 入参时类型不容忍。

之前实现:
  let on = (data?.asInt ?? 0) == 1

asInt 只对 BridgeData.number case 返回值。若 H5 传 string "1"(实测确实
会传)→ asInt 返回 nil → `?? 0 = 0` → `0 == 1 = false` → 开关被关闭。

daoqi 用 ObjC `[data intValue]`(NSString/NSNumber 都能转),永远能
正确处理两种类型。

## 修复

VoicePlayingHandler:改用 asLooseString 比较 "1" 字符串,兼容 H5 传:
  - string "1"  → asLooseString → "1" → on=true ✓
  - number 1    → asLooseString → "1" → on=true ✓
  - string "0"  → asLooseString → "0" → on=false ✓
  - number 0    → asLooseString → "0" → on=false ✓
  - 其它       → on=false(保守拒绝)

同时加 log.debug 记录每次 voicePlaying 调用的 raw + 解析后值,便于后续
诊断 H5 业务行为。

## 诊断辅助

RemoteAudioHandler.handleMediaTypeAudio 增加 log.debug:
  mediaTypeAudio user=X transcoded=Y canPlay=Z

让真机测试能直接看到 canPlay 实际值,避免再次盲猜。

## 验证

BuildProject 通过 0 错误。真机重试 mediaTypeAudio 应能看到:
  voicePlaying H5 → raw=1 → isEnabled=true
  mediaTypeAudio user=0 transcoded=true canPlay=true
  gameui_play_voice user=0
2026-06-27 12:07:20 +08:00
joywayer 5463b07fb6 voicePlaying 回包对齐原项目:从 "Response from voicePlaying" 改为 "voicePlaying"
契约影响:H5-Native-Contract.md §3.1 [6] voicePlaying responseCallback。
新外壳此前按其它 handler 的 "Response from XXX" 模式套写,与原项目
gameController.m:573 / NewRootVC.m:451 不一致(原项目这里就是 handler 名本身
作回包,是历史包袱)。虽然 H5 通常不校验 cb 内容,但字面保持一致是契约硬约束。
2026-06-24 00:07:25 +08:00
joywayerandClaude Opus 4.7 d38ff0f8c4 Phase 2.A:大厅 8 个简单 handler 落地 + BridgeData 加 nonisolated
闭合 Phase 1.17 联调最后一公里(解决 Xcode 日志 4 个 "no handler registered"
+ 提前落地 4 个无外部依赖的简单 handler)。

新增 7 个 handler 模块(Source/Bridge/Handlers/):
  - ClipboardHandler.swift           §3.1 [13][14]剪贴板 UIPasteboard.general
  - ShakeHandler.swift               §3.1 [7][8][9]摇一摇 + §3.2 [5]shakeEnd 反向
                                       canShake / canVoice 状态 + motionEnded 转发钩子
  - VoicePlayingHandler.swift        §3.1 [6]actor VoiceCenter.shared 开关位
  - DeviceInfoHandler.swift          §3.1 [21]+ §3.2 [1]getphoneInfo 大写 I 入、
                                       getphoneinfo 小写 i 出反向 callback
                                       DeviceInfoSnapshot 6 字段(IDFA 用 idfv 兜底,
                                       CLAUDE.md 不接 ATT/IDFA)
  - BrowserHandler.swift             §3.1 [16]UIApplication.open async(Task @MainActor
                                       异步打开,闭包先 cb 不等 open 完成)
  - OpenSaomaHandler.swift           §3.1 [22]空 stub(契约要求注册)
  - StartLocationHandler.swift       §3.1 [20]Phase 5 完整实现,Phase 2 stub

扩展 VibratorHandler.swift:
  - §3.1 [10]vibrator(原有)+ [11]repeatvibrator(msext RootVC.m:1820 沿用:
    实际单次 vibrate 不真循环)+ [12]canclevibrator

BridgeProtocol.swift BridgeData 加 nonisolated:
  - 项目默认 SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor 让 BridgeData 跨 actor
    访问被拦;asString / asDouble / asInt / asBool / asArray / asObject /
    subscript 全部标 nonisolated(纯值类型本就该是 isolation-free)
  - 影响所有 @Sendable async handler 闭包内的 data?.asXxx 访问

WebContainerViewController 接入:
  - 加 private let shakeHandler = ShakeHandler() 持有
  - registerBridgeHandlers() 注册 8 个 handler 模块
  - 加 canBecomeFirstResponder = true + viewDidAppear becomeFirstResponder
  - 加 motionEnded(_:with:) 转发到 shakeHandler.handleMotionEnded
    (motion 检测必需 first responder,否则不触发)

BuildProject 通过。重装 app 后 H5 启动应不再报 "no handler registered" 错误。

Plan §5 Phase 2.A 全部勾选(含 startlocation bonus stub + BridgeData
nonisolated 重构)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 18:38:00 +08:00