首页 关于 微信公众号
欢迎关注我的微信公众号

AVAudioSession(3):定制 Audio Session 的 Category

本文内容主要来源于 Working with Categories

对于 Audio Session 来说,与之对应的 Category 是阐释其音频行为的关键信息。比如:你的 App 的声音是否应该受到手机的静音键的控制、你的 App 使不使用音频输入或输出、其他音乐能否和你的 Audio 共存播放等等。

每一种 Category 都指定了是否支持下列这些能力:

下面是各种 Category 的能力表格:

Category 是否会被静音键或锁屏键静音 是否打断不支持混音播放的应用 是否允许音频输入/输出
AVAudioSessionCategoryAmbient Yes NO 只输出
AVAudioSessionCategoryAudioProcessing - YES 无输入和输出
AVAudioSessionCategoryMultiRoute NO YES 支持输入和输出
AVAudioSessionCategoryPlayAndRecord NO 默认 YES,可重写开关置为 NO 支持输入和输出
AVAudioSessionCategoryPlayback NO 默认 YES,可重写开关置为 NO 只输出
AVAudioSessionCategoryRecord NO(锁屏时依然保持录制) YES 只输入
AVAudioSessionCategorySoloAmbient YES YES 只输出

大部分应用只需要在启动时设置一下 Category 即可,不过你是可以随时修改 Audio Session 的 Category,也可以随时激活和关闭 Audio Session。当你的 Audio Session 是 Inactive 的,Category 的请求会在你激活它时发送,如果是 Active 的,则立即发送。

选择最合适的 Category

每一种 Category 最准确的行为定义是由系统控制而不是你的应用,苹果可能会在将来重新定义不同的 Category 的行为,所以你最好是选择一种与你的应用使用音频方式匹配的 Category 来用。

下面列一下各种 Category 的使用场景:

有一点需要注意的是,当你选择那些支持在静音键切到静音状态以及锁屏键切到锁屏状态下仍然支持你的音频继续播放的 Category 时,你必须在你的应用中开启 Background Audio 的能力,详见 UIBackgroundModes。并且,通常你不应该通过 idleTimerDisabled 接口关闭系统的 Sleep Timer。如果你关闭了,那你应该把 idleTimerDisabled 置回 NO,以免你的应用会禁止自动屏幕锁定,毕竟锁屏并不会影响你的音频播放,你干嘛关闭它呢。Sleep Timer 可以确保你的屏幕在用户无操作一段时间后自动变暗并锁定来省电。

除了 AVAudioSessionCategoryMultiRoute 外,其他的 Category 都遵循 last in wins 原则,即最后接入的音频设备作为输入或输出的主设备。

使用 AVAudioSessionCategoryMultiRoute 来扩展音频选择

AVAudioSessionCategoryMultiRoute 并不是简单的遵循 last in wins 原则,AVAudioSessionCategoryMultiRoute 允许你的使用所有连接的输出接口而不仅是最后连上的接口。比如,当你正在通过 HDMI 输出路径听音频,这时又插上了耳麦,你的应用可以同时在 HDMI 和耳麦都输出音频。

在 AVAudioSessionCategoryMultiRoute 下,你的应用可以发送不同的音频流到不同的输出路径。例如,你的应用可以将一条音频流发送到你的左耳麦,另一条音频流发送到右耳麦,并将第三条流发送到 HDMI 路径。如下图所示:

image

AVAudioSessionCategoryMultiRoute 支持下列输出组合:

AVAudioSessionCategoryMultiRoute 支持单输入接口。

设置 Audio Session Category

代码如下:

NSError *setCategoryError = nil;
BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
// BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers error:&setCategoryError];
if (!success) { /* handle the error in setCategoryError */ }

使用 Mode 来定制 Category

正如使用 Category 可以定制应用的音频行为,我们使用 Mode 则可以定制 Category 的行为。可选的 Mode 有这些:

Mode 兼容的 Category
AVAudioSessionModeDefault All
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord

除了这些 Mode 外,有时在定制你的 Category 时,你还需要使用到一些 Option:

Option 说明 兼容的 Category
AVAudioSessionCategoryOptionMixWithOthers 允许和其他音频 mix AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionDuckOthers 智能调低冲突音频音量 AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionAllowBluetooth 允许蓝牙音频输入 AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionDefaultToSpeaker 默认输出音频到扬声器 AVAudioSessionCategoryPlayAndRecord

苹果推荐音频或视频聊天应用也使用 Voice-Processing I/O Unit,这个模块提供了一系列的特性来支持 VoIP 类应用。

支持 AirPlay 的 Category 和 Mode

以下 Category 支持「镜像」和「非镜像」版本的 AirPlay:

此外:

Mode 只有在和 AVAudioSessionCategoryPlayAndRecord Category 配合使用时才支持 AirPlay,下面的 Mode 只支持「镜像」版本的 AirPlay:

Category 使用调优

你可以有多种方式来调优 Category,下面举几个例子:

音频录制权限申请

从 iOS7 之后,录制音频的权限需要用户授权才能获得。如果用户不给你权限,那么你录制的就是静音。当你使用一个需要录制权限的 Category 来定制你的 Audio Session 时,系统会自动弹出权限申请提示给用户。

除了让系统自动弹出权限申请提示外,你还可以通过 requestRecordPermission: 方法来向用户请求权限。

Blog

Opinion

Project