当我的应用程序第一次尝试在 iOS 8 上访问摄像头时,用户会看到一个摄像头权限对话框,就像 iOS 7 中用于麦克风访问的麦克风一样。
在 iOS 7 中,可以事先调用麦克风权限对话框并查看是否授予了权限(例如,请参阅此问题)。在 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];
}
我遇到了类似的问题,如果用户在第一次收到提示时拒绝了相机访问,按下按钮拍摄快照会导致相机模式下出现黑屏。
但是我想检测用户拒绝访问并提示他们必须打开它但我找不到任何功能来检查当前用户的相机访问,有没有这样的功能?
编辑:以下检查将让您在 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
}
}];
}
此信息是在以下问题中找到的(How to know that application have camera access or not programmatically in iOS8):
这是我的 Swift 解决方案(iOS 8),我需要使用相机进行 QR 扫描,因此必须提示使用它。
这提供了
鼓励用户在默认允许摄像头访问问题之前选择允许
如果用户拒绝了第一个请求,则可以轻松访问设置。
为了让它在 ViewDidAppear / 或 ViewDidLoad 等中运行调用检查相机。我需要使用 viewDidAppear 以便设置我的自定义相机视图约束。
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)
}
感谢上面的 jamix 使用 dispatch_async 的提示 - 使得显示新设置的相机功能的响应更快。
很抱歉混合了尾随关闭..想尝试一下。
似乎没有一个答案同时检查麦克风和摄像头权限。我们的代码针对授予相机权限但拒绝麦克风访问的场景进行检查。
由于我们是 Swift 新手,因此粗糙的嵌套闭包和if
语句不太可能是最佳的。请分享改进代码的建议!但至少到目前为止它在测试中有效。
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 解决方案
导入 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 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)
}
对于 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")
}
}
不要忘记Privacy - Camera Usage Description
在您的Info.plist
对我来说,这项工作适用于 iOS7 和 iOS8:
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusAuthorized:
break;
case ALAuthorizationStatusRestricted:
case ALAuthorizationStatusDenied:
break;
case ALAuthorizationStatusNotDetermined:
break;
}
我对应用程序委托进行访问检查。
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 中没有设置。有点不太可能的情况......但我花了几个小时才确定这一点。希望它对其他人有帮助。