在iOS开发中,只要涉及音频播放、录制(如音乐播放器、语音通话、录音APP),就绕不开AVAudioSession。它是iOS系统管理音频资源的“总管家”,负责协调APP与系统、其他APP之间的音频抢占、路由切换(扬声器/耳机/蓝牙)、音量控制等核心逻辑。
很多开发者在开发音频相关功能时,常会遇到“播放没声音”“插入耳机不切换路由”“后台播放被中断”“与其他音频APP冲突”等问题,本质上都是对AVAudioSession的机制理解不透彻,尤其是分类、模式的选择和激活策略的运用出现了偏差。
本文将从基础概念入手,逐步拆解 AVAudioSession 的完整机制,重点讲解分类、模式的核心作用及选型逻辑,结合激活策略和实战避坑,搭配可直接复用的代码示例,帮你彻底掌握这个iOS音频开发的核心知识点。
一、先搞懂:AVAudioSession 到底是什么?
AVAudioSession 是 Apple 提供的音频会话管理类(隶属于 AVFoundation 框架),它的核心作用是统一管理APP的音频行为,并与系统音频服务进行通信,解决“多个音频APP共存时的资源竞争”“音频硬件(扬声器、耳机等)的路由分配”“音频场景适配”三大核心问题。
简单来说,你的APP想播放或录制音频,必须先通过 AVAudioSession 向系统“报备”自己的音频需求(比如“我要播放音乐,希望能后台播放”“我要录音,需要关闭其他音频”),系统再根据所有APP的“报备”情况,分配音频资源、决定音频路由。
核心特性总结:
单例模式:整个APP只有一个 AVAudioSession 实例,通过
[AVAudioSession sharedInstance]获取,全局共享。行为契约:通过“分类+模式”定义APP的音频行为,系统根据这个契约分配资源。
路由管理:自动或手动控制音频输出/输入路由(扬声器、耳机、蓝牙音箱、麦克风等)。
状态监听:监听音频会话的中断(如来电、闹钟)、路由变化(插入/拔出耳机)等事件,适配场景变化。
### 基础使用代码(OC/Swift)
无论后续配置分类、模式,第一步都是获取单例并导入头文件,以下是基础模板代码,可直接复用:
// OC 基础模板(需导入 AVFoundation 头文件) #import <AVFoundation/AVFoundation.h> // 获取 AVAudioSession 单例 AVAudioSession *audioSession = [AVAudioSession sharedInstance]; // 快速判断当前会话激活状态 BOOL isActive = audioSession.isActive; NSLog(@"当前音频会话激活状态:%@", isActive ? @"已激活" : @"未激活");// Swift 基础模板(需导入 AVFoundation 框架) import AVFoundation // 获取 AVAudioSession 单例 let audioSession = AVAudioSession.sharedInstance() // 快速判断当前会话激活状态 let isActive = audioSession.isActive print("当前音频会话激活状态:isActive ? \"已激活\" : \"未激活\")")二、核心机制1:音频会话分类(Category)—— 定义音频行为的“基础规则”
分类(Category)是 AVAudioSession 最核心的配置,它直接决定了APP的音频行为边界,比如“是否允许后台播放”“是否与其他音频APP共存”“是否需要使用麦克风”。
Apple 提供了7种官方分类(iOS 10+ 稳定支持),每种分类对应特定的音频场景,开发者需根据APP的核心功能选择,不可随意搭配。下面重点讲解常用分类,结合场景说明选型逻辑,并附上对应配置代码。
1. 常用核心分类(必掌握)
(1)AVAudioSessionCategoryPlayback —— 纯播放场景(推荐音乐/视频APP)
核心作用:用于仅播放音频的场景(如音乐播放器、播客APP),是最常用的分类之一。
关键特性:
默认不允许与其他音频APP共存(会抢占其他APP的音频资源,比如打开你的音乐APP,其他正在播放的音乐APP会暂停)。
支持后台播放(需在 Info.plist 中配置
UIBackgroundModes→audio)。支持静音开关控制(静音模式下,若未连接耳机,音频会静音;连接耳机则正常播放)。
不使用麦克风(若需同时播放+录音,不可用此分类)。
### 配置代码(音乐播放器场景)
// OC 配置:纯音乐播放(支持后台播放) #import <AVFoundation/AVFoundation.h> - (void)configurePlaybackCategory { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; // 配置分类为 Playback,模式为默认,允许蓝牙输出 [audioSession setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionAllowBluetooth error:&error]; if (error) { NSLog(@"Playback 分类配置失败:%@", error.localizedDescription); return; } // 激活会话(后续会详细讲解激活策略) [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]; if (error) { NSLog(@"会话激活失败:%@", error.localizedDescription); } }// Swift 配置:纯音乐播放(支持后台播放) import AVFoundation func configurePlaybackCategory() { let audioSession = AVAudioSession.sharedInstance() do { // 配置分类为 Playback,模式为默认,允许蓝牙输出 try audioSession.setCategory(.playback, mode: .default, options: .allowBluetooth) // 激活会话 try audioSession.setActive(true, options: .notifyOthersOnDeactivation) } catch { print("Playback 分类配置/激活失败:\(error.localizedDescription)") } }备注:配置后台播放时,需在 Info.plist 中添加UIBackgroundModes数组,添加audio字段,否则退到后台后音频会立即停止。
适用场景:音乐播放器、视频播放器、有声书APP。
(2)AVAudioSessionCategoryRecord —— 纯录音场景(推荐录音/语音APP)
核心作用:用于仅录制音频的场景(如录音APP、语音备忘录)。
关键特性:
会强制抢占所有音频资源,其他正在播放的音频APP会立即暂停。
不支持后台录音(除非配置后台模式,但需注意隐私权限,且iOS对后台录音有严格限制)。
必须请求麦克风权限(Info.plist 配置
NSMicrophoneUsageDescription)。静音开关不影响录音(即使手机静音,麦克风依然可以正常录音)。
### 配置代码(录音APP场景)
// OC 配置:纯录音(需先请求麦克风权限) #import <AVFoundation/AVFoundation.h> - (void)configureRecordCategory { // 1. 请求麦克风权限 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { if (!granted) { NSLog(@"麦克风权限未授权,无法录音"); return; } // 2. 配置录音分类 AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; [audioSession setCategory:AVAudioSessionCategoryRecord mode:AVAudioSessionModeDefault options:0 error:&error]; if (error) { NSLog(@"Record 分类配置失败:%@", error.localizedDescription); return; } // 3. 激活会话 [audioSession setActive:YES error:&error]; if (error) { NSLog(@"会话激活失败:%@", error.localizedDescription); } }]; }// Swift 配置:纯录音(需先请求麦克风权限) import AVFoundation func configureRecordCategory() { // 1. 请求麦克风权限 AVCaptureDevice.requestAccess(for: .audio) { granted in guard granted else { print("麦克风权限未授权,无法录音") return } // 2. 配置录音分类 let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory(.record, mode: .default) // 3. 激活会话 try audioSession.setActive(true) } catch { print("Record 分类配置/激活失败:\(error.localizedDescription)") } } }备注:Info.plist 需添加NSMicrophoneUsageDescription(描述麦克风使用场景,如“用于录制语音”),否则会崩溃。
适用场景:录音APP、语音备忘录、语音输入功能。
(3)AVAudioSessionCategoryPlayAndRecord —— 播放+录音场景(推荐语音通话/直播APP)
核心作用:用于同时需要播放和录制音频的场景,是语音通话、直播、K歌APP的核心分类。
关键特性:
支持同时使用扬声器/耳机(播放)和麦克风(录音)。
默认不与其他音频APP共存(会抢占资源),但可通过配置选项允许共存。
支持后台播放/录音(需配置后台模式)。
必须请求麦克风权限,静音开关不影响录音,但会影响播放(静音模式下扬声器无声音)。
### 配置代码(语音通话场景,最常用)
// OC 配置:语音通话(支持蓝牙、默认扬声器输出) #import <AVFoundation/AVFoundation.h> - (void)configurePlayAndRecordCategory { // 1. 请求麦克风权限 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { if (!granted) { NSLog(@"麦克风权限未授权,无法进行语音通话"); return; } AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; // 配置分类:PlayAndRecord,模式:VoiceChat(语音通话优化) // 选项:允许蓝牙、默认扬声器输出、允许与其他音频混音 AVAudioSessionCategoryOptions options = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers; [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeVoiceChat options:options error:&error]; if (error) { NSLog(@"PlayAndRecord 分类配置失败:%@", error.localizedDescription); return; } // 激活会话,退出时通知其他APP恢复音频 [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]; if (error) { NSLog(@"会话激活失败:%@", error.localizedDescription); } }]; }// Swift 配置:语音通话(支持蓝牙、默认扬声器输出) import AVFoundation func configurePlayAndRecordCategory() { // 1. 请求麦克风权限 AVCaptureDevice.requestAccess(for: .audio) { granted in guard granted else { print("麦克风权限未授权,无法进行语音通话") return } let audioSession = AVAudioSession.sharedInstance() do { // 配置分类:PlayAndRecord,模式:VoiceChat(语音通话优化) // 选项:允许蓝牙、默认扬声器输出、允许与其他音频混音 let options: AVAudioSession.CategoryOptions = [.allowBluetooth, .defaultToSpeaker, .mixWithOthers] try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: options) // 激活会话,退出时通知其他APP恢复音频 try audioSession.setActive(true, options: .notifyOthersOnDeactivation) } catch { print("PlayAndRecord 分类配置/激活失败:\(error.localizedDescription)") } } }补充:该分类可通过AVAudioSessionCategoryOptionMixWithOthers选项实现与其他音频APP共存(如语音通话时允许背景音乐播放),适合直播、K歌场景。同时,语音通话场景下搭配AVAudioSessionModeVoiceChat模式,可自动开启回声消除、降噪功能,提升通话清晰度。
适用场景:语音通话(微信/QQ电话)、直播APP、K歌APP、语音助手。
(4)AVAudioSessionCategoryAmbient —— 背景音场景(推荐游戏/工具APP)
核心作用:用于非核心的背景音频(如游戏背景音乐、工具APP的提示音),优先级最低。
关键特性:
允许与其他音频APP共存(比如用户打开音乐APP播放音乐,你的APP的背景音会混合播放,或被压低音量)。
不支持后台播放(APP退到后台后,音频会立即停止)。
受静音开关控制(静音模式下,音频会静音)。
### 配置代码(游戏背景音场景)
// OC 配置:游戏背景音(允许与其他音频共存) #import <AVFoundation/AVFoundation.h> - (void)configureAmbientCategory { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; // 配置分类为 Ambient,无需额外选项(默认允许共存) [audioSession setCategory:AVAudioSessionCategoryAmbient mode:AVAudioSessionModeDefault options:0 error:&error]; if (error) { NSLog(@"Ambient 分类配置失败:%@", error.localizedDescription); return; } // 激活会话(背景音场景可延迟激活,避免过早抢占资源) [audioSession setActive:YES error:&error]; if (error) { NSLog(@"会话激活失败:%@", error.localizedDescription); } }// Swift 配置:游戏背景音(允许与其他音频共存) import AVFoundation func configureAmbientCategory() { let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory(.ambient, mode: .default) try audioSession.setActive(true) } catch { print("Ambient 分类配置/激活失败:\(error.localizedDescription)") } }备注:该分类优先级最低,不会抢占其他APP的音频,适合作为“辅助音频”(如游戏音效、APP提示音),用户打开音乐播放器时,背景音会自动混合播放或被压低音量。
适用场景:游戏背景音乐、APP操作提示音、闹钟APP的背景音。
2. 其他补充分类(了解即可)
AVAudioSessionCategorySoloAmbient(默认分类):与 Ambient 类似,但会抢占其他音频资源(其他APP音频暂停),不支持后台播放,适合简单的提示音场景。
AVAudioSessionCategoryMultiRoute:多路由输出,允许音频同时输出到多个设备(如同时连接耳机和蓝牙音箱,两者都能播放),适合专业音频场景。
AVAudioSessionCategoryAudioProcessing:用于音频处理(无播放/录音,仅处理音频数据),适合音频编辑APP。
### 多路由分类配置代码(专业场景)
// OC 配置:多路由输出(专业音频场景) - (void)configureMultiRouteCategory { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; [audioSession setCategory:AVAudioSessionCategoryMultiRoute mode:AVAudioSessionModeDefault options:0 error:&error]; if (error) { NSLog(@"MultiRoute 分类配置失败:%@", error.localizedDescription); } }3. 分类选型核心原则
记住一个核心逻辑:根据APP的“核心音频行为”选择分类,不要过度配置。比如:
只播放音乐 → 选 Playback,不要选 PlayAndRecord(浪费资源,还需额外请求麦克风权限)。
语音通话 → 选 PlayAndRecord,不要选 Playback+Record 组合(分类本身已支持双功能)。
游戏背景音 → 选 Ambient,不要选 Playback(避免抢占用户的音乐播放)。
补充:实际开发中,可先通过audioSession.availableCategories读取当前设备支持的分类,避免配置不兼容的分类导致失败。
三、核心机制2:音频会话模式(Mode)—— 优化特定场景的“补充规则”
模式(Mode)是对分类的“补充优化”,它不能单独使用,必须搭配分类一起配置,用于适配特定的音频场景(如语音通话、视频通话、录音),让音频行为更贴合场景需求。
简单来说,分类定义了“能做什么”(播放/录音/共存),模式定义了“怎么做更好”(适配特定场景的音频优化)。下面讲解常用模式及搭配逻辑,附上对应搭配代码。
1. 常用模式及搭配场景
(1)AVAudioSessionModeDefault —— 默认模式(通用)
所有分类都可以搭配此模式,无额外优化,适用于大多数通用场景(如普通音乐播放、普通录音)。
搭配示例:Playback + Default(音乐播放器)、Record + Default(普通录音)。
### 搭配代码(普通音乐播放)
// OC:Playback + Default 搭配(普通音乐播放) - (void)configurePlaybackWithDefaultMode { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; [audioSession setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionAllowBluetooth error:&error]; if (error) { NSLog(@"配置失败:%@", error.localizedDescription); } }(2)AVAudioSessionModeVoiceChat —— 语音通话模式(重点)
核心优化:针对实时语音通话(如微信电话、手机通话),优化音频质量(降低延迟、降噪),并自动适配路由(插入耳机时切换到耳机,拔出时切换到扬声器)。
搭配要求:仅支持 PlayAndRecord 分类(因为语音通话需要同时播放和录音)。
关键特性:自动启用“回声消除”“降噪”功能,提升语音清晰度;支持蓝牙耳机的通话模式。
### 搭配代码(实时语音通话)
// Swift:PlayAndRecord + VoiceChat 搭配(语音通话) func configureVoiceChatMode() { let audioSession = AVAudioSession.sharedInstance() do { // 仅能搭配 PlayAndRecord 分类 try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.allowBluetooth, .defaultToSpeaker]) try audioSession.setActive(true) } catch { print("语音通话模式配置失败:\(error.localizedDescription)") } }补充:该模式下,系统会自动优化语音传输延迟,开启回声消除和降噪,适合微信语音、手机通话等实时场景,搭配AVAudioSessionCategoryOptionAllowBluetooth可支持蓝牙耳机通话。
(3)AVAudioSessionModeVideoChat —— 视频通话模式
核心优化:针对视频通话(如微信视频、FaceTime),在语音通话优化的基础上,适配视频场景的音频同步(降低音视频延迟)。
搭配要求:仅支持 PlayAndRecord 分类,与 VoiceChat 类似,但更侧重音视频同步。
### 搭配代码(视频通话)
// OC:PlayAndRecord + VideoChat 搭配(视频通话) - (void)configureVideoChatMode { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; AVAudioSessionCategoryOptions options = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker; [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeVideoChat options:options error:&error]; if (error) { NSLog(@"视频通话模式配置失败:%@", error.localizedDescription); } }(4)AVAudioSessionModeMeasurement —— 精准录音模式
核心优化:针对精准录音(如音频分析、专业录音),关闭所有音频处理(降噪、回声消除),保留原始音频数据,确保录音的准确性。
搭配要求:支持 PlayAndRecord、Record 分类。
适用场景:音频分析APP、专业录音APP。
### 搭配代码(专业录音)
// Swift:Record + Measurement 搭配(精准录音) func configureMeasurementMode() { let audioSession = AVAudioSession.sharedInstance() do { // 搭配 Record 分类,关闭所有音频处理,保留原始数据 try audioSession.setCategory(.record, mode: .measurement) try audioSession.setActive(true) } catch { print("精准录音模式配置失败:\(error.localizedDescription)") } }(5)AVAudioSessionModeMoviePlayback —— 视频播放模式
核心优化:针对视频播放,优化音频与视频的同步,提升播放流畅度,支持多声道音频。
搭配要求:仅支持 Playback 分类。
### 搭配代码(视频播放)
// OC:Playback + MoviePlayback 搭配(视频播放) - (void)configureMoviePlaybackMode { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *error = nil; [audioSession setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeMoviePlayback options:AVAudioSessionCategoryOptionAllowAirPlay error:&error]; if (error) { NSLog(@"视频播放模式配置失败:%@", error.localizedDescription); } }补充:该模式优化了音视频同步逻辑,支持多声道音频和AirPlay输出,适合视频播放器、影视APP场景。
2. 模式搭配核心原则
模式必须与分类匹配,不可随意搭配(如 VoiceChat 不能搭配 Playback 分类)。
无需优化的场景,用 Default 模式即可,不要画蛇添足(如普通音乐播放,无需搭配 MoviePlayback)。
特定场景优先用对应模式(如语音通话用 VoiceChat,精准录音用 Measurement),能大幅提升用户体验。
四、核心机制3:激活策略 —— 让音频会话“生效”的关键操作
配置好分类和模式后,必须通过“激活”操作,让音频会话生效。激活(activate)是 AVAudioSession 与系统建立连接的过程,也是音频资源分配的触发点。
很多开发者配置完分类和模式后,发现音频没声音,大概率是没有激活会话,或激活时机、方式错误。下面讲解激活的核心要点、时机和注意事项,附上完整激活代码。
1. 激活的核心API(iOS 10+ 推荐)
// 获取单例 AVAudioSession *session = [AVAudioSession sharedInstance]; // 配置分类和模式(示例:语音通话场景) NSError *error = nil; [session setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeVoiceChat options:AVAudioSessionCategoryOptionAllowBluetooth error:&error]; if (error) { NSLog(@"分类模式配置失败:%@", error.localizedDescription); return; } // 核心激活API(iOS 10+),带选项控制 // 选项说明: // AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation:退出激活时,通知其他APP恢复音频 // AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation:激活时,不中断其他APP音频(需配合分类options) [session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]; if (error) { NSLog(@"会话激活失败:%@", error.localizedDescription); } else { NSLog(@"会话激活成功,可正常播放/录音"); } // 取消激活(退出音频场景时调用) [session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];// Swift 核心激活API(iOS 10+) let session = AVAudioSession.sharedInstance() do { // 配置分类和模式 try session.setCategory(.playAndRecord, mode: .voiceChat, options: .allowBluetooth) // 激活会话,退出时通知其他APP恢复音频 try session.setActive(true, options: .notifyOthersOnDeactivation) print("会话激活成功,可正常播放/录音") // 取消激活(退出音频场景时调用) // try session.setActive(false, options: .notifyOthersOnDeactivation) } catch { print("会话配置/激活失败:\(error.localizedDescription)") }2. 激活的核心时机(避坑关键)
激活时机直接影响用户体验和功能稳定性,推荐以下3种核心时机,附上对应代码逻辑:
(1)延迟激活(推荐)
不要在APP启动时就激活会话,避免过早抢占其他APP的音频资源(如用户正在听音乐,打开你的APP就中断音乐,体验极差)。建议在“即将播放/录音”时激活。
// OC:延迟激活(点击播放按钮时激活) - (IBAction)playButtonClick:(UIButton *)sender { // 1. 配置分类和模式(提前配置,或首次点击时配置) [self configurePlaybackCategory]; // 2. 激活会话(即将播放时激活) AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *error = nil; [session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]; if (error) { NSLog(@"激活失败:%@", error.localizedDescription); return; } // 3. 开始播放音频 [self.audioPlayer play]; }(2)退出场景时取消激活
当APP退出音频场景(如关闭播放页面、退出录音),必须取消激活会话,避免占用音频资源,同时通知其他APP恢复音频。
// Swift:退出页面时取消激活 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) let session = AVAudioSession.sharedInstance() do { // 取消激活,通知其他APP恢复音频 try session.setActive(false, options: .notifyOthersOnDeactivation) print("会话已取消激活") } catch { print("取消激活失败:\(error.localizedDescription)") } }(3)中断后重新激活
当音频会话被系统中断(如来电、闹钟),中断结束后需重新激活会话,恢复音频播放/录音。需先监听中断事件,再执行重新激活。
// OC:监听中断事件,重新激活会话 #import <AVFoundation/AVFoundation.h> @interface ViewController () <AVAudioSessionDelegate> @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 设置代理,监听中断事件 AVAudioSession *session = [AVAudioSession sharedInstance]; session.delegate = self; } // 监听音频会话中断(来电、闹钟等) - (void)audioSessionInterruptionNotification:(NSNotification *)notification { NSInteger type = [[notification.userInfo objectForKey:AVAudioSessionInterruptionTypeKey] integerValue]; // 中断结束,重新激活会话 if (type == AVAudioSessionInterruptionTypeEnded) { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *error = nil; [session setActive:YES error:&error]; if (!error) { NSLog(@"中断结束,重新激活会话,恢复播放"); // 恢复播放/录音 [self.audioPlayer play]; } } }3. 激活的注意事项(避坑重点)
同一时间只能有一个会话处于激活状态,若多个地方调用激活,会导致冲突(报错:AVAudioSessionErrorCodeResourceBusy)。
激活前必须先配置分类和模式,否则会激活失败(报错:AVAudioSessionErrorCodeNotConfigured)。
录音场景激活前,必须先获取麦克风权限,否则会崩溃或激活失败。
取消激活时,建议使用
AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation选项,提升用户体验(如退出APP后,恢复之前的音乐播放)。iOS 14+ 需注意:多次频繁激活/取消激活,可能触发系统Bug,建议添加状态判断,避免重复操作。
五、实战避坑:常见问题及解决方案(附代码)
结合实际开发中高频遇到的问题,整理4个核心避坑点,附上解决方案和代码,帮你快速排查问题。
1. 问题1:播放没声音(最常见)
核心原因:未激活会话、分类配置错误、静音开关影响、路由错误。
// Swift:排查播放没声音的核心代码 func checkNoSoundIssue() { let session = AVAudioSession.sharedInstance() // 1. 检查会话是否激活 guard session.isActive else { print("会话未激活,尝试重新激活") do { try session.setActive(true) } catch { print(error) } return } // 2. 检查分类是否正确(纯播放需用 Playback) guard session.category == .playback else { print("分类配置错误,重新配置 Playback 分类") do { try session.setCategory(.playback, mode: .default) } catch { print(error) } return } // 3. 检查静音开关状态(Playback 分类,静音模式下耳机可正常播放) let isSilent = session.category == .playback && !session.isOtherAudioPlaying && session.outputVolume == 0 if isSilent { print("当前处于静音模式,连接耳机可正常播放") } // 4. 检查音频路由(是否输出到扬声器/耳机) print("当前音频输出路由:\(session.currentRoute.outputs.first?.portType.rawValue ?? "未知")") }2. 问题2:录音失败/无声音
核心原因:未获取麦克风权限、分类错误(未用 Record/PlayAndRecord)、会话未激活。
// OC:录音失败排查代码 - (void)checkRecordIssue { // 1. 检查麦克风权限 AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; if (status != AVAuthorizationStatusAuthorized) { NSLog(@"麦克风权限未授权,请求权限"); [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {}]; return; } // 2. 检查分类(录音需用 Record 或 PlayAndRecord) AVAudioSession *session = [AVAudioSession sharedInstance]; if (![session.category isEqualToString:AVAudioSessionCategoryRecord] && ![session.category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) { NSLog(@"分类错误,重新配置录音分类"); [self configureRecordCategory]; return; } // 3. 检查会话是否激活 if (!session.isActive) { NSLog(@"会话未激活,重新激活"); [session setActive:YES error:nil]; } }3. 问题3:后台播放中断
核心原因:未配置后台模式、退出时未取消激活、分类不支持后台播放。
解决方案:1. Info.plist 配置UIBackgroundModes→audio;2. 用 Playback/PlayAndRecord 分类;3. 后台播放时保持会话激活。
4. 问题4:与其他音频APP冲突(打开APP,其他APP音频暂停)
核心原因:分类默认不允许混音,未配置AVAudioSessionCategoryOptionMixWithOthers选项。
// Swift:允许与其他音频APP共存(混音) func configureMixWithOthers() { let session = AVAudioSession.sharedInstance() do { // 配置分类时,添加 mixWithOthers 选项 try session.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .allowBluetooth]) try session.setActive(true) print("已配置混音,可与其他音频APP共存") } catch { print("配置混音失败:\(error.localizedDescription)") } }补充:该配置适合直播、K歌等需要同时播放背景音乐和录音的场景,需注意部分分类(如 Record)不支持混音选项。
六、总结
AVAudioSession 的核心机制,本质是“分类定义基础行为,模式优化特定场景,激活触发资源分配”。掌握这三者的搭配逻辑,就能解决绝大多数iOS音频开发中的问题。
核心总结:
分类:选对场景(纯播放→Playback,录音→Record,通话→PlayAndRecord),不盲目配置。
模式:特定场景用对应模式(语音通话→VoiceChat,视频播放→MoviePlayback),通用场景用Default。
激活:延迟激活、及时取消、中断后重新激活,避免资源冲突和用户体验问题。
本文所有代码均可直接复制到项目中复用,建议根据自己的APP场景(播放/录音/通话),选择对应的分类、模式和激活策略,同时注意权限配置和避坑点。
最后提醒:音频开发的核心是“贴合用户场景”,不同场景的配置差异较大,建议开发时多测试不同场景(静音模式、后台、耳机切换、来电中断),确保功能稳定。