¿Cómo comprobar si el usuario dio permiso para usar la cámara?

81

Tratando de escribir esto:

if usergavepermissiontousercamera  
  opencamera
else 
  showmycustompermissionview

No se pudo encontrar una forma actual de realizar esta sencilla tarea.
Nota: También debería funcionar iOS7 incluso si requiere un método diferente

Esqarrouth
fuente
Deberías consultar este enlace. stackoverflow.com/questions/25803217/… No debería ser difícil traducir a Swift.
Mehdi.Sqalli
AVCaptureDevice y AVAuthorizationStatus no son reconocidos por xcode, tal vez un error o algo, pero sí, esto lo hace bastante difícil.
Esqarrouth
comprobé esa respuesta. es para el
carrete

Respuestas:

176

Puede utilizar el siguiente código para hacer lo mismo:

if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) ==  AVAuthorizationStatus.Authorized {
    // Already Authorized
} else {
    AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
       if granted == true {
           // User granted
       } else {
           // User rejected
       }
   })
}

NOTA:

  1. Asegúrese de agregar AVFoundationFramework en la sección Link Binary de las fases de compilación
  2. Deberías escribir import AVFoundationen tu clase para importarAVFoundation

SWIFT 3

if AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) ==  AVAuthorizationStatus.authorized {
   // Already Authorized
} else {
   AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
      if granted == true {
         // User granted
      } else {
         // User Rejected
      }
   })
}

Rápido 4

if AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized {
    //already authorized
} else {
    AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
        if granted {
            //access allowed
        } else {
            //access denied
        }
    })
}
MP Midhun
fuente
Gracias. la importación funcionó sin agregar al enlace binario. pero tengo Foundation en los marcos. ¿Eso está relacionado?
Esqarrouth
1
@Esq: No es necesario vincular binarios porque, de acuerdo con Swift Imports, cualquier marco Objective-C (o biblioteca C) que sea accesible como módulo se puede importar directamente a Swift. Esto incluye todos los marcos del sistema Objective-C, como Foundation, UIKit y SpriteKit, así como las bibliotecas C comunes suministradas con el sistema. Merry X'mas ...
Midhun MP
gracias, feliz navidad a ti también :) por cierto, en ios7 este método ingresa ya autorizado a pesar de que nunca recibió la solicitud. ¿Por qué es así y cómo puedo solucionarlo?
Esqarrouth
@Esq: si su aplicación ya tenía el permiso y se configuró en la aplicación de configuración, no volverá a preguntar. Verifique su aplicación de configuración si tiene el permiso o no.
Midhun MP
Restablecí la configuración del simulador antes de intentar esto. Fui y verifiqué la configuración, no hay nada sobre la aplicación allí. probándolo en el simulador ios7.1
Esqarrouth
18

Solución actualizada Swift 3.0

func callCamera(){
    let myPickerController = UIImagePickerController()
    myPickerController.delegate = self;
    myPickerController.sourceType = UIImagePickerControllerSourceType.camera

    self.present(myPickerController, animated: true, completion: nil)
    NSLog("Camera");
}
func checkCamera() {
    let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
    switch authStatus {
    case .authorized: callCamera() // Do your stuff here i.e. callCameraMethod()
    case .denied: alertPromptToAllowCameraAccessViaSetting()
    case .notDetermined: alertToEncourageCameraAccessInitially()
    default: alertToEncourageCameraAccessInitially()
    }
}

func alertToEncourageCameraAccessInitially() {
    let alert = UIAlertController(
        title: "IMPORTANT",
        message: "Camera access required for capturing photos!",
        preferredStyle: UIAlertControllerStyle.alert
    )
    alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
    alert.addAction(UIAlertAction(title: "Allow Camera", style: .cancel, handler: { (alert) -> Void in
        UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
    }))
    present(alert, animated: true, completion: nil)
}

func alertPromptToAllowCameraAccessViaSetting() {

    let alert = UIAlertController(
        title: "IMPORTANT",
        message: "Camera access required for capturing photos!",
        preferredStyle: UIAlertControllerStyle.alert
    )
    alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel) { alert in
        if AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count > 0 {
            AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { granted in
                DispatchQueue.main.async() {
                    self.checkCamera() } }
        }
        }
    )
    present(alert, animated: true, completion: nil)
}
Sourabh Sharma
fuente
Creo que mezclaron nombres de métodos alertToEncourageCameraAccessInitially y alertPromptToAllowCameraAccessViaSetting;)
jonaszmclaren
Puedes mejorar la respuesta. Será mejor. De lo contrario, cuando esté libre, lo comprobaré. Gracias :) @jonaszmclaren
Sourabh Sharma
12

La siguiente es una respuesta limpia y actualizada para Swift 4.x:

A partir de iOS 10, también debe solicitar permiso en el archivo info.plist para evitar un bloqueo:

ingrese la descripción de la imagen aquí

Privacidad: descripción del uso de la cámara

Debe proporcionar una cadena que se presenta al usuario con esta clave. Si no lo hace, se producirá un accidente al intentar acceder a la cámara.

import AVFoundation

func checkCameraAccess() {
    switch AVCaptureDevice.authorizationStatus(for: .video) {
    case .denied:
        print("Denied, request permission from settings")
        presentCameraSettings()
    case .restricted:
        print("Restricted, device owner must approve")
    case .authorized:
        print("Authorized, proceed")
    case .notDetermined:
        AVCaptureDevice.requestAccess(for: .video) { success in
            if success {
                print("Permission granted, proceed")
            } else {
                print("Permission denied")
            }
        }
    }
}

func presentCameraSettings() {
    let alertController = UIAlertController(title: "Error",
                                  message: "Camera access is denied",
                                  preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Cancel", style: .default))
    alertController.addAction(UIAlertAction(title: "Settings", style: .cancel) { _ in
        if let url = URL(string: UIApplicationOpenSettingsURLString) {
            UIApplication.shared.open(url, options: [:], completionHandler: { _ in
                // Handle
            })
        }
    })

    present(alertController, animated: true)
}

Esto probará las cuatro posibles respuestas y luego solicitará permiso si es así notDetermined, o dirigirá al usuario a la configuración para habilitarlo si lo es denied. Si es así restricted, es posible que el usuario actual no pueda habilitarlo, pero debe proporcionarle algún tipo de orientación.

CodeBender
fuente
9

Esto abrirá la cámara cuando el usuario otorgue el permiso. De lo contrario, muestre alerta para pedir permiso.

func openCamera(){
        
        let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
        
        switch (authStatus){
            
        case .notDetermined, .restricted, .denied:
            showAlert(title: "Unable to access the Camera", message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.")
        case .authorized:
            alert.dismiss(animated: true, completion: nil)
            if(UIImagePickerController .isSourceTypeAvailable(.camera)){
                picker.sourceType = .camera
                picker.showsCameraControls=true
                picker.allowsEditing=true
                self.viewController!.present(picker, animated: true, completion: nil)
            }
        }
}

después de esto, llame a esta función para mostrar la alerta

func showAlert(title:String, message:String) {
        let alert = UIAlertController(title: title,
                                      message: message,
                                      preferredStyle: UIAlertController.Style.alert)
        
        let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
        alert.addAction(okAction)
        
        let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in
            // Take the user to Settings app to possibly change permission.
            guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
            if UIApplication.shared.canOpenURL(settingsUrl) {
                if #available(iOS 10.0, *) {
                    UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                        // Finished opening URL
                    })
                } else {
                    // Fallback on earlier versions
                    UIApplication.shared.openURL(settingsUrl)
                }
            }
        })
        alert.addAction(settingsAction)
        
        self.viewController!.present(alert, animated: true, completion: nil)
    }
Prashant Sharma
fuente
+1, ya que funcionó para mí después de un pequeño cambio. Todo bien, excepto por primera vez, el caso .notDetermined será verdadero, por lo que podemos proceder a hacer todo lo que hicimos en el caso .authorised, porque pedirá permitir / denegar o podemos presentar al usuario "AVCaptureDevice.requestAccess (para : .video) ". A partir del siguiente intento, el caso de cambio seguirá en función de la primera respuesta. Además, hasta la primera vez que denegamos / permitamos, no veremos esto en la configuración de privacidad.
Lokesh Purohit
2

Modifiqué la respuesta anterior y eliminé el mensaje inicial, ya que cuando queremos usar la cámara del dispositivo, el sistema solicita los permisos:

func checkPermissions() {
    let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)

    switch authStatus {
    case .authorized:
        setupCamera()
    case .denied:
        alertPromptToAllowCameraAccessViaSetting()
    default:
        // Not determined fill fall here - after first use, when is't neither authorized, nor denied
        // we try to use camera, because system will ask itself for camera permissions
        setupCamera()
    }
}

func alertPromptToAllowCameraAccessViaSetting() {
    let alert = UIAlertController(title: "Error", message: "Camera access required to...", preferredStyle: UIAlertControllerStyle.alert)

    alert.addAction(UIAlertAction(title: "Cancel", style: .default))
    alert.addAction(UIAlertAction(title: "Settings", style: .cancel) { (alert) -> Void in
        UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
    })

    present(alert, animated: true)
}
jonaszmclaren
fuente
2

Puede importar el marco de AVFoundation y utilizar el método de autorizaciónStatus (para :) que se muestra a continuación y manejar los casos respectivos.

switch AVCaptureDevice.authorizationStatus(for: .video) {
    case .authorized: // The user has previously granted access to the camera.
        self.setupCaptureSession()

    case .notDetermined: // The user has not yet been asked for camera access.
        AVCaptureDevice.requestAccess(for: .video) { granted in
            if granted {
                self.setupCaptureSession()
            }
        }

    case .denied: // The user has previously denied access.
        return
    case .restricted: // The user can't grant access due to restrictions.
        return
}
Anu Mittal
fuente