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

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

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


person jamix    schedule 12.09.2014    source источник
comment
Просто опубликовал ответ, который проверяет доступ к камере и микрофону и улавливает сценарий, в котором разрешения камеры предоставляются, а разрешения микрофона - нет.   -  person Crashalot    schedule 07.07.2015


Ответы (9)


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

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];
}
person jamix    schedule 27.09.2014
comment
Небольшой комментарий - метод requestAccessForMediaType присутствует и в iOS 7 (в то время iOS требовал разрешения камеры только в некоторых регионах). так что часть else относится к ‹iOS 6. - person Niraj; 31.10.2014
comment
Обновил комментарии к коду, чтобы они стали немного более информативными / правильными после некоторого собственного тестирования. - person Stunner; 05.01.2015
comment
В наших тестах этот код не улавливает сценарий, в котором разрешения камеры предоставляются, а разрешения микрофона запрещены. - person Crashalot; 07.07.2015
comment
Этот код предназначен только для разрешений камеры, что является предметом исходного вопроса. - person jamix; 07.07.2015
comment
Для iOS 10+ Не забудьте поместить NSCameraUsageDescription в свой список вместе с целью запроса разрешения. Если вы этого не сделаете, произойдет сбой. - person Jordan Hochstetler; 02.03.2017

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

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

РЕДАКТИРОВАТЬ: следующая проверка позволит вам узнать в 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):

person SmokersCough    schedule 23.09.2014

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

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

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

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

Чтобы запустить камеру проверки вызовов в 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 - делает ответ, чтобы показать недавно установленную функцию камеры, намного быстрее.

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

person DogCoffee    schedule 27.06.2015
comment
Я здесь придирчив / любопытен, но почему вы устанавливаете style: .Default для кнопки Cancel и style: .Cancel для кнопки other? Это просто ошибка или вы делаете это специально? - person SaltyNuts; 17.07.2015
comment
Думаю, я просто хотел, чтобы один выделялся больше, чем другой, вот и все. Как жирный шрифт и обычный шрифт. - person DogCoffee; 17.07.2015
comment
@DogCoffee Я немного смущен запросом разрешения для доступа к камере изначально. Разве это не что-то встроенное в iOS, что разработчики не могут имитировать? Мы можем только проверить, было ли это отклонено раньше, а затем предложить обновить в настройках ?? - person user2363025; 27.10.2015
comment
Я сделал это некоторое время назад, приложению требовалась камера для моего QR-ридера. iOS спрашивает, можно ли использовать камеру. Я просто хотел, чтобы пользователь знал, почему. В большинстве случаев, когда что-то всплывает с просьбой о том или о том, что я знаю сам, я обычно сначала отказываюсь. Это был всего лишь мой способ сказать - хорошо, пожалуйста, примите. - person DogCoffee; 27.10.2015
comment
@DogCoffee. Итак, мне не нужно создавать функцию для запроса разрешения на первый доступ, я могу позволить iOS делать это в фоновом режиме, и мне просто нужно позаботиться о том, отказывали ли они в разрешениях в прошлом? - person user2363025; 27.10.2015
comment
@ user2363025 полностью зависит от вас. Попробуйте себя, и если рабочий процесс имеет смысл, то ничего страшного. Но если вам нужна камера и пользователь выбрал не разрешать камеру, вы должны учитывать это, иначе ваше приложение выйдет из строя. - person DogCoffee; 28.10.2015

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

Поскольку мы новички в 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
        }
    })
person Crashalot    schedule 07.07.2015
comment
Только ответ, который касается разрешений как для видео, так и для звука. Боковое примечание, для меня безумие, что вы не можете попросить оба этих сочетания, спасибо, яблоко. - person lostintranslation; 27.05.2016
comment
Это правильный ответ. Для видеозаписи это критично, иначе система сама запустит права доступа к аудио при инициализации сеанса. Тогда ваше приложение не узнает об этом, и это существенно ограничивает возможности пользователя. Я заметил, что многие проекты просто игнорируют это, и, боже мой, это генерирует большое количество заявок в службу поддержки :) - person Ryan Romanchuk; 06.07.2018

  • Решение 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)
        }
person Sourabh Sharma    schedule 22.12.2016
comment
Вы поменяли методы ;-) 'via setting' запускает диалог perm, а второй запускает настройки :-) - person matrejek; 06.10.2017

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

person pableiros    schedule 14.11.2016

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

    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];

    switch (status) {
        case ALAuthorizationStatusAuthorized:
            break;

        case ALAuthorizationStatusRestricted:
        case ALAuthorizationStatusDenied:
            break;

        case ALAuthorizationStatusNotDetermined:
            break;
    }
person confile    schedule 02.03.2015
comment
Работает как часы. Не забывайте импорт: #import <AssetsLibrary/AssetsLibrary.h> - person Jonathan F.; 12.08.2015
comment
Больше не работает в IOS 9, так как ALAssetsLibrary устарела. - person Supertecnoboff; 07.10.2015

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

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

*

person A.G    schedule 29.10.2015

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

person Chris Wagner    schedule 19.08.2016