You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apple Watch后台定时启停录音触发561015905错误求助

解决后台定时启停录音的AVFAudio错误561015905

错误原因解析

错误码561015905对应AVAudioSessionErrorCannotActivateInBackground,核心问题是:iOS不允许应用在后台直接激活纯录音类别的AVAudioSession,后台音频权限仅支持持续的音频任务,而你当前用Timer+主队列延迟的方式,触发时机不符合系统的后台音频会话规则。

针对性解决思路

1. 调整AVAudioSession的类别与激活时机

  • 不要提前在startPeriodicMonitoring中激活会话,改为每次录音启动前激活,结束后按需停用(停用会话时保留权限相关选项,避免系统回收后台资格)。
  • 替换record类别为playAndRecord,该类别对后台环境的兼容性更好,即使你不需要播放功能:
func startMonitoring() {
    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(.playAndRecord, mode: .default, options: [.mixWithOthers, .allowBluetooth])
        try session.setActive(true, options: .notifyOthersOnDeactivation)
        // 执行你的录音启动逻辑
    } catch {
        print("激活录音会话失败: \(error.localizedDescription)")
    }
}

func stopMonitoring() {
    let session = AVAudioSession.sharedInstance()
    do {
        try session.setActive(false, options: .notifyOthersOnDeactivation)
        // 执行你的录音停止逻辑
    } catch {
        print("停用录音会话失败: \(error.localizedDescription)")
    }
}

2. 替换Timer为后台安全的调度方式

Timer.scheduledTimer依赖主RunLoop,应用进入后台后主RunLoop可能被挂起,导致定时器失效。改用DispatchSourceTimer(基于GCD)实现后台定时:

private var measurementTimer: DispatchSourceTimer?

func startPeriodicMonitoring() {
    let queue = DispatchQueue(label: "com.yourapp.recording.timer", qos: .background)
    measurementTimer = DispatchSource.makeTimerSource(queue: queue)
    // 立即触发,之后按interval重复,预留100ms误差缓冲
    measurementTimer?.schedule(deadline: .now(), repeating: measurementInterval, leeway: .milliseconds(100))
    measurementTimer?.setEventHandler { [weak self] in
        guard let self = self else { return }
        DispatchQueue.main.async {
            self.startMonitoring()
            DispatchQueue.main.asyncAfter(deadline: .now() + self.recordingDuration) {
                self.stopMonitoring()
            }
        }
    }
    measurementTimer?.resume()
}

3. 修正后台权限配置

  • 移除WKBackgroundModes配置:该字段仅针对WatchKit应用,iOS应用无需设置,避免混淆系统权限判断。
  • 精简UIBackgroundModes:只保留audio项,self-care权限与iOS后台录音无关,可删除。

4. 维持后台音频会话活跃性

如果录音间隔较长,系统可能回收应用后台权限。可以播放一段静音音频来维持会话活跃:

private var silentPlayer: AVPlayer?

func setupSilentPlayer() {
    guard let silentURL = Bundle.main.url(forResource: "silent", withExtension: "mp3") else { return }
    silentPlayer = AVPlayer(url: silentURL)
    silentPlayer?.actionAtItemEnd = .none
    // 监听音频结束事件,循环播放静音
    NotificationCenter.default.addObserver(self, selector: #selector(restartSilentPlayback), name: .AVPlayerItemDidPlayToEndTime, object: silentPlayer?.currentItem)
}

@objc func restartSilentPlayback() {
    silentPlayer?.seek(to: .zero)
    silentPlayer?.play()
}

启动定时录音前调用setupSilentPlayer()并启动播放,确保后台音频会话持续活跃。

额外注意事项

  • 确认Info.plist中已配置NSMicrophoneUsageDescription,后台录音同样需要用户授权麦克风权限。
  • iOS对后台音频的管控严格,频繁启停录音可能被判定为权限滥用,建议尽量减少录音次数,或改为持续录音后分段处理。

内容的提问来源于stack exchange,提问作者MahanTp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:37:32