How do I prevent a WKWebView from presenting the Camera modal if a user has denied access to the camera?

时间秒杀一切 提交于 2019-11-28 08:50:58

问题


In my app, I have a WKWebView loading a website with file input that allows a user to upload images via the Camera or the Photo Library.

My app has both privacy usage descriptions for the Camera and Photo Library.

If a user has denied access to the Camera, the WKWebView will still show the option to upload images via the Camera, and the Camera modal presents (though it only shows black where you'd normally see an image of what the camera is showing). If a user swipes to the Video option in the Camera modal, the app crashes.

The relevant stack trace shows:

3   TCC __TCCAccessRequest_block_invoke_2.80 + 222
4   TCC __CRASHING_DUE_TO_PRIVACY_VIOLATION__ + 682

Is it possible from the native app side (suppose I can't edit the HTML loaded) to prevent the WKWebView from presenting the Camera modal in this case?


回答1:


Because you mentioned __CRASHING_DUE_TO_PRIVACY_VIOLATION__ the app is probably actually crashing because you haven't added the iOS10 permission description for using the microphone. The camera view will trigger this additional microphone permissions popup if you choose Video. In iOS10, you must fill in the description that is presented to the user or the app will crash as you have reported. In iOS9, it just presents the generic permissions popup.

Try adding a description for the key NSMicrophoneUsageDescription in your Info.plist file. In Xcode this is called Privacy - Microphone Usage Description

This other answer will give you more details of the various privacy keys and their descriptions.




回答2:


It'd appear to be a bug since it only crashes when Video is selected. I found a workaround by injecting JS:

  • Set the content type to only allow photos. (sample code included below)
  • Delete/Hide the input-file
  • Disable the input-file
func requestCamera() {
    AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { response in
        if response {
            self.injectJavascript()
        } else {
            self.webView = WKWebView(frame: .zero)
        }


        self.setupRequest()
    }
}

func injectJavascript() {
    let webConfiguration = WKWebViewConfiguration()
    let contentController = WKUserContentController()
    let js = "var fileInput = document.getElementById('allMedia'); fileInput.setAttribute('accept', 'image/*');"
    let userScript = WKUserScript(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
    contentController.addUserScript(userScript)
    webConfiguration.userContentController = contentController
    webView = WKWebView(frame: .zero, configuration: webConfiguration)
}

func setupRequest() {
    let url = URL(string: "...")!
    let request = URLRequest(url: url)
    webView.load(request)
}

Flow is as follows:

  1. Camera access allowed ?
    • Yes
      1. Load WKWebView normally
    • No
      1. Inject JS
      2. Setup WKWebView
      3. Load WKWebView's request


来源:https://stackoverflow.com/questions/45514435/how-do-i-prevent-a-wkwebview-from-presenting-the-camera-modal-if-a-user-has-deni

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!