Presentación del diálogo de permiso de cámara en iOS 8
permissions camera (9)
Cuando mi aplicación intenta acceder a la cámara por primera vez en iOS 8, se le presenta al usuario un cuadro de diálogo de permisos de cámara, muy similar al micrófono para acceder al micrófono en iOS 7.
En iOS 7, era posible invocar el diálogo de permiso del micrófono de antemano y ver si el permiso fue otorgado (ver esta pregunta , por ejemplo). ¿Existe una forma similar de invocar el diálogo de permiso de la cámara en iOS 8? ¿Se puede combinar el diálogo para el permiso de acceso de micrófono Y cámara?
Aquí está el enfoque que terminamos usando:
if ([AVCaptureDevice respondsToSelector:@selector(requestAccessForMediaType: completionHandler:)]) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
// Will get here on both iOS 7 & 8 even though camera permissions weren''t required
// until iOS 8. So for iOS 7 permission will always be granted.
if (granted) {
// Permission has been granted. Use dispatch_async for any UI updating
// code because this block may be executed in a thread.
dispatch_async(dispatch_get_main_queue(), ^{
[self doStuff];
});
} else {
// Permission has been denied.
}
}];
} else {
// We are on iOS <= 6. Just do what we need to do.
[self doStuff];
}
Aquí está mi solución Swift (iOS 8), necesitaba la cámara para escanear QR, así que realmente tuve que solicitar su uso.
Esto proporciona
-
Anime al usuario a seleccionar Permitir si es anterior a la pregunta predeterminada Permitir acceso a la cámara
-
Manera fácil de acceder a la configuración si el usuario rechaza la primera solicitud.
Para que se ejecute, llame a la cámara de verificación en ViewDidAppear / o ViewDidLoad, etc. Necesitaba usar viewDidAppear para configurar las restricciones de vistas de mi cámara personalizada.
func checkCamera() {
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authStatus {
case .authorized: break // Do your stuff here i.e. allowScanning()
case .denied: alertToEncourageCameraAccessInitially()
case .notDetermined: alertPromptToAllowCameraAccessViaSetting()
default: alertToEncourageCameraAccessInitially()
}
}
func alertToEncourageCameraAccessInitially() {
let alert = UIAlertController(
title: "IMPORTANT",
message: "Camera access required for QR Scanning",
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: "Please allow camera access for QR Scanning",
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)
}
Gracias a jamix anterior por el consejo para usar dispatch_async, hace que la respuesta muestre la función de cámara recién configurada mucho más rápido.
Perdón por una mezcla de cierres finales ... quería probarlos.
El problema para mí fue que el
Bundle name
y el
Bundle name
para
Bundle Display Name
no se configuraron en mi Info.plist debido a algunos cambios recientes en la configuración de la compilación.
Un tipo de caso poco probable ... Pero me llevó unas horas aclarar esto.
Esperemos que ayude a alguien más.
Me encuentro con un problema similar, si el usuario ha denegado el acceso a la cámara cuando se le solicita por primera vez, presionar el botón para tomar una instantánea toma como resultado una pantalla negra en el modo de cámara.
Sin embargo, quiero detectar que el usuario ha rechazado el acceso y solicitar que se active, pero no puedo encontrar ninguna función para verificar el acceso actual de la cámara del usuario, ¿existe tal función?
EDITAR: La siguiente verificación le permitirá saber en iOS 8 sobre el acceso a la cámara:
#import <AVFoundation/AVFoundation.h>
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(status == AVAuthorizationStatusAuthorized) { // authorized
}
else if(status == AVAuthorizationStatusDenied){ // denied
}
else if(status == AVAuthorizationStatusRestricted){ // restricted
}
else if(status == AVAuthorizationStatusNotDetermined){ // not determined
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if(granted){ // Access has been granted ..do something
} else { // Access denied ..do something
}
}];
}
Esta información se encontró en la siguiente pregunta ( Cómo saber que la aplicación tiene acceso a la cámara o no mediante programación en iOS8 ):
Ninguna de las respuestas parece verificar los permisos tanto del micrófono como de la cámara. Nuestro código verifica el escenario en el que se otorgan permisos de cámara pero se deniega el acceso al micrófono.
Como somos nuevos en Swift, es poco probable que los cierres retorcidos anidados y
if
declaraciones sean óptimas.
¡Por favor comparta sugerencias para mejorar el código!
Pero al menos funciona hasta ahora en las pruebas.
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (videoGranted: Bool) -> Void in
if (videoGranted) {
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeAudio, completionHandler: { (audioGranted: Bool) -> Void in
if (audioGranted) {
dispatch_async(dispatch_get_main_queue()) {
// Both video & audio granted
}
} else {
// Rejected audio
}
})
} else {
// Rejected video
}
})
Para Swift 3, puede agregar esto en su método
viewWillAppear
de su primer controlador de vista:
Primero importe el marco de
AVFoundation
import AVFoundation
Entonces:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let authorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authorizationStatus {
case .notDetermined:
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { granted in
if granted {
print("access granted")
}
else {
print("access denied")
}
}
case .authorized:
print("Access authorized")
case .denied, .restricted:
print("restricted")
}
}
No olvide agregar
Privacy - Camera Usage Description
Clave de
Privacy - Camera Usage Description
en su
Info.plist
Para mí, este trabajo en iOS7 y iOS8:
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusAuthorized:
break;
case ALAuthorizationStatusRestricted:
case ALAuthorizationStatusDenied:
break;
case ALAuthorizationStatusNotDetermined:
break;
}
Realizo una comprobación de acceso en el delegado de la aplicación.
import UIKit
import AVFoundation
import Photos
func applicationDidBecomeActive(application: UIApplication) {
cameraAllowsAccessToApplicationCheck()
internetAvailabilityOnApplicationCheck()
photoLibraryAvailabilityCheck()
}
//MARK:- CAMERA ACCESS CHECK
func cameraAllowsAccessToApplicationCheck()
{
let authorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
switch authorizationStatus {
case .NotDetermined:
// permission dialog not yet presented, request authorization
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo,
completionHandler: { (granted:Bool) -> Void in
if granted {
print("access granted")
}
else {
print("access denied")
}
})
case .Authorized:
print("Access authorized")
case .Denied, .Restricted:
alertToEncourageCameraAccessWhenApplicationStarts()
default:
print("DO NOTHING")
}
}
//MARK:- PHOTO LIBRARY ACCESS CHECK
func photoLibraryAvailabilityCheck()
{
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.Authorized
{
}
else
{
var cameraUnavailableAlertController = UIAlertController (title: "Photo Library Unavailable", message: "Please check to see if device settings doesn''t allow photo library access", preferredStyle: .Alert)
var settingsAction = UIAlertAction(title: "Settings", style: .Destructive) { (_) -> Void in
let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString)
if let url = settingsUrl {
UIApplication.sharedApplication().openURL(url)
}
}
var cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil)
cameraUnavailableAlertController .addAction(settingsAction)
cameraUnavailableAlertController .addAction(cancelAction)
self.window?.rootViewController!.presentViewController(cameraUnavailableAlertController , animated: true, completion: nil)
}
}
func internetAvailabilityOnApplicationCheck()
{
//MARK:- INTERNET AVAILABLITY
if InternetReachability.isConnectedToNetwork() {
}
else
{
dispatch_async(dispatch_get_main_queue(), {
//INTERNET NOT AVAILABLE ALERT
var internetUnavailableAlertController = UIAlertController (title: "Network Unavailable", message: "Please check your internet connection settings and turn on Network Connection", preferredStyle: .Alert)
var settingsAction = UIAlertAction(title: "Settings", style: .Destructive) { (_) -> Void in
let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString)
if let url = settingsUrl {
UIApplication.sharedApplication().openURL(url)
}
}
var cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil)
internetUnavailableAlertController .addAction(settingsAction)
internetUnavailableAlertController .addAction(cancelAction)
self.window?.rootViewController!.presentViewController(internetUnavailableAlertController , animated: true, completion: nil)
})
}
}
* *
-
Solución Swift 3.0
importar AVFoundation
Nota: agregue la clave Privacidad - Descripción del uso de la cámara en su Lista de información
// MARK: manejo de la cámara
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: alertToEncourageCameraAccessInitially()
case .notDetermined: alertPromptToAllowCameraAccessViaSetting()
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)
}