How to Ask User for Camera Access After They Have Already Denied It on iOS

Is there a way to ask user for Camera access after they have already denied it on iOS?

After some research it looks like you can't do what I'd like. Here is the alternative that I coded to pop a dialog and open the Settings app automatically if on iOS 8+.

Some notes:

  • Since iOS 10 you need to specify NSCameraUsageDescription key in your Info.plist to be able ask for camera access, otherwise your app will crash at runtime.
  • Once the user changes any permissions for your app, it will kill your app. Handle accordingly and save any needed data before the user hits that "Go" button.
  • At some point between iOS 8 and 11, Apple no longer required the user to touch the Privacy cell in the Setting apps in order to get to and change the Camera settings. You may want to change your instructions on what the user is supposed to do in the Settings app based on what iOS version they are using. If someone wants to leave a comment below telling us all what exact iOS version that changed in, that would be awesome.
  • As of the last edit of this answer, the code below is working on iOS 14.2.

Swift 5.2:

At the top of your view controller:

import AVFoundation

Before opening the camera view:

@IBAction func goToCamera()
{
let status = AVCaptureDevice.authorizationStatus(for: .video)
switch (status)
{
case .authorized:
self.popCamera()

case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { (granted) in
if (granted)
{
self.popCamera()
}
else
{
self.camDenied()
}
}

case .denied:
self.camDenied()

case .restricted:
let alert = UIAlertController(title: "Restricted",
message: "You've been restricted from using the camera on this device. Without camera access this feature won't work. Please contact the device owner so they can give you access.",
preferredStyle: .alert)

let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
@unknown default:
fatalError()
}
}

Denial alert with completion block:

func camDenied()
{
DispatchQueue.main.async
{
var alertText = "It looks like your privacy settings are preventing us from accessing your camera to do barcode scanning. You can fix this by doing the following:\n\n1. Close this app.\n\n2. Open the Settings app.\n\n3. Scroll to the bottom and select this app in the list.\n\n4. Turn the Camera on.\n\n5. Open this app and try again."

var alertButton = "OK"
var goAction = UIAlertAction(title: alertButton, style: .default, handler: nil)

if UIApplication.shared.canOpenURL(URL(string: UIApplication.openSettingsURLString)!)
{
alertText = "It looks like your privacy settings are preventing us from accessing your camera to do barcode scanning. You can fix this by doing the following:\n\n1. Touch the Go button below to open the Settings app.\n\n2. Turn the Camera on.\n\n3. Open this app and try again."

alertButton = "Go"

goAction = UIAlertAction(title: alertButton, style: .default, handler: {(alert: UIAlertAction!) -> Void in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
})
}

let alert = UIAlertController(title: "Error", message: alertText, preferredStyle: .alert)
alert.addAction(goAction)
self.present(alert, animated: true, completion: nil)
}
}

Objective-C:

At the top of your view controller:

#import <AVFoundation/AVFoundation.h>

Before opening the camera view:

- (IBAction)goToCamera
{
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusAuthorized)
{
[self popCamera];
}
else if(authStatus == AVAuthorizationStatusNotDetermined)
{
NSLog(@"%@", @"Camera access not determined. Ask for permission.");

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted)
{
if(granted)
{
NSLog(@"Granted access to %@", AVMediaTypeVideo);
[self popCamera];
}
else
{
NSLog(@"Not granted access to %@", AVMediaTypeVideo);
[self camDenied];
}
}];
}
else if (authStatus == AVAuthorizationStatusRestricted)
{
// My own Helper class is used here to pop a dialog in one simple line.
[Helper popAlertMessageWithTitle:@"Error" alertText:@"You've been restricted from using the camera on this device. Without camera access this feature won't work. Please contact the device owner so they can give you access."];
}
else
{
[self camDenied];
}
}

Denial alert:

- (void)camDenied
{
NSLog(@"%@", @"Denied camera access");

NSString *alertText;
NSString *alertButton;

BOOL canOpenSettings = (&UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings)
{
alertText = @"It looks like your privacy settings are preventing us from accessing your camera to do barcode scanning. You can fix this by doing the following:\n\n1. Touch the Go button below to open the Settings app.\n\n2. Turn the Camera on.\n\n3. Open this app and try again.";

alertButton = @"Go";
}
else
{
alertText = @"It looks like your privacy settings are preventing us from accessing your camera to do barcode scanning. You can fix this by doing the following:\n\n1. Close this app.\n\n2. Open the Settings app.\n\n3. Scroll to the bottom and select this app in the list.\n\n4. Turn the Camera on.\n\n5. Open this app and try again.";

alertButton = @"OK";
}

UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Error"
message:alertText
delegate:self
cancelButtonTitle:alertButton
otherButtonTitles:nil];
alert.tag = 3491832;
[alert show];
}

Delegate call for the UIAlertView:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 3491832)
{
BOOL canOpenSettings = (&UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}

Is there any way to ask permission after denied in iOS

If the user has previously denied access, you can present an alert with a description of why it is essential for correct operation of the app with a button that will open openSettingsURLString. If they select the option to open settings, you can open it with open(_:options:completionHandler:).

But you should do this only if it’s truly required for successful operation (e.g., don’t nag them about location info just because you want that info, but only if the app cannot function as desired by the user in the absence of their permission).

Not able to show the alert if user denied the camera access

for reference purpose I taken the answer from this tutorial.

step 1

add the avfoundation framework in your project

import AVFoundation

step 2

dont forget to Set Camera Usage Description in Info.plist

When you request permission to use the device’s camera, a short message will appear in the default iOS system dialog. You customize this message by adding the Privacy - Camera Usage Description key to your Info.plist file.

step 3

on your image profile change button action verify the permission, etc.

@IBAction func ProfileImageButton(_ sender: UIButton) {
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
switch cameraAuthorizationStatus {
case .notDetermined: requestCameraPermission()
case .authorized: presentCamera()
case .restricted, .denied: alertCameraAccessNeeded()
}
}

based on the above action the condition will satisfy,

If the user has never responded to a request to access his/her camera, you need to prompt with the iOS system alert to request permission:

 func requestCameraPermission() {
AVCaptureDevice.requestAccess(for: .video, completionHandler: {accessGranted in
guard accessGranted == true else { return }
self.presentCamera()
})
}

there after the camera access will continue

 func presentCamera() {
let photoPicker = UIImagePickerController()
photoPicker.sourceType = .camera
photoPicker.delegate = self as? UIImagePickerControllerDelegate & UINavigationControllerDelegate

self.present(photoPicker, animated: true, completion: nil)
}

To use the image that the camera captured, you need to set up your view controller to adhere to and implement couple of delegate protocols:

 class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
// ...
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let photo = info[UIImagePickerControllerOriginalImage] as! UIImage
// do something with the photo... set to UIImageView, save it, etc.

dismiss(animated: true, completion: nil)
}

If camera access has been denied or restricted, you can alert the user and direct them to the Settings app to make the appropriate permissions adjustment:

func alertCameraAccessNeeded() {
let settingsAppURL = URL(string: UIApplicationOpenSettingsURLString)!

let alert = UIAlertController(
title: "Need Camera Access",
message: "Camera access is required to make full use of this app.",
preferredStyle: UIAlertControllerStyle.alert
)

alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Allow Camera", style: .cancel, handler: { (alert) -> Void in
UIApplication.shared.open(settingsAppURL, options: [:], completionHandler: nil)
}))

present(alert, animated: true, completion: nil)
}

Handling denied camera permissions in an iOS App Clip

After reading Learn More About App Clips and having a look at my phone, it appears that the user should be able to change the settings by going to the Settings app and looking under Privacy -> Camera -> App Clip (I don't have any app clips installed so, that's as deep as I got)

How to check if the user gave permission to use the camera?

You can use the following code for doing the same:

if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) ==  AVAuthorizationStatus.Authorized {
// Already Authorized
} else {
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
if granted == true {
// User granted
} else {
// User rejected
}
})
}

NOTE:

  1. Make sure that you add the AVFoundation Framework in the Link Binary section of build phases
  2. You should write import AVFoundation on your class for importing AVFoundation

SWIFT 3

if AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) ==  AVAuthorizationStatus.authorized {
// Already Authorized
} else {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
if granted == true {
// User granted
} else {
// User Rejected
}
})
}

Swift 4

if AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized {
//already authorized
} else {
AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
if granted {
//access allowed
} else {
//access denied
}
})
}

Detect when user denies access to camera

Actually, there's a way of doing it:

 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if(granted){
NSLog(@"Granted access");
} else {
NSLog(@"Not granted access");
}
}];

Detect permission of camera in iOS

Check the AVAuthorizationStatus and handle the cases properly.

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
}


Related Topics



Leave a reply



Submit