Defining an Audio Session
在你的应用中使用声音播放需要定义一个合适的audio session
,它会配置你的应用的声音行为。例如
- 是否让其他应用(音乐播放器)和你的应用声音进行混合
- 来电或闹钟打断应用的声音播放应该如何恢复中断
- 插拔耳机你的应用应该作何回应
当你的应用启动时,audio session
的配置影响到所有音频的活动除了使用System Sounds Services
API 播放的音频。你可以通过audio session
查询到你应用所在的设备的硬件特性,例如:声道数量和采样率等。你可以激活和反激活你的audio session
,系统也能够主动反激活你的audio session
,例如来电和闹钟。
1.1 Audio Session Default Behavior
audio session
有一些默认的行为:
- 正在播放音视频时不可以进行录制
- 应用声音播放跟随静音键的设置(静音键打开应用静音)
- 应用声音跟随锁屏(锁频应用静音)
- 应用声音独占播放(不允许其他应用与之混音)
以上的这些音频默认行为来自系统默认选择的AVAudioSessionCategorySoloAmbient
。
在开发过程中,你可以采用上面这些默认的音频行为。不过,在以下几种情况你可以放心地忽略audio session
的设置:
- 你的应用播放声音使用
System Sound Services or the UIKit playInputClick method
,且没有使用音其他音频API。System Sound Services
用于播放用户交互界面上的简短声音提示以及调用设备的震动功能。The UIKit playInputClick
方法让你在自定义的输入或键盘附件中播放标准的敲击声,它的音频行为由系统处理。 - 你的应用根本没有使用到音频
在有其他音频行为需求下,不要使用默认的audio session
。
1.2 Why a Default Audio Session Usually Isn’t What You Want
如果你没有实例化、配置以及清晰地使用你的audio session
,你的应用则不能对音频线路改变或中断作出响应。
下面是一些演示默认音频行为的场景以及如何去改变它:
- 场景1。你写了一个电子书应用。一个用户开始听《西游记》,不久设备自动锁屏了,应用也静音了。
为了保证设备锁屏后依然能够正常播放声音,应该配置一个
audio session
支持播放并且在UIBackgroundModes
中设置打开音频后台使用开关。 - 场景2。你写了一个第一人称的射击游戏,使用了
OpenAL-based sound effects
。你提供了一个背景声音播放轨道,可以给用户播放音乐库的歌曲。当歌曲正在播放到一半时,你开炮射击了敌人的集中营,随之歌曲停止播放了。为了确保你的歌曲不会被打断,应该设置
audio session
允许被混音。使用AVAudioSessionCategoryAmbient
或者修改AVAudioSessionCategoryPlayback
来支持混音。(详情见Fine-Tuning category
)。 - 场景3。你写了一个流媒体音频应用,使用
Audio Queue Services
来播放。当一个用户在收听时,一个电话打进来了,正如我们所预料到的应用停止播放了。用户选择挂断电话,返回应用点击播放但不再响应。为了恢复播放,用户需要重启应用。为了能够优雅地处理音频队列的中断,设置合适的
category
并且监听AVAudioSessionInterruptionNotification
。
1.3 Initializing Your Audio Session
在你的应用启动时系统就提供了一个audio session
对象。然而,为了处理中断事件你必须实例化这个audio session
。
1 | // implicitly initializes your audio session |
这个session
代表被初始化的audio session
,可以马上使用。当你使用AVAudioSession class’s interruption notifications
或delegate protocols of the AVAudioPlayer and AVAudioRecorder classes
处理中断时,苹果官方推荐对audio session
进行隐式地初始化。
1.4 Adding Volume and Route Control
使用MPVolumeView
类去为你的APP展示音量和线路控制。这个volume view
提供了一个滑动条在应用内部控制音量,还提供了一个旋钮选择音频输出线路。当输出音频到内置扬声器时,苹果官方推荐通过AVAudioSessionPortOverride
使用MPVolumeView route picker
。
1.5 Responding to Remote Control Events
远程控制事件让用户控制应用的多媒体播放。如果你的应用播放音频或视频内容,你可能想要响应来自传输控件或外部附件的远程控制事件。iOS转换UIEvent
对象的命令,传递事件到APP。APP把事件发送给第一响应者,如果第一响应者没有处理它们,将沿着响应链传递下去。你的APP一定要是“Now Playing”,否则不能响应事件。
1.6 Activating and Deactivating Your Audio Session
在你的APP启动时,系统将激活你的audio session
。即使这样,苹果官方推荐在viewDidLoad
方法中显式激活它,同时优先设置硬件偏好值。具体参照Setting Preferred Hardware Values
代码,这可以测试是否激活成功。
下面展示如何激活APP的audio session
1 | NSError *activationError = nil; |
反激活则传递
NO
到setActive
参数中。
在使用AVAudioPlayer
对象播放声音或使用AVAudioRecorder
对象录制音频的具体使用例子中,系统很关心在中断结束后audio session
的重新激活。苹果官方推荐监听通知消息来重新激活audio session
。如此,你可以确保重新激活成功,与此同时你可以更新应用的状态和UI。
大多数应用不需要显示地反激活audio session
,如:VOIP、语音导航、录音的应用。
- 要确保经常在后台运行的VOIP应用的
audio session
只有在处理通话时才是处于激活状态的。在后台等待处理电话通知时的audio session
不应该被激活。 - 设置为
recording category
应用的audio session
只有在录制情况下才处于激活状态。在录制开始前和录制结束时,要确保你的应用的audio session
是处于非激活状态来允许其他声音播放。
1.7 Checking Whether Other Audio Is Playing During App Launch
当用户启动APP的时候,或许设备正在播放音频。例如:当你启动应用时,设备音乐播放器在播放歌曲或浏览器在播放流媒体音频。如果你的应用是游戏,这种情况很明显。很多游戏有一个音乐声轨和一个音效轨道。在这种情况下,Sound in iOS Human Interface Guidelines
建议你音乐和游戏音效一起播放。检查otherAudioPlaying
属性判断在你的应用启动时是否有其他音频正在播放。如果有其他音频正在播放,使你游戏应用的音乐声轨静音并且设置AVAudioSessionCategorySoloAmbient
category。
1.8 Working with Inter-App Audio
在最基本的形式下,跨应用音频允许一个APP(节点APP)发送输出它的音频到另外一个APP(主APP)。也有可能是由主APP发送音频到节点APP,让节点APP来处理音频并返回结果给主APP。主APP需要有一个处于激活状态的audio session
,然而节点APP只有在接收主APP输入时才需要一个处于激活状态的audio session
。使用下面的指南来设置跨应用音频:
- 为
host
andnode
APP的inter-app-audio
授权。 - 为
host
APP打开UIBackgroundModes
的audio
开关。 - 为
node
APP打开UIBackgroundModes
的audio
开关,当node
APP同时连接到一个inter-app
audio host时使用输入或输出线路。 - 为
host
和node
APP设置AVAudioSessionCategoryOptionMixWithOthers
。 - 当
node
APP同时连接到一个inter-app
audio host时,确保node
APP的audio session
在接收来自系统的输入(或者发送音频输出)。