AVAudioSession简介
官方文档镇楼
https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Introduction/Introduction.html
音频在iOS,tvOS
是一种托管服务。系统通过使用音频会话管理应用程序、应用程序间和设备级别的音频行为。
我们使用AVAudioSession
来与系统沟通在我们的应用程序中使用音频。我们可以做的交互如下
- 配置音频会话类别(
Category
)和模式(mode
),以便与系统通信,了解您打算如何在应用程序中使用音频 - 激活应用程序的音频会话,将类别(
Category
)和模式(mode
)配置放入操作中 - 订阅和响应重要的音频会话通知,例如音频中断(
AVAudioSessionInterruptionNotification
)和路由更改(AVAudioSessionRouteChangeNotification
) - 执行高级音频设备配置,如设置
采样速率
、I/O
缓冲区持续时间和通道数量
AVAudioSession
是App和System之间的中介,在App启动的时候,应用程序会自动提供一个AVAudioSession
单例,你通过设置这个单例来实现音频配置。
https://developer.apple.com/videos/play/wwdc2012/505/
https://developer.apple.com/library/archive/qa/qa1754/_index.html
音频的激活
官方文档
https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/ConfiguringanAudioSession/ConfiguringanAudioSession.html#//apple_ref/doc/uid/TP40007875-CH2-SW1
音频竞争
当我们的App启动时,内置的应用程序或者其他App(消息、音乐、Safari、手机)可能正在后台运行。它们中的每一个都可能产生音频:一条文本消息到达,音乐后台播放。
Q1:当QQ音乐后台播放时,你的App需要播放声音,如何处理这种竞争关系呢?
系统处理音频竞争图如下:
背景:Music App正在占用音频播放。此时我们的MyApp需要进行音频播放
1-2.MyApp请求CoreAudio控制中心,我请求激活音频会话
//get your app's audioSession singleton object
AVAudioSession* session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker |AVAudioSessionCategoryOptionAllowBluetooth
error:nil];
[session setMode:AVAudioSessionModeDefault error:&error];
[session setActive:YES error:&error];
3-4.通过MyApp的设置代码,CoreAudio考虑其类别,对其他音频进行处理
如果,您的应用程序使用了一个类别(不是AVAudioSessionCategoryOptionMixWithOthers),该类别要求对其他音频进行静音,系统将关闭音乐应用程序的音频会话,停止其音频播放。
5.系统(CoreAudio)激活您的应用程序的音频会话和播放可以开始。
音频打断恢复
Q2:当你的App正在播放,此时来了一个电话,接听电话后,如何让App恢复音频播放?
AVAudioSessionInterruptionNotification
https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioInterruptions/HandlingAudioInterruptions.html
当电话打断,短信打断时,此类音频打断我们都会受到一个AVAudioSessionInterruptionNotification
通知,通过监听这个通知,我们处理App的音频恢复播放
AVAudioSession *session = [AVAudioSession sharedInstance];
NSNotificationCenter *noficationCenter = [NSNotificationCenter defaultCenter];
[noficationCenter addObserver: self
selector: @selector(handleRouteChange:)
name: AVAudioSessionRouteChangeNotification
object: session]; //这是route改变通知,例如耳机插拔
[noficationCenter addObserver: self
selector: @selector(handleInterruption:)
name: AVAudioSessionInterruptionNotification
object: session]; //这是音频打断通知
以下是我的项目中处理打断通知的模板,[AVAudioSession sharedInstance].secondaryAudioShouldBeSilencedHint
指示另一应用程序是否正在播放音频,与otherAudioPlaying
一样,只是在iOS 8
之后,其判断更加严格
- (void)handleInterruption:(NSNotification*)notification {
NSInteger reason = 0;
NSString *reasonStr = @"";
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
//Posted when an audio interruption occurs.
//bug https://blog.csdn.net/shengpeng3344/article/details/83617979
if ([[[UIDevice currentDevice] systemVersion] compare:@"10.3" options:NSNumericSearch] != NSOrderedAscending) {
BOOL isSuspend = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionWasSuspendedKey] boolValue];
if (isSuspend) {
LogInfo(@"[GSAudioStreamer] AVAudioSessionInterruptionWasSuspendedKey is YES");
return;
}
} else {
// Fallback on earlier versions
}
reason