Представление диалогового окна разрешения камеры в iOS 8

Когда мое приложение впервые пытается получить доступ к камере в iOS 8, пользователю предоставляется диалог разрешения камеры, похожий на микрофон для доступа к микрофону в iOS 7.

В iOS 7 можно было предварительно вызвать диалог разрешения микрофона и посмотреть, было ли предоставлено разрешение (см. этот вопрос). Есть ли аналогичный способ вызвать диалог разрешения камеры в iOS 8? Можно ли объединить диалог для разрешения доступа к микрофону и камеры?

Ответ 1

Вот такой подход, в результате которого мы использовали:

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

Ответ 2

Я столкнулся с подобной проблемой, если пользователь отказал в доступе камеры при первом запросе, нажав кнопку, чтобы сделать мгновенный снимок, получается черный экран в режиме камеры.

Однако я хочу обнаружить, что пользователь отказался от доступа и запросил их, он должен быть включен, но я не могу найти какие-либо функции для проверки доступа к текущей пользовательской камере, есть ли такая функция?

EDIT: следующая проверка сообщит вам в 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

            }
        }];
    }

Эта информация была найдена по следующему вопросу (Как узнать, что у приложения есть доступ к камере или нет программно в iOS8):

Ответ 3

Вот мое быстрое решение (iOS 8), мне нужна была камера для сканирования QR, поэтому ей действительно нужно было предложить ее использовать.

Это обеспечивает

  • Поощряйте пользователя выбирать, разрешать ли до разрешения по умолчанию вопрос о доступе к телефону

  • Простой способ получить доступ к настройкам, если пользователь отказал в первом запросе.

Чтобы запустить камеру проверки вызовов в ViewDidAppear/или ViewDidLoad и т.д. Мне нужно было использовать viewDidAppear, чтобы были настроены ограничения для пользовательских камер.

func checkCamera() {
    let authStatus = AVCaptureDevice.authorizationStatusForMediaType(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.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 - делает ответ, чтобы показать вновь установленную функцию камеры намного быстрее.

Извините за сочетание трейлинг-закрытий.. хотел попробовать их.

Ответ 4

Кажется, что ни один из ответов не проверяет разрешения для микрофона и камеры. Наш код проверяет сценарий, в котором разрешены разрешения камеры, но доступ к микрофонам запрещен.

Поскольку мы новичок в 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
        }
    })

Ответ 5

  • Решение 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)
        }

Ответ 6

Для меня эта работа на iOS7 и iOS8:

    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];

    switch (status) {
        case ALAuthorizationStatusAuthorized:
            break;

        case ALAuthorizationStatusRestricted:
        case ALAuthorizationStatusDenied:
            break;

        case ALAuthorizationStatusNotDetermined:
            break;
    }

Ответ 7

Я делаю проверку доступа к делегату приложения.

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

*

Ответ 8

Для 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

Ответ 9

Проблема для меня заключалась в том, что Bundle name и Bundle Display Name не были установлены в моем Info.plist из-за недавних изменений конфигурации сборки. Вид маловероятного случая... Но мне потребовалось несколько часов, чтобы прибить это. Надеюсь, это поможет кому-то другому.