Android端WebRTC重连后6-7秒断开并进入失败状态问题
WebRTC WiFi重连后短暂恢复随即断开的问题解决思路
首先,我先梳理下你的问题:初始WebRTC会话运行正常,但WiFi断开重连后,会话虽能短暂回到CONNECTED状态,不过6-7秒后就会掉到DISCONNECTED,最终转为FAILED。结合你的日志和代码,我整理了几个可能的原因和对应的解决方案:
问题回顾
状态日志
2020-09-19 19:34:27.112 5941-6059/com.thirdeyegen.mr_workspacee D/NEW_WEBRTC_STATE==>: CHECKING 2020-09-19 19:34:28.338 5941-6059/com.thirdeyegen.mr_workspacee D/NEW_WEBRTC_STATE==>: CONNECTED 2020-09-19 19:35:06.133 5941-6059/com.thirdeyegen.mr_workspacee D/NEW_WEBRTC_STATE==>: DISCONNECTED 2020-09-19 19:35:06.473 5941-6059/com.thirdeyegen.mr_workspacee D/NEW_WEBRTC_STATE==>: CONNECTED 2020-09-19 19:35:21.363 5941-6059/com.thirdeyegen.mr_workspacee D/NEW_WEBRTC_STATE==>: DISCONNECTED 2020-09-19 19:35:31.379 5941-6059/com.thirdeyegen.mr_workspacee D/NEW_WEBRTC_STATE==>: FAILED
事件说明:前两条是初始正常会话;后四条是WiFi重连后的状态,短暂恢复后很快断开失败。
核心代码片段(基于OpenVidu Android)
public PeerConnection createLocalPeerConnection() { final List<PeerConnection.IceServer> iceServers = new ArrayList<>(); PeerConnection.IceServer iceServer = PeerConnection.IceServer .builder("turn:" + turnUrl) .setUsername(turnUsername) .setPassword(turnPassword) .createIceServer(); iceServers.add(iceServer); PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers); rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED; rtcConfig.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE; rtcConfig.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE; rtcConfig.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY; rtcConfig.keyType = PeerConnection.KeyType.ECDSA; rtcConfig.enableDtlsSrtp = true; rtcConfig.enableRtpDataChannel = true; rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN; return peerConnectionFactory.createPeerConnection(rtcConfig, new CustomPeerConnectionObserver("local") { @Override public void onIceCandidate(IceCandidate iceCandidate) { super.onIceCandidate(iceCandidate); websocket.onIceCandidate(iceCandidate, localParticipant.getConnectionId()); } @Override public void onSignalingChange(PeerConnection.SignalingState signalingState) { super.onSignalingChange(signalingState); } @Override public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) { if (iceConnectionState.name().toLowerCase().equals("connected")) { isLocalConnected = true; } Log.d("NEW_WEBRTC_STATE==>", iceConnectionState.name()); if (iceConnectionState.equals(PeerConnection.IceConnectionState.FAILED)) { checkForInternetAndReconnect(); } else if (iceConnectionState.equals(PeerConnection.IceConnectionState.DISCONNECTED)) { activity.showConnectingAnimation(View.VISIBLE); } else { activity.showConnectingAnimation(View.GONE); } super.onIceConnectionChange(iceConnectionState); } }); }
可能的原因及解决办法
1. 旧ICE候选未被替换,新候选未及时同步
你已经设置了continualGatheringPolicy = GATHER_CONTINUALLY,理论上网络变化后会自动收集新的ICE候选,但问题可能出在:新收集的候选没有及时发送给对端,或者对端没有正确添加这些候选,导致连接短暂恢复后,旧的失效候选被使用,最终断开。
解决步骤:
- 监听设备的网络状态变化(比如用Android的
ConnectivityManager),当检测到WiFi重连完成后,主动调用peerConnection.restartIce()。这个方法会强制触发新一轮的ICE收集,生成新的候选,然后通过你的WebSocket发送给对端。 - 确保对端收到新的ICE候选后,调用
peerConnection.addIceCandidate()添加到自己的PeerConnection中,不要只在初始化阶段添加。
2. DTLS会话未重新建立
WiFi断开会导致DTLS会话中断,虽然ICE连接短暂恢复,但DTLS握手可能没有重新完成,WebRTC会因为安全会话失效而断开连接。
解决步骤:
- 在
onIceConnectionChange回调中,当状态从DISCONNECTED回到CONNECTED后,检查DTLS状态:可以调用peerConnection.getDtlsState(),如果状态不是CONNECTED,考虑触发restartIce()或者重新协商SDP。 - 极端情况下,网络恢复后直接销毁旧的PeerConnection,重新调用
createLocalPeerConnection()创建新连接,从头开始协商会话,这样能确保所有状态都是全新的。
3. 重连逻辑的时机不对
现在你的代码只在FAILED状态才触发checkForInternetAndReconnect(),但在DISCONNECTED后短暂恢复又断开的场景下,可能没有及时介入。比如当DISCONNECTED状态超过一定时间(比如5秒)还没恢复,就应该主动触发重连,而不是等它变成FAILED。
解决步骤:
- 在
DISCONNECTED状态时,启动一个计时器,比如设置5秒超时,如果超时后还没回到CONNECTED,就触发重连逻辑。 - 优化
checkForInternetAndReconnect()方法:确保销毁旧的PeerConnection、清理旧的ICE候选和SDP信息,然后重新创建连接并发起协商,不要复用旧的连接对象。
4. TURN服务器的连通性问题
虽然你配置了TURN服务器,但WiFi重连后设备可能无法正常访问TURN服务器(比如防火墙限制、TURN服务器本身的问题),导致无法获取有效的中继候选,最终连接失败。
解决步骤:
- 测试TURN服务器的连通性:可以在代码中添加日志,确认新收集的ICE候选中有没有来自TURN服务器的中继候选。
- 同时配置STUN服务器作为补充,比如添加Google的公共STUN服务器:
stun:stun.l.google.com:19302,这样在TURN不可用时,还能尝试STUN穿透。
内容的提问来源于stack exchange,提问作者Jaswant Singh
相关产品推荐
相关产品推荐

