ios - 在 wkwebview 中启用摄像头和麦克风访问

标签 ios objective-c swift html wkwebview

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

我将此应用程序包装在 WKWebView 中,因为我想提供原生应用程序体验。我知道 iOS 不允许通过浏览器访问摄像头——但是有什么方法可以使用 native 代码(与包装器一起)获得对网络摄像头/麦克风的权限,并将其提供给网络应用程序——也许通过某种方式指向 getUserMedia 到本地流源?

最佳答案

是的,看看cordova-plugin-iosrtccordova-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中,在文档开头注入(inject)脚本:

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 中执行,直接在 WKWebView 中评估函数调用:

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

这些回调需要在 JavaScript 调用 postMessage 之前存储在哈希中,然后必须将哈希键发送到 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 和 native 框架代码背后的一般思想。

关于ios - 在 wkwebview 中启用摄像头和麦克风访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43916436/

相关文章:

ios - 以编程方式将 View 的前缘与约束对齐

ios - 停止由 `performSelector` 在 `viewDidDisappear` 上启动的子线程

swift - 如何在 Swift 中删除字符串中的重复字符

javascript - 圆弧未在 Safari 中的 2D 上下文中呈现

ios - 代码签名对于证明所有权至关重要吗?

ios - 不同UIViewController的调用方法

ios - AVPlayerViewController 播放后退出全屏

ios - 注销时清除所有 View Controller

ios - 如何将 iOS 图表中的突出显示仅剪切到数据点?

ios - Xcode 10 beta iOS 12 不显示图像