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

CallKit结合TokBox使用时扬声器自动激活且无法关闭问题求助

Fixing Auto-Activated Speaker Issue with CallKit + TokBox

I’ve run into this exact audio routing headache with TokBox and CallKit before—super frustrating when the speaker sticks on even after tapping to disable it. Let’s break down the fixes that worked for me, aligned with how apps like WhatsApp and Messenger handle this flow:

1. Take Control of Audio Session in CallKit’s Activation Callback

CallKit takes over the audio session when a call is answered, and TokBox’s default settings can clash with this. You need to explicitly set the audio route to the earpiece right after CallKit activates the session.

Add this to your CXProviderDelegate implementation:

- (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession {
    // Link TokBox to the CallKit-managed audio session first
    [[OTDefaultAudioDevice sharedInstance] setAudioSession:audioSession];
    
    // Force route audio to earpiece (system default) instead of speaker
    NSError *routeError;
    [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&routeError];
    if (routeError) {
        NSLog(@"Failed to adjust audio route: %@", routeError.localizedDescription);
    }
}

AVAudioSessionPortOverrideNone tells the system to use the default audio route (earpiece for calls) instead of forcing speaker output.

2. Delay TokBox Audio Initialization Until After Call Acceptance

Don’t initialize TokBox’s audio device or start your OTSession until the user has actually answered the call. If you set up TokBox before CallKit activates the audio session, it might grab control and lock the speaker on.

Wait until the didActivateAudioSession callback fires, then finish setting up your TokBox call flow—this ensures the audio session is properly managed by CallKit first.

3. Override Unexpected Route Changes

Sometimes system events (like a Bluetooth disconnect) can trigger unwanted route switches. Add a listener to catch these and correct the route back to the earpiece:

// Register the notification in your view controller/manager init
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleAudioRouteShift:)
                                             name:AVAudioSessionRouteChangeNotification
                                           object:[AVAudioSession sharedInstance]];

// Handle route changes
- (void)handleAudioRouteShift:(NSNotification *)notification {
    NSDictionary *routeInfo = notification.userInfo;
    AVAudioSessionRouteChangeReason reason = [routeInfo[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
    
    // If the route switched unexpectedly, force it back to earpiece
    if (reason == AVAudioSessionRouteChangeReasonCategoryChange || reason == AVAudioSessionRouteChangeReasonOverride) {
        AVAudioSession *activeSession = [AVAudioSession sharedInstance];
        NSError *correctionError;
        [activeSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&correctionError];
    }
}

4. Check TokBox’s Default Speaker Setting

Double-check if TokBox’s audio device is defaulting to speakerphone. Some SDK versions have useSpeakerphone enabled by default—disable it before starting your call:

// Call this before initiating/accepting the TokBox call
[[OTDefaultAudioDevice sharedInstance] setUseSpeakerphone:NO];

Why This Works (Like WhatsApp/Messenger)

Apps like WhatsApp don’t let TokBox’s default audio settings override CallKit’s session management. They strictly enforce audio routing rules immediately after CallKit activates the session, ensuring the earpiece is used by default. The key is keeping the audio session under CallKit’s control and only letting TokBox interact with it after the session is properly configured.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:19:08