在iOS应用开发中,使用AVAudioRecorder进行录音时,常遇到因来电或闹钟触发导致录音被意外中断的问题。即使应用进入后台,系统会暂停音频会话,造成录音停止且无法自动恢复。开发者需监听AVAudioSession.interruptionNotification通知,正确处理中断开始与结束状态。但常见问题在于:中断结束后,部分设备未能正确重新激活音频会话,或未及时重启录音,导致录音丢失。如何确保在中断恢复后无缝继续录音,并兼容不同iOS版本的音频会话行为,成为稳定实现后台录音的关键挑战。
2条回答 默认 最新
关注让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。
如果答案能帮助您,请采纳,非常感谢!
.
每日一句正能量,让它带给您好心情:努力的人,自带光芒,走到哪里都能照亮一片天。
.在 iOS 开发中处理录音中断需要正确处理音频会话中断通知,并在中断结束后重新激活会话和录音。以下是完整的实现方案:
1. 设置音频会话类别
import AVFoundation func setupAudioSession() { do { let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth]) try audioSession.setActive(true) } catch { print("设置音频会话失败: \(error.localizedDescription)") } }2. 注册中断通知
class AudioRecorderManager: NSObject { private var audioRecorder: AVAudioRecorder? private var isInterrupted = false private var shouldResume = false override init() { super.init() setupNotifications() } private func setupNotifications() { NotificationCenter.default.addObserver( self, selector: #selector(handleAudioSessionInterruption(_:)), name: AVAudioSession.interruptionNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(handleAppWillResignActive), name: UIApplication.willResignActiveNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(handleAppDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil ) } }3. 处理音频中断的核心逻辑
extension AudioRecorderManager { @objc private func handleAudioSessionInterruption(_ notification: Notification) { guard let userInfo = notification.userInfo, let interruptionTypeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt, let interruptionType = AVAudioSession.InterruptionType(rawValue: interruptionTypeValue) else { return } switch interruptionType { case .began: // 中断开始 handleInterruptionBegan() case .ended: // 中断结束 guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return } let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue) handleInterruptionEnded(shouldResume: options.contains(.shouldResume)) @unknown default: break } } private func handleInterruptionBegan() { isInterrupted = true // 暂停录音但不释放资源 audioRecorder?.pause() // 保存当前录音状态 shouldResume = audioRecorder?.isRecording ?? false print("录音被中断") } private func handleInterruptionEnded(shouldResume: Bool) { isInterrupted = false // 重新激活音频会话 do { let audioSession = AVAudioSession.sharedInstance() try audioSession.setActive(true, options: .notifyOthersOnDeactivation) // 如果需要恢复且之前正在录音 if shouldResume && self.shouldResume { resumeRecording() } } catch { print("重新激活音频会话失败: \(error.localizedDescription)") // 可以在这里添加重试逻辑 attemptToRecoverFromError() } } }4. 恢复录音的实现
extension AudioRecorderManager { private func resumeRecording() { guard let recorder = audioRecorder else { return } // 检查录音器状态 if recorder.isRecording { return // 已经在录音 } do { // iOS 16+ 兼容性处理 if #available(iOS 16.0, *) { // 确保音频会话已激活 let audioSession = AVAudioSession.sharedInstance() if !audioSession.isOtherAudioPlaying { try audioSession.setActive(true) } } // 恢复录音 recorder.record() print("录音已恢复") } catch { print("恢复录音失败: \(error.localizedDescription)") // 失败后尝试重新创建录音器 recreateRecorderAfterInterruption() } } private func recreateRecorderAfterInterruption() { guard let currentRecorder = audioRecorder, let url = currentRecorder.url else { return } let settings = currentRecorder.settings let currentTime = currentRecorder.currentTime do { // 创建新的录音器实例 let newRecorder = try AVAudioRecorder(url: url, settings: settings) newRecorder.delegate = self newRecorder.isMeteringEnabled = true if newRecorder.prepareToRecord() { audioRecorder = newRecorder // 从上次中断的位置继续录音 if newRecorder.record(atTime: currentTime) { print("录音器重新创建并恢复成功") } } } catch { print("重新创建录音器失败: \(error.localizedDescription)") } } }5. 应用前后台状态处理
extension AudioRecorderManager { @objc private func handleAppWillResignActive() { // 应用进入后台前的处理 if audioRecorder?.isRecording == true { shouldResume = true } } @objc private func handleAppDidBecomeActive() { // 应用回到前台后的检查 if shouldResume && !isInterrupted { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.resumeRecording() } } } private func attemptToRecoverFromError() { // 错误恢复策略 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { do { try AVAudioSession.sharedInstance().setActive(true) self.resumeRecording() } catch { print("恢复尝试失败: \(error.localizedDescription)") } } } }6. 完整的录音管理器示例
class AudioRecorderManager: NSObject, AVAudioRecorderDelegate { static let shared = AudioRecorderManager() private var audioRecorder: AVAudioRecorder? private var isInterrupted = false private var shouldResume = false private var currentRecordingURL: URL? private override init() { super.init() setupNotifications() setupAudioSession() } func startRecording() throws { let audioSession = AVAudioSession.sharedInstance() try audioSession.setActive(true) let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let audioFilename = documentsPath.appendingPathComponent("recording-\(Date().timeIntervalSince1970).m4a") currentRecordingURL = audioFilename let settings: [String: Any] = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100.0, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings) audioRecorder?.delegate = self audioRecorder?.isMeteringEnabled = true audioRecorder?.prepareToRecord() if audioRecorder?.record() == true { print("开始录音") } } func stopRecording() { audioRecorder?.stop() shouldResume = false } // AVAudioRecorderDelegate func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { print("录音完成: \(flag)") } func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) { if let error = error { print("录音编码错误: \(error.localizedDescription)") } } deinit { NotificationCenter.default.removeObserver(self) } }关键要点
- 及时处理中断通知:在中断开始时暂停录音,保存状态
- 正确重新激活会话:中断结束后重新激活音频会话
- 兼容性处理:考虑不同 iOS 版本的音频会话行为差异
- 错误恢复机制:提供重试逻辑来处理恢复失败的情况
- 前后台状态协调:结合应用生命周期管理录音状态
这种实现方案能够有效处理来电、闹钟等系统事件导致的中断,确保录音能够在中断结束后无缝恢复。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报