在 iOS 8 中显示相机权限对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25803217/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:24:04  来源:igfitidea点击:

Presenting camera permission dialog in iOS 8

iospermissionscameraios8ios-permissions

提问by jamix

When my app tries to access the camera for the first time on iOS 8, the user is presented with a camera permission dialog, much like the microphone one for microphone access in iOS 7.

当我的应用程序第一次尝试在 iOS 8 上访问摄像头时,用户会看到一个摄像头权限对话框,很像 iOS 7 中用于麦克风访问的麦克风对话框。

In iOS 7, it was possible to invoke the microphone permission dialog beforehand and see if the permission was granted (see this question, for example). Is there a similar way to invoke the camera permission dialog in iOS 8? Can the dialog be combined for microphone AND camera access permission?

在 iOS 7 中,可以预先调用麦克风权限对话框并查看是否授予权限(例如,请参阅此问题)。是否有类似的方法可以在 iOS 8 中调用相机权限对话框?对话是否可以结合麦克风和摄像头访问权限?

回答by jamix

Here is the approach we ended up using:

这是我们最终使用的方法:

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];
}

回答by SmokersCough

I'm running into a similar issue, if the user has denied camera access when they are first prompted, pressing the button to take a snap shot results in a black screen in the camera mode.

我遇到了类似的问题,如果用户在第一次收到提示时拒绝了相机访问,按下按钮拍摄快照会导致在相机模式下出现黑屏。

However i want to detect that the user has declined access and prompt them it must be turned on but i can't find any functions to check the current user camera access, is there such a function?

但是我想检测到用户拒绝访问并提示他们必须打开它但我找不到任何功能来检查当前用户的相机访问,是否有这样的功能?

EDIT: The following check will let you know in IOS 8 about camera access:

编辑:以下检查将让您在 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

            }
        }];
    }

This information was found on the following question (How to know that application have camera access or not programmatically in iOS8):

此信息是在以下问题中找到的(How to know that application has camera access or not programmatically in iOS8):

回答by DogCoffee

Here is my Swift Solution (iOS 8), I needed the camera for QR scanning so really had to prompt its use.

这是我的 Swift 解决方案 (iOS 8),我需要使用相机进行 QR 扫描,因此必须提示其使用。

This provides

这提供了

  1. Encourage the user to select allow if prior to the default allow camera access question

  2. Easy way to access settings if the user denied the first request.

  1. 鼓励用户在默认允许相机访问问题之前选择允许

  2. 如果用户拒绝了第一个请求,则可以轻松访问设置。

To get it running call check camera in ViewDidAppear / or ViewDidLoad etc. I needed to use viewDidAppear so my custom camera views constraints were set up.

为了让它在 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)
}

Thanks to jamix above for the tip for using dispatch_async - makes the response to show the newly set camera function so much faster.

感谢上面的 jamix 提供了使用 dispatch_async 的提示 - 使显示新设置的相机功能的响应速度更快。

Sorry for a mix of trailing closures.. wanted to try them out.

很抱歉混合了尾随闭包……想尝试一下。

回答by Crashalot

None of the answers seem to check for both microphone and camera permissions. Our code checks against the scenario where camera permissions are granted but microphone access is denied.

似乎没有一个答案会检查麦克风和相机权限。我们的代码检查授予相机权限但拒绝麦克风访问的场景。

Since we're new to Swift, it's unlikely the gnarly nested closures and ifstatements are optimal. Please share suggestions for improving the code! But at least it works so far in testing.

由于我们是 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
        }
    })

回答by Sourabh Sharma

  • Swift 3.0 Solution

    import AVFoundation

  • Swift 3.0 解决方案

    导入 AVFoundation

Note:add Privacy - Camera Usage Description key on your Info.plist

注意:在 Info.plist 上添加 Privacy - Camera Usage Description 键

//MARK: Camera Handling

//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)
        }

回答by pableiros

For Swift 3, you can add this on your viewWillAppearmethod of your first view controller:

对于 Swift 3,您可以将其添加到您viewWillAppear的第一个视图控制器的方法中:

First import the AVFoundationframework

首先导入AVFoundation框架

import AVFoundation

Then:

然后:

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")

    }
}

Don't forget to add Privacy - Camera Usage Descriptionkey on your Info.plist

不要忘记Privacy - Camera Usage Description在您的Info.plist

回答by confile

For me this work on iOS7 and iOS8:

对我来说,iOS7 和 iOS8 上的这项工作:

    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];

    switch (status) {
        case ALAuthorizationStatusAuthorized:
            break;

        case ALAuthorizationStatusRestricted:
        case ALAuthorizationStatusDenied:
            break;

        case ALAuthorizationStatusNotDetermined:
            break;
    }

回答by A.G

I make an access check on the app delegate.

我对应用程序委托进行了访问检查。

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)
                })
            }
        }

*

*

回答by Chris Wagner

The issue for me was that Bundle nameand Bundle Display Namewere not getting set in my Info.plist due to some recent build configuration changes. Kind of an unlikely case... But it took me a few hours to nail this down. Hopefully it helps for someone else.

对我来说,问题是,Bundle nameBundle Display Name没有得到我的Info.plist设置由于一些最新内部配置更改。有点不太可能的情况……但我花了几个小时才确定下来。希望它对其他人有所帮助。