WebRTC on iOS

One of the major parts of the app I work on is live video conferencing. We do this using WebRTC, which works great. EXCEPT: when one party is using Chrome on iOS. Here is why.

On iOS WebRTC is supported in iOS 13+, but only in Safari.

Additionally, it’s not supported in WKWebView. And, of course, not in the deprecated UIWebView so make sure you’re using at least Xamarin Forms 4.5.

But, of course, our app needs to show a WebRTC window! To get around this we do all our backend stuff behind the scenes, our API returns a nice little URL with a nonce, and then we open that in a SFSafariViewController.

Xamarin Essentials makes this easy using BrowserLaunchMode.

Normally when you call Browser.OpenAsync it just opens the Safari app. But if you add the parameter BrowserLaunchMode.SystemPreferred it’ll open your URL in a SFSafariViewController.

Xamarin.Essentials.Browser.OpenAsync("https://yoururl.com", BrowserLaunchMode.SystemPreferred);

If we were to load this site like that, it’d look like this:

There are a couple benefits here.

First, our app stays open. This can be a lot less confusing for your users. They simply have to click that “Done” button to get back to what they were doing before. Previously, they were in an entirely different app (Safari) and had to find their way back to your app. This is especially important for us since our app holds a websocket connection open in the background. Switching to Safari meant that connection closed when our app went to the background. Then when it switched back it had to reopen and reauthenticate which was just annoying.

Second, although you can’t see inside the SFSafariViewController like you can with a WKWebView you do get a better idea of when the user closes it by clicking the “Done” button. We do this by just watching ViewAppearing() in the view that launched it. This let’s us keep control over the flow of the app.

One last problem we had was a video conferencing scenario where our user was on our app (so using WebRTC on iOS with SFSafariViewController) and the other party was outside of our app using Chrome on iOS. iOS doesn’t actually allow full third party browsers. Under the hood, Chrome is just showing a WKWebView which, remember, doesn’t support WebRTC. Unfortunately, there is currently no workaround for this. In this situation we have no choice but show a message in Chrome saying “please switch to Safari”.

The problem is that WKWebView is not exposing getUserMedia. There is a bug opened for Chrome as Issue 752458. The bug is actually on Apple’s end and if you look at the comments for WebKit you can see that it was actually fixed back in an earlier beta, but then got dropped when it was moved to production.

Hopefully soon Apple will fix this. And then after that Chrome will have to also update their app. But it looks like it’s a long ways off.

A good resource for testing WebRTC connections is http://test.webrtc.org. If your device doesn’t pass these tests, it’s not going to run your code either.