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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:22:48