最高のエクスペリエンスを確保しながら、ユーザーにカメラ(または他の機能)へのアクセスを提供するように促す最も効果的な方法は何ですか?
カメラにアクセスする場合、iOSはお客様にアクセスを許可する許可を求める必要があります。ご存知のように、お客様が「いいえ」と言った後で気が変わった場合、アプリ内からこの決定を元に戻す方法はありません。ユーザーは[設定]に移動して、アクセスを再度有効にするためのいくつかの手順に従う必要があります。
Settings -> Privacy -> Camera -> [Your App] -> turn switch on
許可プライミングは、顧客がアプリの主要機能へのアクセスを拒否する可能性がある状況を回避する効果的な方法です。
IOSでは、アプリはデフォルトのシステム権限を機能ごとに1回のみトリガーできます。権限プライミングとは、アプリがシステム権限を模倣するアラートでお客様を「準備」することです。
これを行うことの利点は、お客様がオプトアウトした場合([キャンセル]を選択した場合)、「はい」と言うまで、アプリは今後も再度尋ねることができるため、実際のシステム権限が表示され、お客様は統計的に少なくなります。その後、彼らの考えを変え、否定的なワークフローに入る可能性があります。
さらに、cameraSelected()
はこのワークフローを実行するので、ユーザーが拒否した場合でも、将来のある時点でdoesが設定を変更すると、アプリは追加の入力なしで新しい権限をすぐに反映します(つまり、ユーザーは設定に切り替え、権限を変更してから、アプリに戻すことができます)。
この機能を実装するためのSwiftコードを次に示します。
[UPDATE:含まれているのは、以前に拒否した場合に、ユーザーがカメラへのアクセスを有効にできる設定へのディープリンクを開くソリューションです。]
[[更新2:アナリティクス実装のサンプル行を追加しました。]
func cameraSelected() {
// First we check if the device has a camera (otherwise will crash in Simulator - also, some iPod touch models do not have a camera).
if let deviceHasCamera = UIImagePickerController.isSourceTypeAvailable(.camera) {
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authStatus {
case .authorized:
showCameraPicker()
case .denied:
alertPromptToAllowCameraAccessViaSettings()
case .notDetermined:
permissionPrimeCameraAccess()
default:
permissionPrimeCameraAccess()
}
} else {
let alertController = UIAlertController(title: "Error", message: "Device has no camera", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { (alert) in
Analytics.track(event: .permissionsPrimeCameraNoCamera)
})
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
}
}
func alertPromptToAllowCameraAccessViaSettings() {
let alert = UIAlertController(title: "\"<Your App>\" Would Like To Access the Camera", message: "Please grant permission to use the Camera so that you can <customer benefit>.", preferredStyle: .alert )
alert.addAction(UIAlertAction(title: "Open Settings", style: .cancel) { alert in
Analytics.track(event: .permissionsPrimeCameraOpenSettings)
if let appSettingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.openURL(appSettingsURL)
}
})
present(alert, animated: true, completion: nil)
}
func permissionPrimeCameraAccess() {
let alert = UIAlertController( title: "\"<Your App>\" Would Like To Access the Camera", message: "<Your App> would like to access your Camera so that you can <customer benefit>.", preferredStyle: .alert )
let allowAction = UIAlertAction(title: "Allow", style: .default, handler: { (alert) -> Void in
Analytics.track(event: .permissionsPrimeCameraAccepted)
if AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count > 0 {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { [weak self] granted in
DispatchQueue.main.async {
self?.cameraSelected() // try again
}
})
}
})
alert.addAction(allowAction)
let declineAction = UIAlertAction(title: "Not Now", style: .cancel) { (alert) in
Analytics.track(event: .permissionsPrimeCameraCancelled)
}
alert.addAction(declineAction)
present(alert, animated: true, completion: nil)
}
func showCameraPicker() {
let picker = UIImagePickerController()
picker.delegate = self
picker.modalPresentationStyle = UIModalPresentationStyle.currentContext
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
present(picker, animated: true, completion: nil)
}