如何检测隐私权限更改(例如相机访问)

3
我们都曾经遇到过这种情况。你想在你的应用程序中拍照,或者访问照片、麦克风、联系人等等... 但是首先iOS必须提示用户授权。在许多情况下,用户会拒绝授权。
如果你的应用程序检测到用户已经拒绝了访问权限,你可以使用以下代码将用户引导到应用程序的隐私设置页面:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

方便,但是....

我注意到,如果您成功说服用户切换到开启状态,则应用程序无法检测更改。

考虑以下代码。立即提示用户允许访问相机(仅在第一次运行应用程序时显示此项)。假设用户拒绝了权限。接下来,他们决定还是要启用相机访问。没问题。用户点击按钮,打开隐私面板。用户更改开关以允许访问。然后用户切回应用程序。块会触发UIApplicationDidBecomeActiveNotification,再次读取权限。但它不反映用户的更改(仍然读为被拒绝)。

如果从内存中清除该应用程序并重新运行,它将正确读取状态。

并非所有权限都表现出这种行为。例如CoreLocation似乎可以检测到用户的更改。我还找到了一种检测通知更改的方法。但是对于联系人、日历、相机、麦克风、核心动作(等等),直到重新启动应用程序,才能检测到更改。

有什么想法吗?

#import "ViewController.h"
@import AVFoundation;

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        [self printPermission];
    }];

    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
        [self printPermission];
    }];

}


-(void)printPermission{
    dispatch_async(dispatch_get_main_queue(), ^{
        AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if(status == AVAuthorizationStatusNotDetermined){
            NSLog(@"VWWPermissionStatusNotDetermined");
            self.view.backgroundColor = [UIColor whiteColor];
        } else if(status == AVAuthorizationStatusAuthorized){
            NSLog(@"VWWPermissionStatusAuthorized");
            self.view.backgroundColor = [UIColor greenColor];
        } else if(status == AVAuthorizationStatusDenied) {
            NSLog(@"VWWPermissionStatusDenied");
            self.view.backgroundColor = [UIColor redColor];
        } else if(status == AVAuthorizationStatusRestricted) {
            NSLog(@"VWWPermissionStatusRestricted");
            self.view.backgroundColor = [UIColor redColor];
        }
    });
}

- (IBAction)buttonAction:(id)sender {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

@end

但对于联系人、日历、相机、麦克风、核心动作等功能,在应用程序终止并再次运行之前,更改不会被检测到。但根据我的经验,如果用户在应用程序运行时更改了权限,则该应用程序将被终止。 - matt
我有一个设备,该应用程序总是被终止。模拟器也是如此。我还有一些其他设备,它们肯定不会被终止。 - VaporwareWolf
好的,但我发现在应用程序未终止的情况下,在viewDidAppear中测试授权是有效的。例如:https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch19p725calendar/ch32p986calendar/ViewController.swift 在我的测试中,如果我们将用户发送到设置应用并且用户授予权限,则可以正常工作。 - matt
如果你认为自己已经找到了答案,那么不要修改你的问题,而应该回答自己的问题。你甚至可以在一段时间后接受自己的答案!这是帮助其他可能遇到此问题的人的最佳方式。 - matt
谢谢,我会这样做的。我不确定那是否会被认为是贪婪或其他什么。 - VaporwareWolf
1个回答

2

因此,这个问题实际上与iOS 9b1有关。

iOS 8上权限检测正常工作。

我了解到您需要在主队列上检查权限,这样就能反映更新。


自那时起,它是否被修补过?iOS 9.2似乎存在这个问题。 - Teddy
不,我不这么认为。我正在编写一个权限提示框架时遇到了这个问题。我本周使用了该框架,问题仍然存在(会导致调试器崩溃)。我正在运行iOS 9.2。但是在独立运行时没有崩溃。 - VaporwareWolf
调试器也没有崩溃。它只是捕获了某种“影子”异常。但您可以继续执行。在主线程上检查并没有解决我的问题。 - Teddy
哈哈,问题已经解决了:当我调试时,它不会终止应用程序。当我独立运行时,它会终止应用程序(至少是这样)。 - Teddy
当我说崩溃时,我的意思是如果您启动到隐私设置面板并切换设置,则会导致调试器崩溃。如果我没记错,不是所有的权限更改都会导致调试器崩溃,但本周对我来说照片或相机确实会导致崩溃。无论如何,在实际使用中它都可以正常工作。 - VaporwareWolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接