web-dev-qa-db-ja.com

wkwebviewでカメラとマイクへのアクセスを有効にする

getUserMediaを使用してWebカメラとマイクのリソースにアクセスするモバイル用に最適化されたWebアプリがあります。

ネイティブアプリエクスペリエンスを提供するため、このアプリをWKWebViewでラップしています。 iOSがブラウザー経由でのカメラアクセスを許可していないことは承知しています。ただし、おそらくラッパーと一緒にネイティブコードを使用してwebcam/micへのアクセス権を取得し、これをWebアプリにフィードする方法はあります-おそらくgetUserMediaをローカルストリームソース?

8
SB2055

はい、 cordova-plugin-iosrtccordova-plugin-wkwebview-engine をご覧ください。プラグインの背後にある考え方は次のとおりです。

1。さまざまなWebRTCクラスおよび関数を定義し、呼び出しをWKWebViewに渡すJavaScriptファイル(WebRTC.js)を作成します。次に例を示します。

(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ランドで実行する必要がある場合は、WKWebView内で直接関数呼び出しを評価します。

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

これらのコールバックは、JavaScriptのハッシュに保存する必要がありますbefore _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。もちろん、プロジェクトのInfo.plistNSCameraUsageDescriptionおよびNSMicrophoneUsageDescription権限を追加します。

これは重要なタスクですが、JavaScript、WKWebView、および非同期コールバックを使用したネイティブフレームワークコードをブリッジする一般的な考え方です。

8