iOS에서 카메라 권한 감지


143

매우 간단한 비디오 앱을 개발 중입니다. 나는 공식 컨트롤을 사용합니다 : UIImagePickerController.

여기에 문제가 있습니다. UIImagePickerController를 처음으로 제시하면 iOS에서 권한을 요청합니다. 사용자는 예 또는 아니오를 클릭 할 수 있습니다. 사용자가 아니오를 클릭하면 제어가 해제되지 않습니다. 대신 사용자가 시작 버튼을 계속 클릭하면 화면이 항상 검은 색인 동안 타이머가 켜지고 타이머를 중지하거나 되돌아 갈 수 없습니다. 사용자가 할 수있는 유일한 일은 앱을 종료하는 것입니다. 다음에 UIImagePickerController가 표시 될 때 여전히 검은 색 화면이며 시작을 클릭하면 사용자가 되돌아 갈 수 없습니다.

버그인지 궁금합니다. UIImagePickerController를 표시할지 여부를 결정할 수 있도록 카메라의 권한을 감지 할 수있는 방법이 있습니까?


다시 : 버그입니까? IMHO는 그렇게 생각하기 때문에 VC가 하드웨어의 데이터를 표시하지만 OS는 기본적으로 데드 에어를 전송하기 때문입니다. iOS의 등장은 아마도 제품군의 진화에 따른 부작용 일 것입니다. UIImageViewController는 iOS 2.0에 추가 된 것으로 알려져 있으며 문서는 AVAuthorizationStatus를 사용해야한다는 것을 반영하기 위해 주석을 달지 않았지만 다른 프레임 워크에 있습니다.
21:07에

답변:


229

를 확인하고 AVAuthorizationStatus케이스를 올바르게 처리하십시오.

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
또한 필요합니다 : #import <AVFoundation/AVFoundation.h>또는 이와 유사한
toblerpwn

9
유용한 팁 –이 코드를 사용하는 코드를 테스트하는 경우 테스트 장치에서 앱을 삭제 한 다음 다시 설치할 수는 없습니다. 이렇게하면 iOS가 사용자에게 요청을 다시 발행하지 않습니다! 그래도 나를 위해 일한 것은 Bundle ID이것을 테스트 할 때마다 앱의 버전 을 변경하는 것 입니다. 엉덩이에 통증이 있지만 적어도 무언가. 완료되면 ID를 다시 설정하십시오. ;-)
Benjohn

25
@ Benjohn : 번들 ID를 변경할 필요가 없습니다. 당신은 갈 수 > 설정> 일반 재설정 및 장치의 모든 권한 프롬프트를 다시 설정하는 설정을 찾을 수 있습니다. 물론, 그것은 장치의 다른 모든 앱에도 영향을 미치기 때문에 성가시다. 단지 애플은 ... Settings.app의 개발 섹션에이 용 앱 고유의 컨트롤을 추가 할 수 있다면
KennyDeriemaeker

3
@KennyDeriemaeker :-) Apple은 테스트를 위해 전용 장치를 사용해야한다고 대답 할 수도 있습니다! 나를 위해 내 일반 전화를 재설정의 부작용은 꽤 짜증 났을 것입니다. 번들 ID 변경은 상당히 고통스러운 대안이었습니다. 제출하기 전에 다시 변경 한 것을 기억했습니다 :-)
Benjohn

8
완전 재설정을하지 마십시오! 개인 정보 및 위치 설정 (iOS 8)을 재설정하면 충분합니다.
Canucklesandwich

81

스위프트 4 이상

다음을 확인하십시오 :

import AVFoundation

아래 코드는 가능한 모든 권한 상태를 확인합니다.

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

iOS 10부터 NSCameraUsageDescription카메라 액세스를 요청하려면 Info.plist에서 키 를 지정해야합니다 . 그렇지 않으면 앱이 런타임에 중단됩니다. 사용법 설명이 필요한 API를 참조하십시오 .


흥미로운 부수적으로, 설정에서 카메라 권한을 변경하는 동안 iOS가 앱을 실행하면 앱이 종료된다는 것을 알고 있습니까?

Apple 개발자 포럼에서 :

사용자 가 설정에서 앱의 카메라 액세스를 전환하면 시스템이 실제로 앱 을 종료합니다. 설정 → 개인 정보 섹션의 보호 된 데이터 클래스에도 동일하게 적용됩니다.


카메라 및 사진 갤러리 인증은 어떻습니까?
Hajar ELKOUMIKHI

4

스위프트 솔루션

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

그런 다음 사용하려면

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

카메라 및 사진 갤러리 인증은 어떻습니까?
Hajar ELKOUMIKHI

2

@Raptor의 답변 외에도 다음을 언급해야합니다. iOS 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.

이 문제를 해결하려면 다음과 같이 메인 스레드의 결과를 처리해야합니다 (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
                }
            }
        }
    }
}

거부되면 requestAccess 메소드가 작동하지 않습니다. 사용자에게 설정으로 이동하여 권한을 부여하도록 요청하는 경고를 수동으로 표시해야합니다.
Abdullah Umer

0

Info.plist에서 NSCameraUsageDescription 키를 먼저 지정하십시오. 승인 된 경우 AVAuthorizationStatus를 확인한 다음 UIImagePickerController를 표시하십시오. 작동합니다.


-4

스위프트 : AVFoundation 사용

  1. AVFoundation을 대상-> 빌드 단계-> 바이너리와 라이브러리 연결에 추가하십시오.
  2. ViewController에서 AVFoundation을 가져옵니다.
  3. Info.plist에서 다음을 추가하십시오.

여기에 이미지 설명을 입력하십시오

  1. View Controller에서 :

@IBAction func cameraButtonClicked (보낸 사람 : 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 항목은 무엇입니까? 출처?
Bill
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.