美文网首页ios开发那些事
iOS7及以上版本麦克风权限操作

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

作者: ZacharyTAT | 来源:发表于2017-04-29 15:13 被阅读3173次

    我是前言

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

    检查权限

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

    使用前记得#import <AVFoundation/AVFoundation.h>

    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:

    <key>NSMicrophoneUsageDescription</key>
    <string>允许我访问麦克风才能录音哦~</string>
    

    或者这样:

    NSMicrophoneUsageDescription.png

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

    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,即

    <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>prefs</string>
                </array>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLName</key>
                <string>prefs</string>
            </dict>
        </array>
    

    总结

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

    相关文章

      网友评论

        本文标题:iOS7及以上版本麦克风权限操作

        本文链接:https://www.haomeiwen.com/subject/gpmzzttx.html