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

iOS 18.2下VoIP通话应用单向音频问题排查求助

针对iOS 18.2间歇性单向音频问题的解决方案

以下是结合你的场景(PortSIP SDK + RNCallKeep)给出的针对性修复方案:

1. 校准音频会话激活时机与CallKit回调的协同

iOS 18对CallKit与AVAudioSession的交互时序要求更严格,间歇性问题大概率是会话激活与CallKit动作的竞争冲突导致。需确保在CallKit的通话启动/接听回调中,先完成音频会话配置再初始化PortSIP通话:

- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *error = nil;

    // 配置音频会话(添加MixWithOthers避免与系统音频冲突)
    BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord
                                        mode:AVAudioSessionModeVoiceChat
                                     options:AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionMixWithOthers
                                       error:&error];
    if (!success) {
        NSLog(@"音频会话配置失败: %@", error.localizedDescription);
    }

    // 激活会话并设置通知其他应用
    success = [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
    if (!success) {
        NSLog(@"音频会话激活失败: %@", error.localizedDescription);
    }

    // 初始化PortSIP通话逻辑
    [self initPortSIPCallWithAction:action];

    // 完成CallKit动作
    [action fulfill];
}

2. 禁用PortSIP SDK的自动音频会话管理

PortSIP SDK默认会自动管理AVAudioSession,与RNCallKeep的配置易产生冲突。需手动禁用此功能,统一由RNCallKeep或自定义代码管理:

// 在PortSIP SDK初始化时设置
PortSIPSDK *sdk = [PortSIPSDK sharedInstance];
[sdk setAudioSessionManagementEnabled:NO];

3. 监听音频路由变化并主动修复

iOS 18的音频路由切换逻辑有调整,可通过监听路由变化通知,在设备接入/断开时强制重置音频会话:

// 初始化时添加观察者
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleAudioRouteChange:)
                                             name:AVAudioSessionRouteChangeNotification
                                           object:[AVAudioSession sharedInstance]];

// 路由变化处理函数
- (void)handleAudioRouteChange:(NSNotification *)notification {
    AVAudioSessionRouteChangeReason reason = [[notification.userInfo objectForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
    
    // 设备接入/断开时重置音频会话
    if (reason == AVAudioSessionRouteChangeReasonNewDeviceAvailable || reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        NSError *error = nil;
        
        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeVoiceChat options:AVAudioSessionCategoryOptionAllowBluetooth error:&error];
        [audioSession setActive:YES error:&error];
        
        // 通知PortSIP更新音频设备
        [[PortSIPSDK sharedInstance] updateAudioDevice];
    }
}

4. 升级RNCallKeep至最新版本

旧版本RNCallKeep未适配iOS 18的音频会话逻辑,升级到最新版本可修复已知兼容性问题:

# yarn 升级
yarn upgrade react-native-callkeep@latest

# npm 升级
npm update react-native-callkeep@latest

5. 前置检查麦克风权限状态

iOS 18对权限获取的时机要求更严格,需在发起通话前确保麦克风权限已授予:

- (void)preCheckMicrophonePermissionBeforeCall {
    AVAudioSessionRecordPermission permission = [[AVAudioSession sharedInstance] recordPermission];
    
    if (permission == AVAudioSessionRecordPermissionUndetermined) {
        [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (granted) {
                    [self startCall];
                } else {
                    [self showPermissionAlert];
                }
            });
        }];
    } else if (permission == AVAudioSessionRecordPermissionDenied) {
        [self showPermissionAlert];
    } else {
        [self startCall];
    }
}

- (void)showPermissionAlert {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"麦克风权限不足" message:@"请在设置中开启麦克风权限以正常通话" preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"前往设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
    }]];
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

6. 调整RNCallKeep的音频会话配置

尝试补充更多配置项,确保与系统音频逻辑对齐:

NSDictionary *audioSessionConfig = @{
    @"category": @"playAndRecord",
    @"mode": @"voiceChat",
    @"categoryOptions": @(AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker),
    @"active": @YES
};

[RNCallKeep setup:@{
    @"appName": @"My App",
    @"maximumCallGroups": @1,
    @"maximumCallsPerCallGroup": @1,
    @"includesCallsInRecents": @NO,
    @"supportsVideo": @NO,
    @"imageName": @"app-icon.png",
    @"audioSession": audioSessionConfig
}];

额外排查点

  • 查看PortSIP SDK的日志输出,检查是否有麦克风初始化失败、音频流启动异常等错误信息;
  • 测试通话时关闭其他占用音频的应用(如音乐、视频APP),排除资源竞争问题;
  • 尝试在通话启动后延迟0.5秒再激活音频会话,避免与系统初始化流程冲突。

内容的提问来源于stack exchange,提问作者Sandun Isuru Niraj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:14:51