WebRTC Native vs browser: ICE Connectivity checks fail

I am trying to solve a problem that has been holding back a project for the past month. I am looking for any advice on moving forward, and also looking for confirmation that anyone else has succeeded with what I’m attempting.

I have an Android app using native Web RTC. For a variety of reasons, this solution needs native Web RTC instead of a browser.

Janus is installed on a VM in a data center with UDP port ranges exposed to the Internet, and the server is available to the Internet via host name.

Using an Android tablet over Wifi or an Android emulator, I can join a video room with signaling server and Janus running in Docker containers in a local environment from the native app. Audio and video flowing, recording works, I can covert the audio and video after the call, etc.

Using the same Android tablet and same app with settings pointing to the signaling server and Janus in the data center, the ICE connectivity checks almost immediately move to a fail status.

Using that exact same Android tablet and the same home wifi, I can join one of the test video rooms in the same Janus server in that data center via Chrome. I did this with the video room test html/js, pointing everything at Janus in the data center. I can also create an Android app with an embedded web view that points to the same video test, and this works. For these tests, STUN is all that was needed.

From that same exact tablet with a native Android app and native WebRTC, the ICE connectivity immediately fails.

That same exact tablet and native android app can switch settings to use my local Janus server without a problem.

From this, my assumptions are as such:

  • Janus is deployed and configured properly (or the videoroom test via browser would fail).
  • The Android app and native Web RTC implementation is correct, or it would not work with the local Janus install
  • TURN is not needed as the browser test successfully uses STUN.
  • TURN should work, as my TURN server is included for my app as well as a STUN server, and I can see that the native app both obtains a TURN allocation and maintains it with keep alive messages

I have watched the Janus admin for successful and failed attempts, and have saved the ICE candidate lists and SDPs of both successful and failed attempts. The ICE candidate lists are nearly identical (host and server reflex candidates are the same other than UDP port and user fragments).

Thank you in advance for any help. I have Janus server logs from good connections (via a browser) and failed connections (via native WebRTC). I have UDP packet captures from the Janus server, and I have logs from native WebRTC, any and all of which I can scrub of sensitive data and provide as needed.