İOS'ta kamera iznini algılama


143

Çok basit bir video uygulaması geliştiriyorum. Resmi kontrolü kullanıyorum: UIImagePickerController.

İşte sorun. UIImagePickerController'ı ilk kez sunarken, iOS izin isteyecektir. Kullanıcı evet veya hayır'ı tıklayabilir. Kullanıcı no'yu tıklatırsa, denetim reddedilmez. Bunun yerine, kullanıcı başlat düğmesini tıklamaya devam ederse, ekran her zaman siyahken zamanlayıcılar devam eder ve kullanıcı zamanlayıcıları durduramaz veya geri dönemez. Kullanıcının yapabileceği tek şey uygulamayı öldürmektir. UIImagePickerController bir dahaki sefere sunulduğunda, hala siyah bir ekran ve başlat'ı tıklarsa kullanıcı geri dönemez.

Bunun bir hata olup olmadığını merak ediyordum. UIImagePickerController'ı göstermeye karar verebilmemiz için kameranın iznini tespit edebilmemizin bir yolu var mı?


Re: bir hata mı? IMHO, sanırım, çünkü görünen o ki VC donanımdan veri gösteriyor, ancak işletim sistemi temelde ölü hava gönderiyor. İOS'un buraya nasıl geldiği muhtemelen ürün ailesinin evriminin bir yan etkisidir. UIImageViewControlleriOS 2.0'da eklendiği belirtiliyor ve dokümanlar hiçbir zaman AVAuthorizationStatus'un kullanılması gerektiğini yansıtacak şekilde açıklanmadı, ancak başka bir çerçevede yaşıyor.
benc

Yanıtlar:


229

Kutuları kontrol edin AVAuthorizationStatusve uygun şekilde kullanın.

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
}

19
Ayrıca gerektirir: #import <AVFoundation/AVFoundation.h>veya benzeri
toblerpwn

9
Muhtemelen yararlı bir ipucu - bunu kullanan kodu test ediyorsanız, Uygulamanızı test cihazından silip yeniden yükleyemezsiniz. Bunu yapmak, iOS'un isteği kullanıcıya yeniden göndermesine neden olmaz! Benim için işe yarayan şey, bunu Bundle IDher test etmek istediğimde uygulamanın değiştirilmesidir . Serseri bir ağrı, ama en azından bir şey. İşiniz bittiğinde kimliği yeniden ayarlamayı unutmayın ;-)
Benjohn

25
@ Benjohn: Paket Kimliğini değiştirmek gereksizdir. Ayarlar> Genel> Sıfırla'ya gidebilir ve cihazdaki tüm izin istemlerini sıfırlayacak bir ayar bulabilirsiniz. Ayrıca, cihazınızdaki diğer tüm uygulamaları da etkilediği için bu da sinir bozucu. Yalnızca Apple bunun için uygulamalara özel kontroller ekleyebilirse Settings.app ...
KennyDeriemaeker

3
@KennyDeriemaeker :-) Apple test için özel cihazlar kullanmamız gerektiğini söyleyebilir! Benim için normal telefonumu sıfırlamanın yan etkileri oldukça berbat olurdu. Paket kimliğini değiştirmek oldukça acısız bir alternatifti. Ben de göndermeden önce geri değiştirmek hatırladı :-)
Benjohn

8
Sadece tam sıfırlama yapmadığınızdan emin olun! Gizlilik ve Konum ayarlarını (iOS 8) sıfırlamak yeterli olacaktır.
Canucklesandwich

81

Swift 4 ve daha yenisi

Emin ol:

import AVFoundation

Aşağıdaki kod tüm olası izin durumlarını kontrol eder:

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

İOS 10'dan beri NSCameraUsageDescription, kamera erişimi isteyebilmek için Info.plist'inizde bir anahtar belirtmeniz gerekir , aksi takdirde uygulamanız çalışma zamanında kilitlenir. Bkz . Kullanım Açıklamaları Gerektiren API'lar .


İlginç bir yan not olarak, Ayarlar'daki kamera izinlerini değiştirirken iOS'un uygulamayı çalıştırdığını öldürdüğünü biliyor muydunuz?

Apple Developer forumundan:

Kullanıcı, uygulamanızın Kamera'ya erişimini Ayarlar'da değiştirirse sistem aslında uygulamanızı öldürür . Aynısı Ayarlar → Gizlilik bölümündeki tüm korumalı veri türleri için de geçerlidir.


Kamera ve fotoğraf galerisini yetkilendirmeye ne dersiniz?
Hajar ELKOUMIKHI

4

Hızlı Çözüm

extension AVCaptureDevice {
    enum AuthorizationStatus {
        case justDenied
        case alreadyDenied
        case restricted
        case justAuthorized
        case alreadyAuthorized
        case unknown
    }

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

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

    private class func authorize(mediaType: AVMediaType, completion: ((AuthorizationStatus) -> Void)?) {
        let status = AVCaptureDevice.authorizationStatus(for: mediaType)
        switch status {
        case .authorized:
            completion?(.alreadyAuthorized)
        case .denied:
            completion?(.alreadyDenied)
        case .restricted:
            completion?(.restricted)
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: mediaType, completionHandler: { (granted) in
                DispatchQueue.main.async {
                    if granted {
                        completion?(.justAuthorized)
                    } else {
                        completion?(.justDenied)
                    }
                }
            })
        @unknown default:
            completion?(.unknown)
        }
    }
}

Ve sonra onu kullanmak için

AVCaptureDevice.authorizeVideo(completion: { (status) in
   //Your work here
})

Kamera ve fotoğraf galerisini yetkilendirmeye ne dersiniz?
Hajar ELKOUMIKHI

2

@ Raptor'un cevabına ek olarak aşağıdakilerden bahsedilmelidir. İOS 10'dan başlayarak aşağıdaki hatayı alabilirsiniz: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.

Bunu düzeltmek için, ana iş parçasındaki sonuçları aşağıdaki gibi işlediğinizden emin olun (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
                }
            }
        }
    }
}

Reddedilirse, requestAccess yöntemi çalışmaz. Kullanıcının ayarlara gitmesini ve izin vermesini istemek için manuel olarak bir uyarı göstermeniz gerekir.
Abdullah Umer

0

Önce Info.plist'te NSCameraUsageDescription anahtarını belirtin. Ardından Yetkilendirilmişse AVAuthorizationStatus'u kontrol edin ve ardından UIImagePickerController'ı gösterin. Çalışacak.


-4

Swift: AVFoundation'ı kullanma

  1. AVFoundation'ı Hedef -> Derleme Aşamaları -> İkili Kitaplıklarıyla Bağlantıya ekleyin.
  2. AVFoundation'ı ViewController'a aktarın.
  3. Info.plist'de aşağıdakileri ekleyin:

resim açıklamasını buraya girin

  1. On View Denetleyici:

@IBAction func cameraButtonClicked (gönderen: 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)
}

Info.plist girişleri nedir? Kaynak?
Bill
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.