AVAudioSession

AVAudioSession类由AVFoundation框架引入。每个IOS应用都有一个音频会话。这个会话可以被AVAudioSession类的sharedInstance类方法访问,如下:

  1. AVAudioSession*audioSession = [AVAudioSession sharedInstance];
复制代码

 

在获得一个AVAudioSession类的实例后,你就能通过调用音频会话对象的setCategory:error:实例方法,来从IOS应用可用的不同类别中作出选择。下面列出了可供使用的音频会话类别:
AVAudioSessionCategorySoloAmbient


这个类别非常像AVAudioSessionCategoryAmbient类别,除了会停止其他程序的音频回放,比如iPod程序。当设备被设置为静音模式,你的音频回放将会停止。


AVAudioSessionCategoryRecord
这会停止其他应用的声音(比如iPod)并让你的应用也不能初始化音频回放(比如AVAudioPlayer)。在这种模式下,你只能进行录音。使用这个类别,调用AVAudioPlayer的prepareToPlay会返回YES,但是调用play方法将返回NO。主UI界面会照常工作。这时,即使你的设备屏幕被用户锁定了,应用的录音仍会继续。


AVAudioSessionCategoryPlayback
这个类别会静止其他应用的音频回放(比如iPod应用的音频回放)。你可以使用AVAudioPlayer的prepareToPlay和play方法,在你的应用中播放声音。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放都会继续。


AVAudioSessionCategoryPlayAndRecord
这个类别允许你的应用中同时进行声音的播放和录制。当你的声音录制或播放开始后,其他应用的声音播放将会停止。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放和录制都会继续。


AVAudioSessionCategoryAudioProcessing
这个类别用于应用中进行音频处理的情形,而不是音频回放或录制。设置了这种模式,你在应用中就不能播放和录制任何声音。调用AVAPlayer的prepareToPlay和play方法都将返回NO。其他应用的音频回放,比如iPod,也会在此模式下停止。


AVAudioSessionCategoryAmbient
这个类别不会停止其他应用的声音,相反,它允许你的音频播放于其他应用的声音之上,比如iPod。你的应用的主UI县城会工作正常。调用AVAPlayer的prepareToPlay和play方法都将返回YES。当用户锁屏时,你的应用将停止所有正在回放的音频。仅当你的应用是唯一播放该音频文件的应用时,静音模式将停止你程序的音频回放。如果正当iPod播放一手歌时,你开始播放音频,将设备设为静音模式并不能停止你的音频回放。







iOS 4开始引入的multitask,我们可以实现像ipod程序那样在后台播放音频了。 如果音频 操作是用苹果官方 的AVFoundation.framework实现,像用AvAudioPlayer,AvPlayer播放的话,要实现完美的后台音频播放,依据app的功能需要,可能需要实现几个关键的功能。

首先,播放音频之前先要设置AVAudioSession模式,通常只用来播放的App可以设为AVAudioSessionCategoryPlayback即可。模式意义及其他模式请参考文档。

[plain] view plain copy print ?
  1. AVAudioSession *session = [AVAudioSession sharedInstance];  
  2. [session setCategory:AVAudioSessionCategoryPlayback error:nil];  
  3. [session setActive:YES error:nil];  

1。通知OS该app支持background audio。缺省情况下,当按下home键时,当前正在运行的程序被suspend,状态从active变成in-active,也就是说如果正在播放音频,按下HOME后就会停止。这里需要让app在按在HOME后,转到后台运行而非被suspend,解决办法是在程序的-info.plist中增加required background modes这个key项,并选择App playsaudio这个value项。

AVAudioSession_第1张图片


2。现在按下HOME键后,程序退到后台,但是声音仍在播放。但是如果要实现播放列表的依次播放、循环播放,即放完一首后自动切换到下一首,问题来了,当App在后台放完一首后,就会停下来。原因是在后台运行时,一旦声音停下来,程序也随之suspend,因此在切换文件加载的间隙,程序就会被suspend。曾经有山寨的解决办法是专门起一个player的实例连续不停的放同一无声音片断,阻止程序被suspend。这里提供的方法是通过申请后台taskID达到后台切换播放文件的功能。

即声明后台taskid,并通过beginBackgroundTaskWithE
xpirationHandler将App设为后台Task,达到持续后台运行的目的。我们知道一般情况下,按HOME将程序送到后台,可以有5或10秒时间可以进行一些收尾工作,具体时间[[UIApplicationsharedApplication]backgroundTimeRemaining]返回值。超时后app会被suspend,现在要做的就是用[[UIApplicationsharedApplication]beginBackgroundTaskWithE xpirationHandler:NULL]开始后台任务,可以将后台运行超时时间长时间的延长,具体延长多少时间还是见返回值,总之对于放段时间音乐应该够了。另一个问题是每个开始的后台任务,都必须用endBackgroundTask来结束。因此,在每次开始播放后启动新的后台任务,同时结束上一个后台任务:

首先,要在viewdidload中

[plain] view plain copy print ?
  1. [UIApplication sharedApplication] beginReceivingRemoteControlEvents];  
否则,无法切换到下一首,接下来
[plain] view plain copy print ?
  1. UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;  
  2.       
  3. [avPlayer play];  
  4. newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];  
  5. if (newTaskId != UIBackgroundTaskInvalid && oldTaskId != UIBackgroundTaskInvalid) {  
  6.      [[UIApplication sharedApplication] endBackgroundTask: oldTaskId];}   
  7. oldTaskId = newTaskId;  

当然,还有更方便的办法就是在resignActive时beginBackgroundTaskWithExpirationHandler:并在BecomeActive中endBackgroundTask: 


3。我们知道,ipod播放程序在后台时,双击HOME键,会有个控制界面,可以对它进行播放控制。

AVAudioSession_第2张图片

如果您想让您的app可以像ipod一样在后台也可以方便的通过双击HOME键来控制,就要用到远程控制事件了。

首先在viewdidload等初始化的地方声明App接收远程控制事件,并在相应地方结束声明

[plain] view plain copy print ?
  1. - (void) viewWillAppear:(BOOL)animated  
  2. {  
  3. [super viewWillAppear:animated];  
  4. [UIApplication sharedApplication] beginReceivingRemoteControlEvents];  
  5. [self becomeFirstResponder];  
  6. }  
  7.   
  8. - (void) viewWillDisappear:(BOOL)animated  
  9. {  
  10. [super viewWillDisappear:animated];  
  11. [UIApplication sharedApplication] endReceivingRemoteControlEvents];  
  12. [self resignFirstResponder];  
  13. }  

定义
[plain] view plain copy print ?
  1. - (BOOL)canBecomeFirstResponder  
  2. {  
  3.        return YES;  
  4. }  

最后定义  remoteControlReceivedWithEvent,处理具体的播放、暂停、前进、后退等具体事件
[plain] view plain copy print ?
  1. - (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {      
  2.     if (receivedEvent.type == UIEventTypeRemoteControl) {  
  3.   
  4.         switch (receivedEvent.subtype) {  
  5.   
  6.             case UIEventSubtypeRemoteControlTogglePlayPause:  
  7.                 [self playButtonPressed:playButton];  
  8.                 [self testing];  
  9.                 break;  
  10.   
  11.             case UIEventSubtypeRemoteControlPreviousTrack:  
  12.                 [self rewButtonReleased:(UIButton *)rewButton];  
  13.                 break;  
  14.   
  15.             case UIEventSubtypeRemoteControlNextTrack:  
  16.                 [self ffwButtonReleased:(UIButton *)ffwButton];  
  17.                 break;  
  18.   
  19.             default:  
  20.                 break;  
  21.         }  
  22.     }  
  23. }  

4.至此,您有播放App已经相当完美了,还有最后一个问题,那就是当用户使用耳机时,问题又来了。系统默认当插入耳机时,正在播放的声音不中断,直接切换到耳机播放,而当拔出耳机时,播放停止。如果这种行为满足您的要求,那OK,否则您就需要进一步研究耳机检测和声音路由切换的问题。


你可能感兴趣的:(AVAudioSession)