ios 在iOS中检测相机的权限
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20464631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect permission of camera in iOS
提问by user418751
I am developing a very simple video app. I use the official control: UIImagePickerController.
我正在开发一个非常简单的视频应用程序。我使用官方控件:UIImagePickerController。
Here is the problem. When presenting the UIImagePickerController for the first time, the iOS will ask for the permission. The user can click yes or no. If the user clicks no, the control is not dismissed. Instead, if the user keeps clicking the start button, the timers go on while the screen is always black, and the user can't stop the timers or go back. The only thing the user can do is to kill the app. The next time the UIImagePickerController is presented, it is still a black screen and the user can't go back if clicking start.
这是问题所在。当第一次呈现 UIImagePickerController 时,iOS 会请求许可。用户可以单击是或否。如果用户单击“否”,则不会解除控件。相反,如果用户一直单击开始按钮,计时器会继续运行,而屏幕始终是黑色的,并且用户无法停止计时器或返回。用户唯一能做的就是杀死应用程序。下一次出现 UIImagePickerController 时,还是黑屏,点击开始就回不去了。
I was wondering if it's a bug. Is there any way we can detect the permission of the camera so that we can decide to show the UIImagePickerController or not?
我想知道这是不是一个错误。有什么方法可以检测相机的权限,以便我们可以决定是否显示 UIImagePickerController?
回答by Raptor
Check the AVAuthorizationStatus
and handle the cases properly.
检查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
}
回答by Nikita Kukushkin
Swift 4 and newer
Swift 4 及更新版本
Make sure to:
确保:
import AVFoundation
The code below checks for all possible permission states:
下面的代码检查所有可能的权限状态:
let cameraMediaType = AVMediaType.video
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: 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(for: cameraMediaType) { granted in
if granted {
print("Granted access to \(cameraMediaType)")
} else {
print("Denied access to \(cameraMediaType)")
}
}
}
Since iOS 10 you need to specify
NSCameraUsageDescription
key in your Info.plist to be able ask for camera access, otherwise your app will crash at runtime. See APIs Requiring Usage Descriptions.
从 iOS 10 开始,您需要NSCameraUsageDescription
在 Info.plist 中指定
key 才能请求相机访问,否则您的应用程序将在运行时崩溃。请参阅需要使用说明的 API。
As an interesting side note, did you know that iOS kills the app if it's running while you change its camera permissions in Settings?
作为一个有趣的旁注,您是否知道当您在“设置”中更改其相机权限时,iOS 会杀死正在运行的应用程序?
From Apple Developer forum:
来自苹果开发者论坛:
The system actually kills your app if the user toggles your app's access to camerain Settings. The same applies to any protected dataclass in the Settings→Privacy section.
如果用户在“设置”中切换您的应用程序对相机的访问权限,系统实际上会终止您的应用程序。这同样适用于设置→隐私部分中的任何受保护数据类。
回答by Josh Bernfeld
Swift Solution
快速解决方案
extension AVCaptureDevice {
enum AuthorizationStatus {
case justDenied
case alreadyDenied
case restricted
case justAuthorized
case alreadyAuthorized
case unknown
}
class func authorizeVideo(completion: ((AuthorizationStatus) -> Void)?) {
AVCaptureDevice.authorize(mediaType: AVMediaType.video, completion: completion)
}
class func authorizeAudio(completion: ((AuthorizationStatus) -> Void)?) {
AVCaptureDevice.authorize(mediaType: AVMediaType.audio, completion: completion)
}
private class func authorize(mediaType: AVMediaType, completion: ((AuthorizationStatus) -> Void)?) {
let status = AVCaptureDevice.authorizationStatus(for: mediaType)
switch status {
case .authorized:
completion?(.alreadyAuthorized)
case .denied:
completion?(.alreadyDenied)
case .restricted:
completion?(.restricted)
case .notDetermined:
AVCaptureDevice.requestAccess(for: mediaType, completionHandler: { (granted) in
DispatchQueue.main.async {
if granted {
completion?(.justAuthorized)
} else {
completion?(.justDenied)
}
}
})
@unknown default:
completion?(.unknown)
}
}
}
And then in order to use it you do
然后为了使用它你做
AVCaptureDevice.authorizeVideo(completion: { (status) in
//Your work here
})
回答by Bart van Kuik
As an addition to the answer from @Raptor the following should be mentioned. You may receive the following error starting with 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.
作为@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.
To fix this, make sure you handle the results from the main thread as follows (Swift 3):
要解决此问题,请确保按如下方式处理主线程的结果(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
}
}
}
}
}
回答by Yogendra Singh
Specify NSCameraUsageDescription key in Info.plist first. Then check AVAuthorizationStatus if Authorised then present the UIImagePickerController. It will work.
首先在 Info.plist 中指定 NSCameraUsageDescription 键。然后检查 AVAuthorizationStatus 如果已授权,则显示 UIImagePickerController。它会起作用。
回答by A.G
Swift: Using AVFoundation
Swift:使用 AVFoundation
- Add AVFoundation to Target -> Build Phases -> Link Binary with Libraries.
- import AVFoundation on ViewController.
- On Info.plist, Add the following:
- 将 AVFoundation 添加到 Target -> Build Phases -> Link Binary with Libraries。
- 在 ViewController 上导入 AVFoundation。
- 在 Info.plist 上,添加以下内容:
- On View Controller:
- 在视图控制器上:
@IBAction func cameraButtonClicked(sender: AnyObject) {
@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)
}