iOS7及以上版本麦克风权限操作

我是前言

本文主要介绍iOS7及以上版本麦克风权限的操作,包括检查权限、请求权限、引导用户跳到设置页打开麦克风权限。

检查权限

使用AVAudioSessionrecordPermission方法可以检查麦克风的权限

使用前记得#import

AVAudioSession* sharedSession = [AVAudioSession sharedInstance];
AVAudioSessionRecordPermission permission = [sharedSession recordPermission];
switch (permission) {
    case AVAudioSessionRecordPermissionUndetermined:
        NSLog(@"Undetermined");
        break;
    case AVAudioSessionRecordPermissionDenied:
        NSLog(@"Denied");
        break;
    case AVAudioSessionRecordPermissionGranted:
        NSLog(@"Granted");
        break;
    default:
        break;
}

返回的结果是AVAudioSessionRecordPermission类型,有如下值:

{
    AVAudioSessionRecordPermissionUndetermined, // 还未决定,说明系统权限请求框还未弹出过
    AVAudioSessionRecordPermissionDenied, // 用户明确拒绝,不再弹出系统权限请求框
    AVAudioSessionRecordPermissionGranted // 用户明确授权
}

但是,recordPermission方法只有iOS8及更高版本才支持,iOS7AVCaptureDevice检查麦克风权限,代码如下:

AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
switch (authStatus) {
    case AVAuthorizationStatusNotDetermined:
        NSLog(@"NotDetermined");
        break;
    case AVAuthorizationStatusRestricted:
        NSLog(@"Restricted");
        break;
    case AVAuthorizationStatusDenied:
        NSLog(@"Denied");
        break;
    case AVAuthorizationStatusAuthorized:
        NSLog(@"Authorized");
        break;
    default:
        break;
}

authorizationStatusForMediaType:方法不止可以检查麦克风,根据传入的mediaType可以检查不同媒体的权限,AVMediaTypeAudio代表音频。返回的枚举值相比之前的多了个AVAuthorizationStatusRestricted,是设备使用受限的意思,猜测mediaType如果是AVMediaTypeAudio不会返回这个值,因为AVAudioSessionRecordPermission就三种状态。将其处理成和AVAuthorizationStatusDenied一样即可。

所以最后的兼容性代码如下:

AVAudioSession* sharedSession = [AVAudioSession sharedInstance];
if ([sharedSession respondsToSelector:@selector(recordPermission)]) {
    AVAudioSessionRecordPermission permission = [sharedSession recordPermission];
    switch (permission) {
        case AVAudioSessionRecordPermissionUndetermined:
            NSLog(@"Undetermined");
            break;
        case AVAudioSessionRecordPermissionDenied:
            NSLog(@"Denied");
            break;
        case AVAudioSessionRecordPermissionGranted:
            NSLog(@"Granted");
            break;
        default:
            break;
    }
    return;
}

if (iOS7) {
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    switch (authStatus) {
        case AVAuthorizationStatusNotDetermined:
            NSLog(@"NotDetermined");
            break;
        case AVAuthorizationStatusRestricted:
        case AVAuthorizationStatusDenied:
            NSLog(@"Denied");
            break;
        case AVAuthorizationStatusAuthorized:
            NSLog(@"Authorized");
            break;
        default:
            break;
    }
}

如果应用是支持iOS6的,使用authorizationStatusForMediaType方法时还要判断是否是iOS7,因为该方法是iOS7以后才有的。另外,iOS6不需要请求麦克风权限即可使用麦克风。

请求权限

请求权限还是用到AVAudioSession,方法是requestRecordPermission:,在block里面获取授权结果,

AVAudioSession* sharedSession = [AVAudioSession sharedInstance];
[sharedSession requestRecordPermission:^(BOOL granted) {
    NSLog(@"%@ -- %@", @(granted), @([NSThread isMainThread]));
    dispatch_sync(dispatch_get_main_queue(), ^{
        callback(granted);
    });
}];

如果系统的权限请求框没有弹出过,即权限的状态是AVAuthorizationStatusNotDetermined或者AVAudioSessionRecordPermissionUndetermined,则调用该方法会弹出系统框,用户点击允许或者不允许后,block会被调用,通过granted可以获得结果,但该block不是在主线程里面调用,所以得到结果后,应该在主队列中回调。

注意:系统的权限请求框只会弹出一次,当权限的状态是determined的,再调用该方法,则block会立即在主队列中被调用

幸运的是,该方法从iOS7就支持了,不用判断系统版本了。不幸的是,该方法在iOS10调用会崩溃,iOS8iOS9没试过。报如下错:

[access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSMicrophoneUsageDescription key with a string value explaining to the user how the app uses this data.

说得很明显,Info.plist文件中缺少NSMicrophoneUsageDescription配置。

Info.plist文件中添加麦克风权限请求相关的key:

NSMicrophoneUsageDescription
允许我访问麦克风才能录音哦~

或者这样:

NSMicrophoneUsageDescription.png

添加了之后,请求权限就会弹出系统框了

iOS7及以上版本麦克风权限操作_第1张图片
request.png

弹框的副标题就是Info.plist中指定的文案。

跳到设置

跳到设置就是调用UIApplicationopenURL:方法,关键是指定的URL。从iOS8以后,一个应用所有的设置都在一个地方,URLUIApplicationOpenSettingsURLStringiOS7是按照权限分类的,比如麦克风权限,则所有需要麦克风的权限都放在一个地方,URLprefs:root=Privacy&path=MICROPHONE,其他的权限也可类比。代码如下:

NSURL* openUrl = nil;

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
    openUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
}
else {
    openUrl = [NSURL URLWithString:@"prefs:root=Privacy&path=MICROPHONE"];
}
[[UIApplication sharedApplication] openURL:openUrl];

注意:MICROPHONE要写对(全部大写),不然可能跳的是Privacy

这样写可能还跳不成功,原因是在Info.plist中没有添加URL types,即

CFBundleURLTypes
    
        
            CFBundleURLSchemes
            
                prefs
            
            CFBundleTypeRole
            Editor
            CFBundleURLName
            prefs
        
    

总结

iOS8前后关于麦克风相关的api有些调整,如应用需要支持iOS7,则要编写一些兼容性的代码。另外,请求权限还要配置Info.plist文件,不然有些系统版本会崩溃。

你可能感兴趣的:(iOS7及以上版本麦克风权限操作)