AVAudioSession Programming Guide

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
2
// implicitly initializes your audio session
AVAudioSession *session = [AVAudioSession sharedInstance];

这个session代表被初始化的audio session,可以马上使用。当你使用AVAudioSession class’s interruption notificationsdelegate 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
2
3
NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
if (!success) { /* handle the error in activationError */ }

反激活则传递 NOsetActive 参数中。

在使用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属性判断在你的应用启动时是否有其他音频正在播放。如果有其他音频正在播放,使你游戏应用的音乐声轨静音并且设置AVAudioSessionCategorySoloAmbientcategory。

1.8 Working with Inter-App Audio

在最基本的形式下,跨应用音频允许一个APP(节点APP)发送输出它的音频到另外一个APP(主APP)。也有可能是由主APP发送音频到节点APP,让节点APP来处理音频并返回结果给主APP。主APP需要有一个处于激活状态的audio session,然而节点APP只有在接收主APP输入时才需要一个处于激活状态的audio session。使用下面的指南来设置跨应用音频:

  • hostandnodeAPP的inter-app-audio授权。
  • hostAPP打开UIBackgroundModesaudio开关。
  • nodeAPP打开UIBackgroundModesaudio开关,当nodeAPP同时连接到一个inter-appaudio host时使用输入或输出线路。
  • hostnodeAPP设置AVAudioSessionCategoryOptionMixWithOthers
  • nodeAPP同时连接到一个inter-appaudio host时,确保nodeAPP的audio session在接收来自系统的输入(或者发送音频输出)。

坚持原创技术分享,您的支持将鼓励我继续创作!