twostraws / CodeScanner

A SwiftUI view that is able to scan barcodes, QR codes, and more, and send back what was found.
MIT License
1.02k stars 293 forks source link

How do I get notified when user denies camera permission? #27

Closed haemi closed 2 years ago

haemi commented 3 years ago

Is there a delegate method that handles this case?

ralfebert commented 3 years ago

Having the same problem - the permission error is currently unhandled: https://github.com/twostraws/CodeScanner/blob/main/Sources/CodeScanner/CodeScanner.swift#L172

twostraws commented 2 years ago

I would hope this is reported back as one of the ScanError types, but if it isn't let me know!

rholstad commented 2 years ago

@twostraws there is no error reported when the user denies camera access on the initial permission request. Subsequent initializations of the AVCaptureDeviceInput throw an exception with code AVError.Code.applicationIsNotAuthorizedToUseDevice, which correctly filters back up the delegate chain.

You would need to explicitly manage the permission request rather than relying on the implicit request which is generated for you in the AVCaptureDeviceInput initializer. See AVCaptureDevice.authorizationStatus(for:) and AVCaptureDevice.requestAccess(for:completionHandler:). Then, put your setup code behind these requests to cover the initial denial.

I made a sample Pull Request illustrating how this could be done. #49

emog commented 2 years ago

You can use:

func checkCameraPermission() { if AVCaptureDevice.authorizationStatus(for: .video) == .authorized { //already authorized print("already authorized") } else { AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in if granted { //access allowed print("access allowed") } else { //access denied showingCameraAlert = true } }) } }

and

`.alert(isPresented: $showingCameraAlert) { Alert( title: Text("Camera access"), message: Text("This app uses the camera to scan barcode. Please go to Settings and allow camera access to proceed."), primaryButton: .default(Text("Settings")) { if let settingsUrl = URL(string: UIApplication.openSettingsURLString) {

                    UIApplication.shared.open(settingsUrl)

                }
            },
            secondaryButton: .cancel()
        )
    }`
nathanfallet commented 2 years ago

The completion now returns an error with .permissionDenied in this case.