You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Chrome及原生WebView中WebRTC onicecandidate事件未触发问题排查

Android Chrome & WebView 94+ 中 RTCPeerConnection.onicecandidate 不触发的问题排查与解决

根据你描述的情况,代码在桌面浏览器、Android Firefox以及旧版本Chrome(84/87)中正常运行,但在Chrome 94.0.4606.85及对应的原生WebView里完全无法触发onicecandidate事件,降级Chrome到87后恢复正常,这大概率是Chrome 94+版本中WebRTC模块的行为变更或特定Bug导致的。结合你的代码和测试结果,我整理了几个可能的解决方向:

一、排查iceCandidatePoolSize配置的影响

你的代码中设置了iceCandidatePoolSize: 10,这个参数用于预收集ICE候选,但在Chrome 94+版本中,该配置的逻辑可能发生了变化,导致预收集逻辑失效或阻塞了后续的ICE收集流程。

尝试调整方案
移除iceCandidatePoolSize配置,或者将其设置为默认值0,让ICE候选在需要时才主动开始收集:

const servers = {
  iceServers: [
    {
      urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'],
    },
  ],
  // 移除或注释掉这一行,或设置为0
  // iceCandidatePoolSize: 10,
};

二、调整DataChannel的创建时机

你当前在createOffer之前就创建了DataChannel,虽然这符合WebRTC标准,但新版本Chrome可能对这个流程的处理逻辑有变更。尝试将DataChannel的创建延迟到setLocalDescription完成之后:

修改后的connectPeers函数片段

export async function connectPeers() {
  // ... 其他代码保持不变 ...
  var offerDescription = await localConnection.createOffer();
  await localConnection.setLocalDescription(offerDescription);

  // 延迟创建DataChannel到setLocalDescription之后
  dataConstraint = null;
  sendChannel = localConnection.createDataChannel("sendChannel", dataConstraint);
  sendChannel.onopen = handleSendChannelStatusChange;
  sendChannel.onclose = handleSendChannelStatusChange;
  
  const offer = {
    sdp: offerDescription.sdp,
    type: offerDescription.type,
  };
  await calldoc.set({offer});
  // ... 后续代码保持不变 ...
}

同时注意:作为WebRTC连接的接收方,不需要主动创建DataChannel(应该通过ondatachannel事件接收对方创建的通道),你当前在listenForConnection函数中主动创建DataChannel的代码可能导致冲突,建议移除:

async function listenForConnection() {
  calldoc = firebase.firestore().collection('calls').doc(answerInput.value);
  answerCandidates = calldoc.collection('answerCandidates');

  localConnection.onicecandidate = event => {
    event.candidate && answerCandidates.add(event.candidate.toJSON());
  };

  // 移除接收方主动创建DataChannel的代码
  // sendChannel = localConnection.createDataChannel("receiveChannel");
  // sendChannel.onopen = handleSendChannelStatusChange;
  // sendChannel.onclose = handleSendChannelStatusChange;
  
  localConnection.ondatachannel = receiveChannelCallback;
  // ... 后续代码保持不变 ...
}

三、显式触发ICE收集

如果上述调整无效,可以尝试在setLocalDescription之后显式调用restartIce()来强制触发ICE候选收集:

await localConnection.setLocalDescription(offerDescription);
// 显式触发ICE收集流程
localConnection.restartIce();

四、WebView特定配置检查

对于原生WebView,除了版本问题,还需要确保WebView的配置启用了WebRTC相关功能:

  • 确保启用JavaScript:webSettings.setJavaScriptEnabled(true)
  • 允许媒体访问(即使是DataChannel,部分版本可能依赖此配置):webSettings.setMediaPlaybackRequiresUserGesture(false)
  • 检查是否开启了WebView的隐私沙箱或其他限制功能,尝试临时关闭相关限制测试

五、调试建议

可以使用Chrome开发者工具的WebRTC内部页面(在Chrome地址栏输入chrome://webrtc-internals/),查看ICE收集的状态日志,是否有错误或未触发收集的具体原因,这能帮助快速定位问题。

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

火山引擎 最新活动