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?
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.
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:
- Camera access allowed ?
- Yes
- Load WKWebView normally
- No
- Inject JS
- Setup WKWebView
- Load WKWebView's request
- Yes
来源:https://stackoverflow.com/questions/45514435/how-do-i-prevent-a-wkwebview-from-presenting-the-camera-modal-if-a-user-has-deni