Wykrywanie uprawnień kamery w systemie iOS

Rozwijam bardzo prostą aplikację wideo. Używam oficjalnej kontroli: UIImagePickerController.

Oto problem. Podczas prezentacji interfejsu UIImagePickerController po raz pierwszy, iOS poprosi o pozwolenie. Użytkownik może kliknąć TAK lub nie. Jeśli użytkownik kliknie nie, Kontrola nie zostanie odrzucona. Zamiast tego, jeśli użytkownik nadal kliknie przycisk start, liczniki włączają się, gdy ekran jest zawsze czarny, a użytkownik nie może zatrzymać liczników ani cofnąć. Jedyne co użytkownik może zrobić to zabić aplikację. Następnym razem, gdy UIImagePickerController jest przedstawiony, nadal jest czarny ekran i użytkownik nie może wrócić, jeśli kliknięcie start.

Zastanawiałem się, czy to błąd. Czy jest jakiś sposób możemy wykryć uprawnienia kamery tak, że możemy zdecydować się pokazać UIImagePickerController lub nie?

Author: Cœur, 2013-12-09

6 answers

Sprawdź AVAuthorizationStatus i zajmij się sprawami prawidłowo.

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
}
 206
Author: Raptor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-23 17:04:04

Od iOS 10 musisz określić NSCameraUsageDescription klucz w informacji.plist, aby móc poprosić o dostęp do kamery, w przeciwnym razie aplikacja zawiesi się w czasie wykonywania. Zobacz API Wymagające Opisów Użycia .


Upewnij się, że:

import AVFoundation

Poniższy kod Swift sprawdza wszystkie możliwe Stany uprawnień:

Swift 4

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

Swift 3

let cameraMediaType = AVMediaTypeVideo
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: 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(forMediaType: cameraMediaType) { granted in
        if granted {
            print("Granted access to \(cameraMediaType)")
        } else {
            print("Denied access to \(cameraMediaType)")
        }
    }
}

Swift 2.2

let cameraMediaType = AVMediaTypeVideo
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(cameraMediaType)

switch cameraAuthorizationStatus {
case .Denied: break
case .Authorized: break
case .Restricted: break

case .NotDetermined:
    // Prompting user for the permission to use the camera.
    AVCaptureDevice.requestAccessForMediaType(cameraMediaType) { granted in
        if granted {
            print("Granted access to \(cameraMediaType)")
        } else {
            print("Denied access to \(cameraMediaType)")
        }
    }
}

Jako ciekawostkę, Czy wiesz, że iOS zabija aplikację, jeśli jest działa podczas zmiany uprawnień aparatu w Ustawieniach?

Z forum programistów Apple:

System faktycznie zabija aplikację, jeśli użytkownik włącza aplikację dostęp do kamery w Ustawieniach. To samo dotyczy wszelkich chronionych dataclass w sekcji Ustawienia → Prywatność.

 69
Author: Nikita Kukushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 14:07:25
extension AVCaptureDevice {
    enum AuthorizationStatus {
        case justDenied
        case alreadyDenied
        case restricted
        case justAuthorized
        case alreadyAuthorized
    }

    class func authorizeVideo(completion: ((AuthorizationStatus) -> Void)?) {
        AVCaptureDevice.authorize(mediaType: AVMediaTypeVideo, completion: completion)
    }

    class func authorizeAudio(completion: ((AuthorizationStatus) -> Void)?) {
        AVCaptureDevice.authorize(mediaType: AVMediaTypeAudio, completion: completion)
    }

    private class func authorize(mediaType: String, completion: ((AuthorizationStatus) -> Void)?) {
        let status = AVCaptureDevice.authorizationStatus(forMediaType: mediaType)
        switch status {
        case .authorized:
            completion?(.alreadyAuthorized)
        case .denied:
            completion?(.alreadyDenied)
        case .restricted:
            completion?(.restricted)
        case .notDetermined:
            AVCaptureDevice.requestAccess(forMediaType: mediaType, completionHandler: { (granted) in
                if(granted) {
                    completion?(.justAuthorized)
                }
                else {
                    completion?(.justDenied)
                }
            })
        }
    }
}

A następnie, aby go użyć, robisz

AVCaptureDevice.authorizeVideo(completion: { (status) in
   //Your work here
})
 1
Author: Josh Bernfeld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-06 03:33:31

Jako uzupełnienie odpowiedzi od @ Raptor należy wymienić: W systemie iOS może pojawić się następujący błąd 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.

Aby to naprawić, upewnij się, że obsługujesz wyniki z głównego wątku w następujący sposób (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
                }
            }
        }
    }
}
 0
Author: Bart van Kuik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-08 09:42:54

Określ klucz NSCameraUsageDescription w Info.plist pierwszy. Następnie sprawdź AVAuthorizationStatus jeśli jest autoryzowany, a następnie przedstaw interfejs użytkownika. To zadziała.

 0
Author: Yogendra Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-27 13:29:12

Swift: Using AVFoundation

  1. Dodaj AVFoundation do Target - > Build Phases - > Link Binary with Libraries.
  2. Importuj AVFoundation w ViewController.
  3. Na Info.plist, dodaj:

Tutaj wpisz opis obrazka

  1. On View Controller:

@ 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)
}
 -5
Author: A.G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-08 04:58:26