ios - 有没有办法在用户已经在 iOS 上拒绝相机访问权限后向他们询问?

标签 ios objective-c iphone camera

我正在使用此代码,但不幸的是它不起作用。

在用户拒绝相机访问后,我想请求他们允许在他们下次尝试加载相机时再次使用相机(在这种情况下,它是使用相机 View 的条形码扫描仪)。我总是得到 AVAuthorizationStatusDenied 然后 granted 总是自动返回 NO 即使我在代码中再次要求它。

我的许多用户给我发电子邮件说“我尝试扫描条形码时屏幕是黑的”,这是因为他们出于某种原因拒绝了相机访问。我希望能够再次提示他们,因为拒绝很可能是一个错误。

有没有办法做到这一点?

    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if(authStatus == AVAuthorizationStatusAuthorized)
    {
        NSLog(@"%@", @"You have camera access");
    }
    else if(authStatus == AVAuthorizationStatusDenied)
    {
        NSLog(@"%@", @"Denied camera access");

        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if(granted){
                NSLog(@"Granted access to %@", AVMediaTypeVideo);
            } else {
                NSLog(@"Not granted access to %@", AVMediaTypeVideo);
            }
        }];
    }
    else if(authStatus == AVAuthorizationStatusRestricted)
    {
        NSLog(@"%@", @"Restricted, normally won't happen");
    }
    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);
            } else {
                NSLog(@"Not granted access to %@", AVMediaTypeVideo);
            }
        }];
    }
    else
    {
        NSLog(@"%@", @"Camera access unknown error.");
    }

最佳答案

经过一些研究,您似乎无法做我想做的事。这是我编写的用于弹出对话框并在 iOS 8+ 上自动打开“设置”应用程序的替代方法。

一些注意事项:

  • 从 iOS 10 开始,您需要在 Info.plist 中指定 NSCameraUsageDescription 键才能请求相机访问权限,否则您的应用将在运行时崩溃。
  • 一旦用户更改了您应用的任何权限,它就会终止您的应用。在用户点击“开始”按钮之前,相应地处理并保存任何需要的数据。
  • 在 iOS 8 和 11 之间的某个时间点,Apple 不再要求用户触摸“设置”应用中的“隐私”单元格来访问和更改相机设置。您可能希望根据用户使用的 iOS 版本更改有关用户应该在“设置”应用中执行的操作的说明。如果有人想在下方发表评论,告诉我们具体的 iOS 版本发生了哪些变化,那就太好了。
  • 截至本答案的最后一次编辑,以下代码适用于 iOS 14.2。

Swift 5.2:

在 View Controller 的顶部:

import AVFoundation

在打开相机 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()
    }
}

带有完成 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 :

在 View Controller 的顶部:

#import <AVFoundation/AVFoundation.h>

在打开相机 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];
    }
}

拒绝警报:

- (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];
}

对 UIAlertView 的委托(delegate)调用:

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

关于ios - 有没有办法在用户已经在 iOS 上拒绝相机访问权限后向他们询问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26070393/

相关文章:

ios - 使用 UItableViewCell 类型的表达式初始化 'CustomCellView *' 的不兼容指针类型

iphone - 延迟触摸响应

ios - 缺少 xcode dylib 动态库文件

objective-c - 在 ARC 下正确定义静态 NSString* c 样式数组

objective-c - 带有数字格式化程序的 NSTextField 不接受仅填充字符

objective-c - 使用 NSTimer 制作闹钟

iphone - 为什么我的 iPhone 5 即使在完全裸露的 UITableView 滚动条上也没有显示 60+ fps?

ios - 使用 "compare"比较 NSString,就像 Java 的 compareTo

iOS:应用程序主页按钮快捷方式

ios - UIPrintPageRenderer 如何在 US-Letter 和 DIN-A4 格式之间切换