在iOS中检测相机的权限
我开发了一个非常简单的video应用程序。 我使用官方控件:UIImagePickerController。
这是问题。 当第一次展示UIImagePickerController时,iOS会询问权限。 用户可以点击是或否。 如果用户点击否,控制不会被解除。 相反,如果用户不断点击开始button,定时器将继续,而屏幕始终是黑色的,用户不能停止定时器或返回。 用户唯一能做的就是杀死应用程序。 UIImagePickerController下一次出现时,它仍然是一个黑屏,如果点击开始,用户不能返回。
我想知道这是否是一个错误。 有什么办法可以检测到相机的权限,以便我们可以决定显示UIImagePickerController吗?
检查AVAuthorizationStatus
并正确处理这些情况。
NSString *mediaType = AVMediaTypeVideo; AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType]; if(authStatus == AVAuthorizationStatusAuthorized) { // do your logic } else if(authStatus == AVAuthorizationStatusDenied){ // denied } else if(authStatus == AVAuthorizationStatusRestricted){ // restricted, normally won't happen } else if(authStatus == AVAuthorizationStatusNotDetermined){ // not determined?! [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) { if(granted){ NSLog(@"Granted access to %@", mediaType); } else { NSLog(@"Not granted access to %@", mediaType); } }]; } else { // impossible, unknown authorization status }
从iOS 10开始,您需要在Info.plist中指定NSCameraUsageDescription
键,以便能够请求相机访问,否则您的应用程序将在运行时崩溃。 请参阅API要求使用说明 。
确保:
import AVFoundation
下面的Swift代码检查所有可能的权限状态:
斯威夫特3,4
let cameraMediaType = AVMediaTypeVideo let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: cameraMediaType) switch cameraAuthorizationStatus { case .denied: break case .authorized: break case .restricted: break case .notDetermined: // Prompting user for the permission to use the camera. AVCaptureDevice.requestAccess(forMediaType: cameraMediaType) { granted in if granted { print("Granted access to \(cameraMediaType)") } else { print("Denied access to \(cameraMediaType)") } } }
Swift 2.2
let cameraMediaType = AVMediaTypeVideo let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(cameraMediaType) switch cameraAuthorizationStatus { case .Denied: break case .Authorized: break case .Restricted: break case .NotDetermined: // Prompting user for the permission to use the camera. AVCaptureDevice.requestAccessForMediaType(cameraMediaType) { granted in if granted { print("Granted access to \(cameraMediaType)") } else { print("Denied access to \(cameraMediaType)") } } }
作为一个有趣的方面说明,你知道,如果iOS在应用程序中更改摄像头权限时正在运行,它将会终止应用程序?
从Apple开发者论坛:
如果用户在“设置”中切换应用对相机的访问权限,系统实际上会杀死您的应用。 这同样适用于Settings-> Privacy部分中的任何受保护的dataclass。
作为@Raptor答案的补充,应该提到以下内容。 从iOS 10开始,您可能会收到以下错误: This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
要解决这个问题,请确保您按照以下方式处理主线程的结果(Swift 3):
private func showCameraPermissionPopup() { let cameraMediaType = AVMediaTypeVideo let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: cameraMediaType) switch cameraAuthorizationStatus { case .denied: NSLog("cameraAuthorizationStatus=denied") break case .authorized: NSLog("cameraAuthorizationStatus=authorized") break case .restricted: NSLog("cameraAuthorizationStatus=restricted") break case .notDetermined: NSLog("cameraAuthorizationStatus=notDetermined") // Prompting user for the permission to use the camera. AVCaptureDevice.requestAccess(forMediaType: cameraMediaType) { granted in DispatchQueue.main.sync { if granted { // do something } else { // do something else } } } } }
Swift:使用AVFoundation
- 将AVFoundation添加到目标 – >构build阶段 – >与库链接二进制文件。
- 在ViewController上导入AVFoundation。
- 在Info.plist上,添加以下内容:
- 在视图控制器上:
@IBAction func cameraButtonClicked(sender:AnyObject){
let authorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) print(authorizationStatus.rawValue) if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) == AVAuthorizationStatus.Authorized{ self.openCameraAfterAccessGrantedByUser() } else { print("No Access") dispatch_async(dispatch_get_main_queue()) { [unowned self] in AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted :Bool) -> Void in if granted == true { // User granted self.openCameraAfterAccessGrantedByUser() } else { // User Rejected alertToEncourageCameraAccessWhenApplicationStarts() } }); } } //Open camera func openCameraAfterAccessGrantedByUser() { if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){ self.cameraAndGalleryPicker!.sourceType = UIImagePickerControllerSourceType.Camera cameraAndGalleryPicker?.delegate = self cameraAndGalleryPicker?.allowsEditing = false cameraAndGalleryPicker!.cameraCaptureMode = .Photo cameraAndGalleryPicker!.modalPresentationStyle = .FullScreen presentViewController(self.cameraAndGalleryPicker!, animated: true, completion: nil) } else { } } //Show Camera Unavailable Alert func alertToEncourageCameraAccessWhenApplicationStarts() { //Camera not available - Alert let cameraUnavailableAlertController = UIAlertController (title: "Camera Unavailable", message: "Please check to see if it is disconnected or in use by another application", preferredStyle: .Alert) let settingsAction = UIAlertAction(title: "Settings", style: .Destructive) { (_) -> Void in let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString) if let url = settingsUrl { dispatch_async(dispatch_get_main_queue()) { UIApplication.sharedApplication().openURL(url) } } } let cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil) cameraUnavailableAlertController .addAction(settingsAction) cameraUnavailableAlertController .addAction(cancelAction) self.window?.rootViewController!.presentViewController(cameraUnavailableAlertController , animated: true, completion: nil) }