在 wkwebview 中启用相机和麦克风访问



我有一个针对移动设备优化的Web应用程序,它利用getUserMedia来访问网络摄像头和麦克风资源。

我正在将此应用程序包装在WKWebView中,因为我想提供本机应用程序体验。 我知道 iOS 不允许通过浏览器访问相机 - 但是有没有办法使用本机代码(以及包装器)获得对网络摄像头/麦克风的权限并将其提供给 Web 应用程序 - 也许通过以某种方式将getUserMedia指向本地流源?

是的,看看cordova-plugin-iosrtc和cordova-plugin-wkwebview-engine。插件背后的想法如下:

1.创建一个JavaScript文件(WebRTC.js),它定义了各种WebRTC类和函数,并将调用传递给WKWebView,例如:

(function() {
if (!window.navigator) window.navigator = {};
window.navigator.getUserMedia = function() {
webkit.messageHandlers.callbackHandler.postMessage(arguments);
}
})();

2.在 WKWebView 中,在文档开头注入脚本:

let contentController = WKUserContentController();
contentController.add(self, name: "callbackHandler")
let script = try! String(contentsOf: Bundle.main.url(forResource: "WebRTC", withExtension: "js")!, encoding: String.Encoding.utf8)
contentController.addUserScript(WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true))
let config = WKWebViewConfiguration()
config.userContentController = contentController
webView = WKWebView(frame: CGRect.zero, configuration: config)

3.监听从 JavaScript 发送的消息:

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {
var webView: WKWebView!
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "callbackHandler" {
print(message.body)
// make native calls to the WebRTC framework here
}
}
}

4.如果需要在 JavaScript-land 中执行成功或失败的回调,请直接在 WKWebView 中评估函数调用:

webView.evaluateJavaScript("callback({id: (id), status: 'success', args: ...})", completionHandler: nil)

这些回调需要在调用postMessage之前存储在 JavaScript 中的哈希中,然后必须将哈希键发送到 WKWebView。这是插件中的commandId

int exec_id = 0;
function exec(success, failure, ...) {
// store the callbacks for later
if (typeof success == 'function' || typeof failure == 'function') {
exec_id++;
exec_callbacks[exec_id] = { success: success, failure: failure };
var commandId = exec_id;
}
webkit.messageHandlers.callbackHandler.postMessage({id: commandId, args: ...})
}
// the native code calls this directly with the same commandId, so the callbacks can be performed and released
function callback(opts) {
if (opts.status == "success") {
if (typeof exec_callbacks[opts.id].success == 'function') exec_callbacks[opts.id].success(opts.args);
} else {
if (typeof exec_callbacks[opts.id].failure == 'function') exec_callbacks[opts.id].failure(opts.args);
}
// some WebRTC functions invoke the callbacks multiple times
// the native Cordova plugin uses setKeepCallbackAs(true)
if (!opts.keepalive) delete exec_callbacks[opts.id];
}

5.当然,将NSCameraUsageDescriptionNSMicrophoneUsageDescription权限添加到项目的Info.plist中。

请记住,这是一项不平凡的任务,但这是将JavaScript,WKWebView和本机框架代码与异步回调桥接的一般思想。

所以我现在找到了WebRTC访问的解决方案

通过配置 WKWebView 以允许内联媒体播放为 true

例。

internal lazy var webview: WKWebView = {
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
return WKWebView(frame: .zero, configuration: config)
}()

希望这个答案对您和其他人有所帮助。

最新更新