MacOS下WKWebView调用getUserMedia无提示且挂起问题排查
解决方案
1. 实现无头WKWebView的权限代理逻辑
无头WKWebView不会自动触发系统权限弹窗,需在Flutter插件的Native层(Objective-C/Swift)手动对接权限回调,把系统已授予的权限传递给WebView:
- 给WKWebView设置
WKUIDelegate,实现webView:requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler:方法- (void)webView:(WKWebView *)webView requestMediaCapturePermissionForOrigin:(WKSecurityOrigin *)origin initiatedByFrame:(WKFrameInfo *)frame type:(WKMediaCaptureType)type decisionHandler:(void (^)(WKPermissionDecision))decisionHandler { AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; if (status == AVAuthorizationStatusAuthorized) { decisionHandler(WKPermissionDecisionGrant); } else { decisionHandler(WKPermissionDecisionDeny); } } - 该操作能让WebView识别系统权限状态,避免
getUserMedia请求挂起。
2. 修复HALC错误与权限配置问题
HALC错误多因Sandbox或Hardened Runtime权限未完全生效,需补充以下操作:
- 在XCode的Sandbox设置中,确认
Audio Input已勾选,同时检查Entitlements.plist中存在com.apple.security.device.audio-input权限项 - 确保Hardened Runtime的
Audio Input权限已开启,且Entitlements.plist中对应字段值为true - 执行
Command+Shift+K清除缓存后重新编译应用,避免配置未加载。
3. 同步系统权限到WebView
Safari网站权限设置未显示应用,说明WebView权限存储未关联系统权限,可在WebView加载前主动同步:
- 先通过Native层确认系统麦克风权限已授予,再注入
WKUserScript提前告知WebView权限状态:let script = WKUserScript(source: """ navigator.mediaDevices.getUserMedia = new Proxy(navigator.mediaDevices.getUserMedia, { apply(target, thisArg, args) { return new Promise((resolve, reject) => { if (args[0].audio) { resolve(new MediaStream()); } else { reject(new Error('Permission denied')); } }); } }); """, injectionTime: .atDocumentStart, forMainFrameOnly: true) webView.configuration.userContentController.addUserScript(script) - 注意:仅在系统已授权时使用该脚本,需配合Native层权限检查,避免模拟授权导致Twilio Voice JS异常。
4. 适配Twilio Voice JS的无头环境
Twilio Voice JS在无头WebView下需调整初始化配置:
- 初始化时设置
disableAudioContextResume为true,避免自动恢复音频上下文引发的权限问题:const device = new Twilio.Device(token, { disableAudioContextResume: true, // 其他业务配置 }); - 待通话建立后,再手动调用
audioContext.resume()激活音频上下文。
内容的提问来源于stack exchange,提问作者CybeX
相关产品推荐
相关产品推荐

