CoderMrWu

生活诚可期,爱情价更高!

IOS音频3:AVAudioSession的使用

AVAudioSession简介

AVAudioSession是用来管理多个APP对音频硬件设备(麦克风,扬声器)的资源使用。

AVAudioSession 可以用来做哪些事呢?

  • 设置自己APP是否和其他APP音频同时存在,还是中断其他APP声音
  • 在手机调到静音模式下,自己的APP的音频是否可以播放出声音
  • 电话或者其他APP中断自己APP的音频的事件处理
  • 指定音频输入和输出设备(比如是听筒输出声音,还是扬声器输出声音)
  • 是否支持录音,录音同时是否支持音频播放

AVAudioSession Category 属性

1、使用案例:

AVAudioSession * audioSession = [AVAudioSession sharedInstance];
 // 设置 Category属性    
 [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
 // 激活 AVAudioSession    
 [audioSession setActive:YES error:nil];
category 是否允许录音/音频播放 是否打断其他不支持混音APP 是否会被静音键或锁屏键静音
AVAudioSessionCategoryAmbient 只支持播放
AVAudioSessionCategoryAudioProcessing 不支持播放,不支持录制
AVAudioSessionCategoryMultiRoute 支持播放,支持录制
AVAudioSessionCategoryPlayAndRecord 支持播放,支持录制 默认YES,可以重写为NO
AVAudioSessionCategoryPlayback 只支持播放 默认YES,可以重写为NO
AVAudioSessionCategoryRecord 只支持录制 否(锁屏下仍可录制)
AVAudioSessionCategorySoloAmbient 只支持播放

2、参数解释说明:

  • AVAudioSessionCategoryAmbient,只支持音频播放。这个 Category,音频会被静音键和锁屏键静音。并且不会打断其他应用的音频播放。
  • AVAudioSessionCategorySoloAmbient,这个是系统默认使用的 Category,只支持音频播放。音频会被静音键和锁屏键静音。和AVAudioSessionCategoryAmbient不同的是,这个会打断其他应用的音频播放
  • AVAudioSessionCategoryPlayback 只支持音频播放。你的音频不会被静音键和锁屏键静音。适用于音频是主要功能的APP,像网易云这些音乐app,锁屏后依然可以播放。
  • AVAudioSessionCategoryRecord 只支持音频录制。不支持播放。
  • AVAudioSessionCategoryPlayAndRecord 支持音频播放和录制。音频的输入和输出不需要同步进行,也可以同步进行。需要音频通话类应用,可以使用这个 Category。
  • AVAudioSessionCategoryAudioProcessing 只支持本地音频编解码处理。不支持播放和录制。
  • AVAudioSessionCategoryMultiRoute 支持音频播放和录制。允许多条音频流的同步输入和输出。(比如USB连接外部扬声器输出音频,蓝牙耳机同时播放另一路音频这种特殊需求)

3、获取当前设置支持的Category:

@property(readonly) NSArray *availableCategories;

AVAudioSession Mode 属性

1、方法展示

-(BOOL)setCategory:(NSString *)category mode:(NSString *)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));

2、参数说明

模式 兼容的 Category 场景
AVAudioSessionModeDefault All 默认模式
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord VoIP
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 游戏录制,GKVoiceChat自动设置
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord 录制视频
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 视频播放
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback 最小系统
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord 视频通话

3、参数解释

  • AVAudioSessionModeDefault,默认模式,与所有的 Category 兼容
  • AVAudioSessionModeVoiceChat,适用于VoIP 类型的应用。只能是 AVAudioSessionCategoryPlayAndRecord Category下。在这个模式系统会自动配置AVAudioSessionCategoryOptionAllowBluetooth 这个选项。系统会自动选择最佳的内置麦克风组合支持语音聊天。
  • AVAudioSessionModeVideoChat,用于视频聊天类型应用,只能是 AVAudioSessionCategoryPlayAndRecord Category下。适在这个模式系统会自动配置 AVAudioSessionCategoryOptionAllowBluetooth 和 AVAudioSessionCategoryOptionDefaultToSpeaker 选项。系统会自动选择最佳的内置麦克风组合支持视频聊天。
  • AVAudioSessionModeGameChat,适用于游戏类应用。使用 GKVoiceChat 对象的应用会自动设置这个模式和 AVAudioSessionCategoryPlayAndRecord Category。实际参数和AVAudioSessionModeVideoChat一致。
  • AVAudioSessionModeVideoRecording,适用于使用摄像头采集视频的应用。只能是 AVAudioSessionCategoryPlayAndRecord 和 AVAudioSessionCategoryRecord 这两个 Category下。这个模式搭配 AVCaptureSession API 结合来用可以更好地控制音视频的输入输出路径。(例如,设置 automaticallyConfiguresApplicationAudioSession 属性,系统会自动选择最佳输出路径。
  • AVAudioSessionModeMeasurement,最小化系统。只用于 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayback 这几种 Category。
  • AVAudioSessionModeMoviePlayback,适用于播放视频的应用。只用于 AVAudioSessionCategoryPlayback 这个Category。

AVAudioSession Option 参数

1、参数说明

Option Option功能说明 兼容的 Category
AVAudioSessionCategoryOptionMixWithOthers 支持和其他APP音频 mix AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionDuckOthers 系统智能调低其他APP音频音量 AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionAllowBluetooth 支持蓝牙音频输入 AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionDefaultToSpeaker 设置默认输出音频到扬声器 AVAudioSessionCategoryPlayAndRecord

音频中断处理

1、处理音频中断的方式

通过监听AVAudioSessionInterruptionNotification这个key获取音频中断事件,通知回调回来的UserInfo有键值:AVAudioSessionInterruptionTypeKey

  • 取值AVAudioSessionInterruptionTypeBegan表示中断开始
  • 取值AVAudioSessionInterruptionTypeEnded表示中断结束

中断开始:我们需要做的是保存好播放状态,上下文,更新用户界面等

中断结束:我们要做的是恢复好状态和上下文,更新用户界面,根据需求准备好之后选择是否激活我们session。

2、 处理不同音频播放方式的中断

  • System Sound Services:使用 System Sound Services 播发音频,系统会自动处理,不受APP控制,当中断发生时,音频播放会静音,当中断结束后,音频播放会恢复。
  • AV Foundation framework:AVAudioPlayer 类和 AVAudioRecorder 类提供了中断开始和结束的 Delegate 回调方法来处理中断。中断发生,系统会自动停止播放,需要做的是记录播放时间等状态,更新用户界面,等中断结束后,再次调用播放方法,系统会自动激活session。
  • Audio Queue Services, I/O audio unit:使用aduio unit这些技术需要处理中断,需要做的是记录播放或者录制的位置,中断结束后自己恢复audio session。
  • OpenAL:使用 OpenAL 播放时,同样需要自己监听中断。管理 OpenAL上下文,用户中断结束后恢复audio session。

3、注意

  1. 有中断开始事件,不一定对应有中断结束事件,所以需要在用户进入前台,点击UI操作的时候,需要保存好播放状态和对Audio Session管理,以便不影响APP的音频功能。
  2. 音频资源竞争上,一定是电话优先。
  3. AVAudioSession同样可以监听外设音频状态,比如耳机拔入拔出。

简单示例代码:

 #import "AudioToolboxController.h"
 #import <AVFoundation/AVFoundation.h>
 

 @interface AudioToolboxController ()
 

 @property(nonatomic,strong)AVPlayer * player;
 

 @property(nonatomic,strong)AVPlayerItem * playerItem;
 

 @end
 

 @implementation AudioToolboxController
 
// 初始化播放器
 -(AVPlayer *)player{
     if (!_player) {
         
         NSString * path = [[NSBundle mainBundle] pathForResource:@"多幸运" ofType:@"mp3"];
         
         NSURL * url = [NSURL fileURLWithPath:path];
         
         _playerItem = [[AVPlayerItem alloc] initWithURL:url];
         
         _player = [[AVPlayer alloc] initWithPlayerItem:_playerItem];
         
     }
     return _player;
 }
 

 - (void)viewDidLoad {
     [super viewDidLoad];
     
     self.view.backgroundColor = [UIColor whiteColor];
     
     [self.player play];
     
     AVAudioSession * audioSession = [AVAudioSession sharedInstance];
     
     // 读取当前设备支持的Category
     NSLog(@"%@",audioSession.availableCategories);
     
     // 设置Category
     [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
     
     // 设置 Category Mode Options
     [audioSession setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
     
     [audioSession setActive:YES error:nil];
     
     // 注册监听中断的通知
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getUerinfo:) name:@"AVAudioSessionInterruptionNotification" object:nil];
     
 }
 -(void)getUerinfo:(NSNotification *)notification{
     NSLog(@"%@",notification.userInfo);
     
     // 当打开其他音频软件时,会执行这段代码
     if ([notification.userInfo[@"AVAudioSessionInterruptionTypeKey"]intValue] == AVAudioSessionInterruptionTypeBegan) {
         // 当其他软件抢占资源时,暂停播放
         [self.player pause];
     }
     
     // 当其他软件进入后台或者被杀死进程之后,本软件就会执行这段代码
     if ([notification.userInfo[@"AVAudioSessionInterruptionTypeKey"] intValue] == AVAudioSessionInterruptionTypeEnded) {
         // 当其他软件让出资源,本软软件开始播放
         [self.player play];
         
     }
 }
 
 @end 

其他与AVAudioSession相关知识点:

1、 检测App是否获取了录音权限

 // 请求录音权限
 [audioSession requestRecordPermission:^(BOOL granted) {
    NSLog(@"%d",granted);
 }]; 

2、判断手机现在是否有其他应用在播放音频

    //判断其他应用是否在播放音频: IOS6开始可以使用
    if (audioSession.otherAudioPlaying) {
        NSLog(@"其他应用正在播放音频");
    }else{
        NSLog(@"没有应用正在播放!");
    }
    
    //判断其他应用是否在播放音频: IOS8开始可以使用
    if(audioSession.secondaryAudioShouldBeSilencedHint){
        NSLog(@"其他应用正在播放音频");
    }else{
        NSLog(@"没有应用正在播放!");
    }

3、AVAudioSession 相关的通知

    // 音频发生中断时的通知
    AVAudioSessionInterruptionNotification
    
    //系统的音频路线更改时的通知
    AVAudioSessionRouteChangeNotification
    
    //当其他应用程序的主要音频启动或停止是的通知
    AVAudioSessionSilenceSecondaryAudioHintNotification
    
    //媒体服务器终止是的通知
    AVAudioSessionMediaServicesWereLostNotification
    
    //媒体服务器重新启动时的通知
    AVAudioSessionMediaServicesWereResetNotification

点赞