How to detect privacy permission changes (Camera access for example)

4.4k views Asked by At

We've all been there. You want to take photos within your app, or access photos, microphone, contacts, etc... But first iOS must prompt the user for permission. In many cases the user will deny access.

If your app detects that the user has denied access, you can navigate the user to the App's privacy settings with this:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

Handy. However....

I've noticed that if you do convince the user to toggle the switch to on, that the app does not detect the changes.

Consider this code. The user is immediately prompted for permission to access the camera (this only shows the first time that app is run). Suppose the user denied permission. Next they decide that they did want to enable camera access after all. No problem. The user taps on the button which brings up the privacy panel. The user changes the switch to allow access. Then the user switches back to the app. The block fires for UIApplicationDidBecomeActiveNotification which reads the permission again. However it does not reflect the user's changes (still reads as Denied).

If the app is purged from memory and run again, it will properly read the state.

Not all permissions behave this way. For instance CoreLocation seems to detect the user's changes. I've also found a way to detect changes for Notifications. But for Contacts, Calendars, Camera, Microphone, Core Motion (and more) the changes are not detected until the app is terminated and run again.

Any ideas?

#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
1

There are 1 answers

5
z2k On BEST ANSWER

So, this turned out to be a bug related to iOS 9b1.

Permission detection works fine on iOS 8.

I did learn that you need to check the permission on the main queue. If you do that, it will reflect updates.