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

我是前言

本文主要介绍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文件,不然有些系统版本会崩溃。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 准备内容 Python安装 安装pip(pythonpip是一个安装和管理Python包的工具) 安装reques...
    简单生活101阅读 5,570评论 0 3
  • 阿布今天很高兴,不知道是不是因为下午刷题的时候打开了脑洞,还是因为今天喝了两包咖啡兴奋。好心情不用纠结原因,高兴多...
    30前立xoxo阅读 105评论 0 2
  • 永远不需要向别人解释你自己 因为 喜欢你的人不需要 讨厌你的人不值得 快乐的前提 不是有能力改变世界 而是有恒心改...
    七八岁阅读 222评论 0 6
  • 青城后山位于青城山后,泰安乡境内,自然风光出众,水秀、林幽、山雄,是徒步休闲的好去处。 由于学校的地理...
    出行and回归阅读 382评论 0 1
  • 昨日,韩国双宋大婚,我的学生说,这才是《太阳的后裔》的大结局,从戏内恋到戏外,他们拥有着旁人所羡煞的容颜(虽是...
    樱桃小丸子A阅读 208评论 0 1