在iOS 8中显示相机权限对话框
当我的应用程序尝试在iOS 8上首次访问摄像头时,会向用户展示摄像头权限对话框,就像iOS 7中用于麦克风访问的麦克风一样。
在iOS 7中,可以预先调用麦克风权限对话框,并查看权限是否被授予(例如,请参阅此问题 )。 有没有类似的方式来调用iOS 8的摄像头权限对话框? 话筒和摄像头访问权限可以组合在一起吗?
以下是我们最终使用的方法:
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]; }
我遇到了类似的问题,如果用户在第一次提示时拒绝摄像头访问,按下button拍摄快照会导致摄像头模式中出现黑屏。
不过,我想检测到用户拒绝访问,并提示他们必须打开,但我找不到任何function来检查当前用户的相机访问,有没有这样的function?
编辑:下面的检查将让你知道在IOS 8关于相机访问:
#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 } }]; }
这个信息是在以下问题上find的( 如何知道应用程序在iOS8中是否有相机访问权限 ):
这里是我的Swift解决scheme(iOS 8),我需要相机进行QR扫描,所以真的必须提示它的使用。
这提供了
-
鼓励用户在默认允许摄像头访问问题之前select允许
-
如果用户拒绝第一个请求,则可以轻松访问设置。
为了让它运行在ViewDidAppear /或ViewDidLoad等呼叫检查相机我需要使用viewDidAppear,所以我的自定义相机视图约束设置。
func checkCamera() { let authStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) switch authStatus { case .Authorized: break // Do your stuff here ie 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.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!) })) presentViewController(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.devicesWithMediaType(AVMediaTypeVideo).count > 0 { AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo) { granted in dispatch_async(dispatch_get_main_queue()) { self.checkCamera() } } } } ) presentViewController(alert, animated: true, completion: nil) }
感谢上面的jamix使用dispatch_async的提示 – 使响应更快地显示新设置的相机function。
对不起,结尾倒闭的混合..想试试看。
没有一个答案似乎检查麦克风和相机的权限。 我们的代码检查相机权限被授予的场景,但麦克风访问被拒绝。
由于我们是Swift的新手,所以不太可能是粗糙的嵌套closures和if
语句是最优的。 请分享改进代码的build议! 但至less它在testing中起作用。
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 } })
-
Swift 3.0解决scheme
导入AVFoundation
注意:在您的Info.plist上添加隐私 – 照相机使用说明键
// MARK:相机处理
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 ie 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) }
对于我来说这个在iOS7和iOS8上的工作:
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; switch (status) { case ALAuthorizationStatusAuthorized: break; case ALAuthorizationStatusRestricted: case ALAuthorizationStatusDenied: break; case ALAuthorizationStatusNotDetermined: break; }
对于Swift 3,你可以在你的第一个视图控制器的viewWillAppear
方法上添加这个:
首先导入AVFoundation
框架
import AVFoundation
然后:
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") } }
不要忘记在Info.plist
上添加Privacy - Camera Usage Description
键
我对应用程序委托进行访问检查。
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) }) } }
*
我的问题是Bundle name
和Bundle Display Name
没有被设置在我的Info.plist中,这是由于一些最近的构buildconfiguration改变。 一种不太可能的情况…但是,我花了几个小时才明白这一点。 希望它可以帮助别人。