Home > Enterprise >  Access device camera from WKWebView doesn't start
Access device camera from WKWebView doesn't start

Time:01-10

I know that this question was asked many times but after hours of testing I'm still for something which works.. I try to load an url from a WKWebView in Swift. That's the easy part. In this pointed website the user can start automatically (if permission granted) the camera feed. This works fine from a computer with camera.

With this code below I try to achieve the same goal but natively with an iOS App in Swift. The webview is loaded, I prompted for the camera permission because I filled the Infos.plist but the camera feed never starts.. If someone has an idea ? Thanks!

import UIKit
import WebKit
import AVFoundation

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    
    var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in
            if response {
                //access granted
                DispatchQueue.main.async {
                    self.webView = WKWebView(frame: .zero)

                    self.view.addSubview(self.webView)

                    let layoutGuide = self.view.safeAreaLayoutGuide

                    self.webView.translatesAutoresizingMaskIntoConstraints = false
                    self.webView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
                    self.webView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
                    self.webView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
                    self.webView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true

                    if let url = URL(string: "https://webrtc.github.io/samples/src/content/devices/input-output/") {
                        self.webView.load(URLRequest(url: url))
                        self.webView.load(URLRequest(url: url, cachePolicy: .reloadRevalidatingCacheData, timeoutInterval: 15))
                    }
                }
            }
        }
    }
}

CodePudding user response:

After hours of testing I finally found a working solution. A WKWebViewConfiguration was needed AND a javascript code called as WKUserScript. Here is where I find the solution: https://developer.apple.com/forums/thread/134216

Swift code :

import UIKit
import WebKit

class ViewController: UIViewController {
    
    var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
            
        let userScriptURL = Bundle.main.url(forResource: "UserScript", withExtension: "js")!
        let userScriptCode = try! String(contentsOf: userScriptURL)
        let userScript = WKUserScript(source: userScriptCode, injectionTime: .atDocumentStart, forMainFrameOnly: false)
        
        let webConfiguration = WKWebViewConfiguration()
            webConfiguration.mediaTypesRequiringUserActionForPlayback = []
            webConfiguration.allowsInlineMediaPlayback = true
            webConfiguration.userContentController.addUserScript(userScript)
        
        self.webView = WKWebView(frame: .zero, configuration: webConfiguration)

        self.view.addSubview(self.webView)

        let layoutGuide = self.view.safeAreaLayoutGuide

        self.webView.translatesAutoresizingMaskIntoConstraints = false
        self.webView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
        self.webView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
        self.webView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
        self.webView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true

        if let url = URL(string: "https://webrtc.github.io/samples/src/content/getusermedia/gum/") {
            self.webView.load(URLRequest(url: url))
        }
    }
}

UserScript.js :

//injects this into webpage to listen to the camera request

(function() {

  if (!window.navigator) window.navigator = {};

    //if getuserMedia is called -> If the user requests native camera

        window.navigator.getUserMedia = function() {

            webkit.messageHandlers.callbackHandler.postMessage(arguments);

  }

})();
  •  Tags:  
  • Related