我是前言
本文主要介绍iOS7及以上版本麦克风权限的操作,包括检查权限、请求权限、引导用户跳到设置页打开麦克风权限。
检查权限
使用AVAudioSession
的recordPermission
方法可以检查麦克风的权限
使用前记得#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
及更高版本才支持,iOS7
用AVCaptureDevice
检查麦克风权限,代码如下:
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
调用会崩溃,iOS8
和iOS9
没试过。报如下错:
[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>
或者这样:
添加了之后,请求权限就会弹出系统框了
弹框的副标题就是Info.plist
中指定的文案。
跳到设置
跳到设置就是调用UIApplication
的openURL:
方法,关键是指定的URL
。从iOS8
以后,一个应用所有的设置都在一个地方,URL
是UIApplicationOpenSettingsURLString
。iOS7
是按照权限分类的,比如麦克风权限,则所有需要麦克风的权限都放在一个地方,URL
是prefs: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
文件,不然有些系统版本会崩溃。