簡體   English   中英

在 iOS 中請求相機權限對話框啟動(Prime Permissions)

[英]Request Camera Permission Dialog Priming (Prime Permissions) in iOS

在確保最佳體驗的同時,提示用戶提供對相機(或其他功能)的訪問權限的最有效方法是什么?

訪問相機時,iOS 必須征得客戶的許可以允許訪問。 眾所周知,如果客戶說“不”但后來改變了主意,則無法從您的應用程序中撤消此決定。 他們必須轉到“設置”並按照一些步驟重新啟用訪問,即:

Settings -> Privacy -> Camera -> [Your App] -> turn switch on

權限啟動是避免客戶可能拒絕訪問應用程序關鍵功能的有效方法。

在iOS上,每個功能只允許應用程序觸發一次默認系統權限。 權限啟動是指應用程序使用模仿系統權限的警報“填充”客戶。

這樣做的好處是,如果客戶選擇退出(選擇取消),應用程序仍然可以在將來再次詢問,直到他們說是 - 此時顯示實際的系統權限並且客戶在統計上更少可能會改變主意並進入負面工作流程。

此外,由於cameraSelected()執行此工作流程,如果用戶拒絕,但在某個未來點確實更改其設置,應用程序將立即反映新權限而無需進一步輸入(即,用戶可以切換到設置,更改權限,然后切換回App)。

以下是一些實現此功能的Swift 3代碼:

[更新:包含一個解決方案,打開設置的深層鏈接,用戶可以啟用相機訪問,如果他們以前拒絕了它。]

[更新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)
}

假設我們有兩個按鈕(一個用於從庫中選擇圖片,另一個用於從相機中選擇),帶有與動作相關聯的標簽 1,2:

import UIKit
import AVFoundation

    @IBAction func changeImage(sender: UIButton) {
        let picker = UIImagePickerController()
        if sender.tag == 2 { // tag = 2 for camera button. tag = 1 for image picker
            guard UIImagePickerController.isSourceTypeAvailable(.camera) else { return }
            let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
            
            switch cameraAuthorizationStatus {
            case .notDetermined:
                requestCameraPermission()
                return
            case .authorized:
                break
            case .restricted, .denied:
                alertCameraAccessNeeded()
                return
            @unknown default:
                return
            }
            picker.sourceType = .camera
        }
        
        picker.allowsEditing = true
        picker.delegate = self
        present(picker, animated: true)
    }

    private func requestCameraPermission() {
        AVCaptureDevice.requestAccess(for: .video) { [weak self] accessGranted in
            if !accessGranted {
                DispatchQueue.main.async {
                    self?.alertCameraAccessNeeded()
                }
            }
        }
    }
    
    private  func alertCameraAccessNeeded() {
        guard let settingsAppURL = URL(string: UIApplication.openSettingsURLString),
              UIApplication.shared.canOpenURL(settingsAppURL) else { return } // This should never happen
        let alert = UIAlertController(
            title: "Need Camera Access",
            message: "Camera access is required to take pictures of item.",
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: "Cancel", style: .default))
        alert.addAction(UIAlertAction(title: "Allow Camera", style: .cancel) { _ in
            UIApplication.shared.open(settingsAppURL, options: [:])
        })
        present(alert, animated: true)
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM