React Native集成Twilio Voice与callkeep后通话立即中断问题求助
问题:Expo React Native集成Twilio Voice与react-native-callkeep时通话被自动终止
我用Expo开发React Native应用,集成Twilio Voice SDK和react-native-callkeep处理VoIP来电,目标是有VoIP来电时通过react-native-callkeep展示iOS原生CallKit来电UI,用户接听后连接到Twilio会议通话。
当前问题:通话能短暂成功连接,但react-native-callkeep随即触发endCall事件终止通话。推测是CallKeep与Twilio Voice SDK的音频会话冲突——当Twilio SDK激活音频会话时,CallKit将其视为其他通话接管,从而结束当前管理的通话。
控制台日志事件序列:
1 LOG DEBUG: Twilio: Call.Event.Connected event received 2 LOG ============================================================ 3 LOG TwilioService: ✅ CALL CONNECTED 4 LOG TwilioService: Call SID: CA3e35f733949a1b8b30ada886241de85c 5 LOG TwilioService: Call State: connected 6 LOG TwilioService: Is Muted: false 7 LOG ============================================================ 8 LOG CallManager: Twilio call connected 9 LOG CallManager: State change: CONNECTING -> CONNECTED 10 LOG useCallManager: Call state changed: CONNECTED 11 LOG DEBUG: CallKeep endCall event received for UUID: e31feea4-6a02-4555-8d09-c061cc17ef83 12 LOG DEBUG: Active session matches. Current state: CONNECTED 13 LOG DEBUG: Call is connected, calling endCall() 14 LOG CallManager: Ending call 15 LOG CallManager: Handling call ended
已尝试方案:
- 延迟Twilio连接至CallKeep的
didActivateAudioSession事件触发后,同步音频会话激活:- 用户通过CallKit接听时触发
answerCall事件,向后端请求Twilio参会信息 - 收到参会信息后存储至
this.conferenceJoinInfo - 监听CallKeep的
didActivateAudioSession事件,触发后再连接Twilio
但问题仍存在。
- 用户通过CallKit接听时触发
相关代码(call-manager.ts):
// services/call-manager.ts // ... (imports and class definition) private initializeCallKeep(): Promise<void> { // ... await RNCallKeep.setup({ ios: { appName: 'My VoIP App', // ... other options }, // ... }); this.setupCallKeepListeners(); // ... } private setupCallKeepListeners(): void { RNCallKeep.addEventListener('answerCall', async ({ callUUID }) => { if (this.activeSession && this.activeSession.callUUID === callUUID) { await this.handleAcceptCall(); } }); RNCallKeep.addEventListener('endCall', async ({ callUUID }) => { // ... (logic to end or reject the call) }); RNCallKeep.addEventListener('didActivateAudioSession', () => { if (this.conferenceJoinInfo) { this.connectTwilio(); } }); } private async handleConferenceJoinInfo(message: any): Promise<void> { this.conferenceJoinInfo = message; // Now we wait for the didActivateAudioSession event } private async connectTwilio(): Promise<void> { if (!this.conferenceJoinInfo) { return; } // ... (logic to extract token and other info from conferenceJoinInfo) const call = await twilioService.connectToConference( twilioToken, conferenceId, backendUrl ); // ... }
解决方案:正确管理音频会话与事件序列
核心是确保Twilio Voice SDK完全复用CallKit管理的音频会话,避免独立激活音频会话触发CallKit的终止逻辑,具体步骤如下:
1. 禁用Twilio自动管理音频会话
在Twilio连接配置中,强制禁用其自动创建和管理音频会话,改用CallKeep的音频会话:
// 修改twilioService.connectToConference方法的连接逻辑 const call = await TwilioVoice.connect({ accessToken: twilioToken, params: { 'ConferenceName': conferenceId, 'TwilioBackendUrl': backendUrl }, // 关键配置:禁止Twilio自行管理音频会话 audioSession: { enabled: false } });
2. 手动接管音频会话的激活与停用
在CallKeep的音频会话事件中,手动控制Twilio的音频会话状态:
// 在setupCallKeepListeners中补充监听 RNCallKeep.addEventListener('didActivateAudioSession', async () => { if (this.conferenceJoinInfo) { await this.connectTwilio(); // 连接成功后手动激活Twilio音频会话 await TwilioVoice.audioSession.start(); } }); RNCallKeep.addEventListener('didDeactivateAudioSession', async () => { // 通话结束后停用Twilio音频会话 await TwilioVoice.audioSession.stop(); });
3. 同步CallKit与Twilio的通话状态
Twilio通话连接成功后,必须通知CallKeep更新状态为已连接,避免状态不一致触发终止:
// 在connectTwilio方法中,Twilio连接成功后添加状态同步 call.on('connected', async () => { await RNCallKeep.reportConnected(this.activeSession.callUUID); });
4. 修正事件触发顺序
在answerCall事件中,先通知CallKeep标记通话为进行中,再请求Twilio参会信息:
private async handleAcceptCall() { // 先告知CallKeep开始通话 await RNCallKeep.startCall(this.activeSession.callUUID, this.activeSession.callerId, 'My VoIP App'); // 再请求后端获取Twilio参会信息 const conferenceInfo = await this.requestConferenceJoinInfo(); this.handleConferenceJoinInfo(conferenceInfo); }
5. 优化CallKeep初始化配置
确保CallKeep初始化时开启音频会话共享模式:
await RNCallKeep.setup({ ios: { appName: 'My VoIP App', audioSessionMode: 'voiceChat', audioSessionActive: true, audioSessionPreferredSampleRate: 44100, audioSessionPreferredIOBufferDuration: 0.005 } });
内容的提问来源于stack exchange,提问作者Zeeshan Ghazanfar
相关产品推荐
相关产品推荐

