sip_ua网络中断后通话无法重连问题及优化需求
问题:sip_ua 网络中断后重连导致对方通话终止
sip_ua 包目前无内置机制处理通话过程中的网络中断场景,无法自动检测网络断开、尝试重连并恢复通话。我尝试用 renegotiate 函数实现自定义重连逻辑,但网络恢复后调用该函数会意外终止对方通话,而非重新协商连接,这严重限制了库在网络波动场景下的实用性。
复现步骤
- 使用 sip_ua 库发起并保持通话;
- 通话过程中断开网络;
- 检测到网络恢复后调用
renegotiate函数尝试重连。
预期行为
网络恢复时应重新协商连接,恢复通话且不终止对方通话。
代码片段
@override Future<void> callStateChanged(Call call, CallState callState) async { if (call.peerConnection != null) { monitorConnectionState(call); } } Timer? connectivityTimer; int retryCount = 0; void monitorConnectionState(Call call) { if (call.peerConnection?.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateDisconnected) { startConnectivityCheck(call); } } void startConnectivityCheck(Call call) { stopConnectivityCheck(); retryCount = 0; connectivityTimer = Timer.periodic(const Duration(seconds: 1), (timer) async { retryCount++; bool isInternetAvailable = await ConnectivityHelper.hasInternetConnection(); if (isInternetAvailable) { stopConnectivityCheck(); renegotiateCall(call); } if (retryCount >= 10) { stopConnectivityCheck(); endCallDueToNetworkIssue(); } }); } void stopConnectivityCheck() { connectivityTimer?.cancel(); connectivityTimer = null; } void renegotiateCall(Call call) { try { call.renegotiate( useUpdate: true, options: {'useUpdate': true}, done: (response) {}, ); } catch (e) {} } void endCallDueToNetworkIssue() async { Provider.of<SipRegisterProvider>(context, listen: false).upDateSipCallSpeaker(false); await endAllCalls(); if (Navigator.of(navigatorKey.currentContext!).canPop()) { Navigator.of(navigatorKey.currentContext!).pop(); } }
需求
提供网络中断恢复后优雅处理通话重连的方案。
系统信息
- Flutter SDK 版本:3.24.4
解决方案
1. 重建 PeerConnection 替代直接调用 renegotiate
直接调用 renegotiate 易因原 PeerConnection 状态异常触发终止逻辑,需先销毁旧连接再重建协商:
Future<void> reconnectCall(Call call) async { // 关闭旧的 PeerConnection await call.peerConnection?.close(); // 重新初始化 PeerConnection await call.initPeerConnection(); // 用 INVITE 发起协商(避免 UPDATE 导致的通话终止) call.invite( call.remoteUri.toString(), options: { 'sessionDescriptionHandlerOptions': { 'constraints': { 'audio': true, 'video': call.hasVideo ? true : false, } } }, done: (response) { if (response.statusCode == 200) { // 通话恢复成功 } }, onProgress: (session) {}, ); }
2. 优化网络连通性检测
不要仅依赖系统网络状态,需结合 SIP 服务器可达性验证:
Future<bool> checkSipConnectivity(SipUAHelper sipUA) async { try { // 发送 OPTIONS 请求验证 SIP 服务器连通性 var response = await sipUA.sendOptions(sipUA.configuration.uri.toString()); return response.statusCode >= 200 && response.statusCode < 300; } catch (e) { return false; } }
修改检测逻辑:
bool isInternetAvailable = await ConnectivityHelper.hasInternetConnection(); bool isSipReachable = await checkSipConnectivity(sipUA); if (isInternetAvailable && isSipReachable) { stopConnectivityCheck(); reconnectCall(call); }
3. 提前通知对方重连状态
发送 SIP INFO 消息告知对方即将重连,避免对方因异常信令终止通话:
void sendReconnectNotification(Call call) { call.sendInfo( content: 'Reconnecting due to network recovery', contentType: 'text/plain', done: (response) {}, ); }
在重连前调用:
sendReconnectNotification(call); await reconnectCall(call);
4. 精准监听连接状态
直接监听 PeerConnection 的连接状态变化,替代仅依赖 callStateChanged:
void monitorConnectionState(Call call) { call.peerConnection?.onConnectionStateChange = (state) { if (state == RTCPeerConnectionState.RTCPeerConnectionStateDisconnected) { startConnectivityCheck(call); } }; }
内容的提问来源于stack exchange,提问作者Umar Aslam
相关产品推荐
相关产品推荐

