web-dev-qa-db-ja.com

iOSでカメラの許可を検出する

私は非常にシンプルなビデオアプリを開発しています。公式コントロールのUIImagePickerControllerを使用します。

ここに問題があります。 UIImagePickerControllerを初めて表示するとき、iOSは許可を求めます。ユーザーは[はい]または[いいえ]をクリックできます。ユーザーが[いいえ]をクリックした場合、コントロールは閉じられません。代わりに、ユーザーが[スタート]ボタンをクリックし続けると、画面が常に黒である間にタイマーがオンになり、ユーザーはタイマーを停止または元に戻すことができません。ユーザーができることは、アプリを強制終了することだけです。次回UIImagePickerControllerが表示されるとき、それはまだ黒い画面であり、ユーザーが[スタート]をクリックすると戻ることはできません。

私はそれがバグかどうか疑問に思っていました。 UIImagePickerControllerを表示するかどうかを決定できるように、カメラの許可を検出する方法はありますか?

134
user418751

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
}
218
Raptor

IOS 10以降、Info.plistでNSCameraUsageDescriptionキーを指定してカメラアクセスを要求する必要があります。そうしないと、実行時にアプリがクラッシュします。 使用方法の説明が必要なAPI を参照してください。


確認してください:

import AVFoundation

以下のSwiftコードは、考えられるすべての許可状態をチェックします。

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

スイフト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)")
        }
    }
}

おもしろいことに、[設定]でカメラの権限を変更しているときに、iOSが実行中のアプリを強制終了することをご存知でしたか?

Apple開発者フォーラムから:

ユーザーが設定でcameraへのアプリのアクセスを切り替えると、システムは実際にアプリを強制終了します。同じことは、[設定]→[プライバシー]セクションの保護されたデータクラスにも適用されます。

74

@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
                }
            }
        }
    }
}
2
Bart van Kuik

迅速なソリューション

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

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

そして、それを使用するには

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

最初にInfo.plistでNSCameraUsageDescriptionキーを指定します。次に、Authorizedの場合はAVAuthorizationStatusを確認し、UIImagePickerControllerを提示します。それが動作します。

0
Yogendra Singh