3.E 修复:首次启动权限请求与浮层 touchObserver 死锁
## 问题 首次启动 app,H5 按住麦克风按钮触发 prepareaudio: 1. 主动调 AVAudioSession.requestRecordPermission 弹系统权限对话框 2. 用户为了点"允许"必须松手 3. 松手被 RecordingAwareWindow.touchObserver 立刻捕获 → recorder.stop() 4. 浮层瞬间关闭,录音失败 5. 用户感受:"按一次没反应,再点也没用" ## 根因 我之前用 `requestRecordPermission` 主动请求权限(会同步弹系统对话框), 与 daoqi `FuncPublic.ifauth`(只读 `AVCaptureDevice.authorizationStatus`, 不主动请求)行为不一致。主动请求 + 按住状态 + touchObserver 全局监听 三者形成死锁。 ## 修复 改用只读状态 + 三分支处理: - `.denied / .restricted`:弹 Alert + return(对齐 daoqi) - `.notDetermined`(首次):**主动弹权限对话框但不启动录音浮层**。 用户做完选择后 return,不触发 cb。第二次按录音按钮时走 .authorized 分支正常录音 - `.authorized`:直接启动录音浮层 ## 与 daoqi 行为对比 daoqi 在 .notDetermined 时 ifauth 返回 1(继续启动录音),但实测此路径 也有体验问题——浮层弹出 + 系统对话框遮挡 + 用户松手立刻触发 touchEnded → 录音空文件 → 转码失败 → silent return。最终用户体验也是"按一次没 反应"。 新外壳的修复让首次行为更明确(不启动录音 = 不会有空文件上传),与 daoqi 真实终态(不触发 getaudiourl)等价,UX 等价(首次启动需按两次)。 ## H5 契约影响 无。"不触发 cb" 与 daoqi 转码失败 silent return 等价;H5 收不到 getaudiourl 反向 callback 时本来就要兼容(daoqi 各类失败路径都不触发 cb)。 ## 验证 BuildProject 通过 0 错误。
This commit is contained in:
@@ -85,16 +85,39 @@ public enum RemoteAudioHandler {
|
||||
isSubGame: Bool,
|
||||
callback: BridgeCallback?
|
||||
) async {
|
||||
// 1. 麦克风权限请求
|
||||
let granted: Bool = await withCheckedContinuation { cont in
|
||||
AVAudioSession.sharedInstance().requestRecordPermission { ok in
|
||||
cont.resume(returning: ok)
|
||||
}
|
||||
}
|
||||
guard granted else {
|
||||
// 拒绝:弹 Alert + 不触发 callback(对齐 daoqi NewRootVC.m:314-319)
|
||||
// 1. 麦克风权限**只读**状态检查(对齐 daoqi FuncPublic.m:1144-1170 ifauth 实现)。
|
||||
// 主动请求权限(requestRecordPermission)会立即弹出 iOS 系统对话框;
|
||||
// 在 H5 按住状态下弹系统对话框 → 用户必须松手点"允许" →
|
||||
// RecordingAwareWindow.touchObserver 捕获松手立刻 stop → 浮层瞬间关闭,
|
||||
// 用户体验异常(首次启动 app 录音永远失败)。
|
||||
let status = AVCaptureDevice.authorizationStatus(for: .audio)
|
||||
switch status {
|
||||
case .denied, .restricted:
|
||||
// 明确拒绝 → 弹 Alert + 不触发 cb(对齐 daoqi NewRootVC.m:314-319)
|
||||
showMicrophonePermissionAlert(on: hostVC())
|
||||
return
|
||||
|
||||
case .notDetermined:
|
||||
// 首次启动:弹系统权限对话框,**不**启动录音浮层(避免与 touchObserver
|
||||
// 死锁)。用户做完选择 / 第二次按录音按钮时走 .authorized 分支正常录音。
|
||||
//
|
||||
// ⚠️ daoqi ifauth 在 .notDetermined 时返回 1(继续录音),但 daoqi 用
|
||||
// NotificationCenter 全局监听,行为可能与新外壳的 touchObserver 不一致;
|
||||
// 经实测新外壳走 daoqi 老路径会"按一次没反应"——改用先请求权限再 return
|
||||
// 的策略,等价于 "第一次按录音按钮 = 触发权限请求;第二次按 = 正常录音"。
|
||||
_ = await withCheckedContinuation { cont in
|
||||
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
||||
cont.resume(returning: granted)
|
||||
}
|
||||
}
|
||||
// 无论用户允许/拒绝都不触发 cb(H5 端会因没收到 cb 知道本次录音未发生)
|
||||
return
|
||||
|
||||
case .authorized:
|
||||
break // 继续启动录音
|
||||
|
||||
@unknown default:
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 启动录音浮层
|
||||
|
||||
Reference in New Issue
Block a user