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


143

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

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

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


再:それはバグですか?私見、私はそう思います。なぜなら、VCがハードウェアからのデータを表示しているように見えますが、OSは基本的に無音を送信しているためです。iOSがここに登場したのは、おそらく製品ファミリーの進化の副作用だろう。UIImageViewControlleriOS 2.0で追加されたものとして記載されており、ドキュメントにはAVAuthorizationStatusを使用する必要があることを示す注釈は付けられていませんが、別のフレームワークに存在しています。
benc

回答:


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の変更は不要です。[設定]> [一般]> [リセット]に移動して、デバイスのすべての権限プロンプトをリセットする設定を見つけます。確かに、これはデバイス上の他のすべてのアプリにも影響を与えるので、迷惑です。Appleだけがこのためのアプリ固有のコントロールをSettings.app ...の開発セクションに追加できる場合
KennyDeriemaeker

3
@KennyDeriemaeker :-) Appleは、テスト用に専用デバイスを使用することになっていると返信する場合があります。私にとっては、私の通常の電話をリセットすることの副作用はかなり厄介だったでしょう。バンドルIDを変更することは、かなり簡単な方法です。私も提出前にそれを元に戻したことを思い出しました:-)
Benjohn

8
完全にリセットしないでください!プライバシーと位置情報の設定(iOS 8)をリセットするだけで十分です。
Canucklesandwich、2015年

81

Swift 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 Developerフォーラムから:

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


カメラとフォトギャラリーの認証についてはどうですか?
Hajar ELKOUMIKHI

4

Swiftソリューション

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

Swift:AVFoundationの使用

  1. AVFoundationをターゲットに追加->ビルドフェーズ->バイナリをライブラリにリンクします。
  2. ViewControllerにAVFoundationをインポートします。
  3. Info.plistで、以下を追加します。

ここに画像の説明を入力してください

  1. ビューコントローラ上:

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

Info.plistエントリとは何ですか?ソース?
ビル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.