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

iOS后台中断并恢复第三方媒体播放的问题求助

解决方案:iOS后台状态下暂停/恢复第三方媒体音频

错误原因分析

后台触发的AVAudioSessionErrorCodeCannotInterruptOthers(错误码560557684),本质是系统限制后台应用随意抢占活跃的第三方音频会话,结合你的代码场景,核心问题包括:

  • 未配置后台音频权限,系统不允许后台执行音频抢占操作
  • 使用AVAudioSessionCategoryPlayAndRecord类别但未获取麦克风权限
  • 音频播放器为局部变量,方法结束后被释放导致会话状态异常
  • 会话切换时未正确处理前后状态衔接

具体修复步骤

1. 配置后台音频与麦克风权限

在Info.plist中添加以下配置:

<!-- 后台音频权限 -->
<key>UIBackgroundModes</key>
<array>
    <string>audio</string>
</array>

<!-- 麦克风权限说明(PlayAndRecord类别必需) -->
<key>NSMicrophoneUsageDescription</key>
<string>需要访问麦克风以播放音频</string>

在代码中提前请求麦克风权限:

- (void)requestMicrophonePermission {
    [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
        if (granted) {
            [self setupAudioSession];
        } else {
            NSLog(@"麦克风权限被拒绝,无法正常使用音频功能");
        }
    }];
}

2. 优化初始音频会话配置

简化viewDidLoad中的会话初始化逻辑,避免频繁激活/停用:

- (void)setupAudioSession {
    NSError *error = nil;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    
    // 初始设置为可混合模式,不抢占第三方音频
    BOOL success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
                             withOptions:AVAudioSessionCategoryOptionMixWithOthers
                                   error:&error];
    if (!success) {
        NSLog(@"setCategoryError: %@", error.localizedDescription);
        return;
    }
    
    success = [session setMode:AVAudioSessionModeDefault error:&error];
    if (!success) {
        NSLog(@"setModeError: %@", error.localizedDescription);
        return;
    }
    
    success = [session setActive:YES error:&error];
    if (!success) {
        NSLog(@"activationError: %@", error.localizedDescription);
    }
}

// 在viewDidLoad中调用
- (void)viewDidLoad {
    [super viewDidLoad];
    [self requestMicrophonePermission];
}

3. 修改暂停第三方媒体的逻辑

将音频播放器改为全局属性,确保后台播放时不被释放;同时正确处理会话切换流程:

// 在头文件中声明全局播放器
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;

- (void)pauseBackgroundAudio {
    NSError *error = nil;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    
    // 先停用当前会话,避免状态冲突
    BOOL success = [session setActive:NO error:&error];
    if (!success) {
        NSLog(@"deactivationError: %@", error.localizedDescription);
    }
    
    // 设置为非混合模式,抢占第三方音频
    success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
                             withOptions:AVAudioSessionCategoryOptionsNone
                                   error:&error];
    if (!success) {
        NSLog(@"setCategoryError: %@", error.localizedDescription);
        return;
    }
    
    success = [session setMode:AVAudioSessionModeDefault error:&error];
    if (!success) {
        NSLog(@"setModeError: %@", error.localizedDescription);
        return;
    }
    
    // 激活会话,处理无法中断的异常
    success = [session setActive:YES error:&error];
    if (!success) {
        if (error.code == AVAudioSessionErrorCodeCannotInterruptOthers) {
            NSLog(@"后台无法抢占第三方音频,切换回混合模式播放");
            [session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
            [session setActive:YES error:nil];
        } else {
            NSLog(@"activationError: %@", error.localizedDescription);
        }
        return;
    }
    
    NSLog(@"starting playback (pauseBackgroundAudio)");
    
    NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"path1" withExtension:@"wav"];
    NSLog(@"%@", soundURL);
    
    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
    if (self.audioPlayer) {
        self.audioPlayer.delegate = self; // 监听播放完成事件
        [self.audioPlayer play];
    } else {
        NSLog(@"audioPlayer init error: %@", error.localizedDescription);
        [self resumeBackgroundAudio]; // 初始化失败,恢复第三方音频
    }
}

// 监听播放完成,自动恢复第三方音频
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    [self resumeBackgroundAudio];
}

4. 优化恢复第三方媒体的逻辑

确保恢复时先切换回混合模式,再通知其他应用继续播放:

- (void)resumeBackgroundAudio {
    NSError *sessionError = nil;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    
    // 切换回可混合模式
    BOOL success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
                             withOptions:AVAudioSessionCategoryOptionMixWithOthers
                                   error:&sessionError];
    if (!success) {
        NSLog(@"setCategoryError when resume: %@", sessionError.localizedDescription);
    }
    
    // 停用会话并通知其他应用恢复播放
    success = [session setActive:NO
                    withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
                          error:&sessionError];
    if (!success) {
        NSLog(@"deactivationError when resume: %@", sessionError.localizedDescription);
    }
    
    NSLog(@"stopping playback (resumeBackgroundAudio)");
    self.audioPlayer = nil;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:37:02