官方API文档是这样对AVAudioSession描述的:
audiosession负责调节你的app和iOS系统里的音频行为.一旦加载了audiosession你可以获得一个audiosession的单例.你可以配置这个audiosession来控制你的app的音频行为.例如:
当你的app播放声音的时候,你是希望其他正在播放声音的app静音还是混合两个app的声音?
你的app如何回应突发的打断,例如这时候闹铃突然响了?
你的app又该如何回应耳机口的拔插呢?
AuioSession的配置会影响你的app在运行中所有的音频活动,除了利用System Sounds Services API控制的音频.
你还可以利用AudioSession来检测你所用硬件的参数,例如声道和采样率.
你还可以随时激活或者停止你的audioSession,当你的app播放声音或者正在录音的时候,你必须确保AudioSession处于激活状态.
系统也有权利随时中断你的audioSession,例如,当你来电话的时候.当然,AudioSession提供了api来让你的app从这种中断中恢复.
一、
AVAudioSessionCategoryAmbient,//用于播放。随静音键和屏幕关闭而静音。不终止其它应用播放声音
AVAudioSessionCategorySoloAmbient,//用于播放。随静音键和屏幕关闭而静音。终止其它应用播放声音
AVAudioSessionCategoryPlayback,//用于播放。不随静音键和屏幕关闭而静音。终止其它应用播放声音,需要在工程里设置targets->capabilities->选择backgrounds modes->勾选audio,airplay,and picture in picture
AVAudioSessionCategoryPlayAndRecord,//用于播放和录音。不随着静音键和屏幕关闭而静音。终止其他应用播放声音
AVAudioSessionCategoryMultiRoute//用于播放和录音。不随着静音键和屏幕关闭而静音。可多设备输出
AVAudioSession类由AVFoundation框架引入。每个IOS应用都有一个音频会话。这个会话可以被AVAudioSession类的sharedInstance类方法访问,如下:
AVAudioSession*audioSession = [AVAudioSession sharedInstance];
在获得一个AVAudioSession类的实例后,你就能通过调用音频会话对象的setCategory:error:实例方法,来从IOS应用可用的不同类别中作出选择。下面列出了可供使用的音频会话类别:
AVAudioSessionCategoryAmbient:
用于非以语音为主的应用,随着静音键和屏幕关闭而静音。不中止其它应用播放声音,可以和其它自带应用如iPod,safari等同时播放声音。锁屏时,应用将停止所有正在回放的音频。如果正当iPod播放一手歌时,你开始播放音频,将设备设为静音模式并不能停止你的音频回放。
AVAudioSessionCategorySoloAmbient(默认类别)
这个类别非常像AVAudioSessionCategoryAmbient类别,除了会停止其他程序的音频回放,比如iPod程序。当设备被设置为静音模式,你的音频回放将会停止。
AVAudioSessionCategoryPlayback
会静止其他应用的音频回放(比如iPod应用的音频回放)。你可以使用AVAudioPlayer的prepareToPlay和play方法,在你的应用中播放声音。屏幕被锁定或者设备为静音模式,音频会放都会继续。
AVAudioSessionCategoryRecord
这会停止其他应用的声音(比如iPod)并让你的应用也不能初始化音频回放(比如AVAudioPlayer)。在这种模式下,你只能进行录音。使用这个类别,调用AVAudioPlayer的prepareToPlay会返回YES,但是调用play方法将返回NO。主UI界面会照常工作。这时,即使你的设备屏幕被用户锁定了,应用的录音仍会继续。
AVAudioSessionCategoryPlayAndRecord
这个类别允许你的应用中同时进行声音的播放和录制。当你的声音录制或播放开始后,其他应用的声音播放将会停止。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放和录制都会继续。
AVAudioSessionCategoryAudioProcessing
这个类别用于应用中进行音频处理的情形,而不是音频回放或录制。设置了这种模式,你在应用中就不能播放和录制任何声音。调用AVAPlayer的prepareToPlay和play方法都将返回NO。其他应用的音频回放,比如iPod,也会在此模式下停止。
//判断如果其他应用有正在播放的音频 恢复播放。
[[AVAudioSession sharedInstance] setActive:NO
withFlags:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
error:nil];
情况一:用户按home键主动退到后台,一般的音乐类播放软件都会有后台播放的设置,不用进行额外的操作,但是如果是正在播放视频的话,退到后台后视频应该是暂停状态,这时我们只需要在AppDelegate的相关方法中进行主动的设置就可以
//程序即将进入后台
- (void)applicationWillResignActive:(UIApplication *)application {
//这里可以用通知中心的方式,通知视频播放的界面将UI更新为暂停的状态(视频会自动暂停)
[[NSNotificationCenter defaultCenter] postNotificationName:BackgroundOperation object:@"willResignActive"];
}
//程序即将进入活跃状态
- (void)applicationDidBecomeActive:(UIApplication *)application {
//此时程序已经回到前台,如果需要的话可以让视频继续播放,让UI切换到播放的状态,如果不需要可以什么都不做
[[NSNotificationCenter defaultCenter] postNotificationName:BackgroundOperation object:@"didBecomeActive"];
}
情况二:被电话或者其他App播放的声音打断,此时就需要我们在程序中去监听这些事件,当事件被触发时进行相应的操作
//监测被中断的事件
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(isPlayerPlaying:) name:AVAudioSessionInterruptionNotification object:nil];
其中AVAudioSessionInterruptionNotification就是系统提供的被中断的通知
然后在被打断时进行相应的操作
//检测歌曲被打断事件(别的软件播放音乐,来电话)
- (void)isPlayerPlaying:(NSNotification *)notification {
NSInteger type = [[notification.userInfo valueForKey:@"AVAudioSessionInterruptionTypeKey"] integerValue];
if (type == 1) {
//在这里进行你想要的操作
}
}
音乐类软件为了提高用户体验一般都会添加耳机线控音乐的功能(单机暂停/播放,双击下一曲,点击三下上一曲),还可以对耳机的插拔进行监听
监听耳机的插拔:
//监听耳机的插拔
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
//相应的事件
- (void)routeChange:(NSNotification *)notification {
NSDictionary *interuptionDict = notification.userInfo;
NSInteger roteChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
switch (roteChangeReason) {
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
//插入耳机
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
//拔出耳机
NSLog(@"拔出耳机");
[self pausePlay];
break;
}
}
//上面的roteChangeReason还有其他的集中类型,代表了其他的状态,可以对应的进行不同的操作
点击耳机中键的事件:
首先要在程序入口处让app接收远程控制事件
//让app支持接收远程控制事件
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
然后在远程事件通知中进行相应的操作(这个通知还会接收系统上拉菜单中的控制中心的播放和暂停按钮)
//app接受远程控制(控制中心 耳机等)
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl) {
switch (event.subtype) {
case 100:
//控制中心的播放按钮
[[PlayingManager defaultManager] musicPlay];
break;
case 101:
//控制中心的暂停按钮
[[PlayingManager defaultManager] pausePlay];
break;
case 103:{
//耳机的单击事件 根据音乐的播放状态选择暂停或播放
if ([[PlayingManager defaultManager] getStateOfPlayer]) {
[[PlayingManager defaultManager] pausePlay];
} else {
[[PlayingManager defaultManager] musicPlay];
}
}
break;
case 104:
//耳机的双击中键事件
[[PlayingManager defaultManager] nextMusic];
break;
case 105:
//耳机的中键盘点击三下触发的时间
[[PlayingManager defaultManager] beforeMusic];
break;
default:
break;
}
}
}