Adding WebRTC support to an iOS Cordova based application

WebRTC support to an iOS Cordova

Despite the recent rise of frameworks that utilize native UI, Cordova is still remaining one of the most popular and easy ways to build an Android or iOS application. With Crosswalk WebView, you get a great solution for your WebRTC based app, which works almost perfectly out of the box… on Android. When it comes to iOS, things become a little more sophisticated. Read on to find out how to get real time communications to work on iPhones and iPads.

Just before we get started, a couple of words on why things are so complicated with WebRTC on Cordova iOS app. Crosswalk Webview uses extended WKWebView instead of Chromium since Apple does not accept Chromium-based apps in App Store. WKWebView is pretty good but it does not support WebRTC at all. Fortunately, there is a solution called LibWebRTC, the Google’s WebRTC implementation written in Objective C, as well as cordova-plugin-iosrtc, a Cordova plugin that wraps it and exposes is API to JavaScript. In the rest of this article, I will explain how to tie these things together.

Note: you need a real iOS device in order to test your WebRTC application. It is impossible to use microphone, cameras and also push notifications in a simulator.

Cordova iOSRTC plugin installation

It would be dumb to rewrite the plugin’s documentation, which is pretty good, and I highly recommend reading it through before you start acting. The installation process requires setting up a custom Cordova hook and adding explanations why your application needs such dangerous permissions as microphone and camera to your project’s config.xml file.

If you build the application after installing the plugin, you will have the new API available in the “window.cordova.plugins.iosrtc” object. To set it to the right place (navigator.getUserMedia, etc), you need to call cordova.plugins.iosrtc.registerGlobals(). The window.cordova.plugins.iosrtc object becomes available only when the "deviceready" event is fired, and that’s the tricky part. If you use libraries that rely on checking WebRTC support on start up, like SIP.js, you should make sure that they are imported and initiated only after registerGlobals() has finished doing its job. With all that in mind, you are ready to start using WebRTC APIs as though your WebView has its native support.

Playing video streams

Due to implementation restrictions, cordova-plugin-iosrtc uses native UIView (actually, it’s RTCEAGLVideoView) to display streaming video. It watches for insertion of video tags in to DOM and places such views right on top. Videos require special care, details of which are described in this document. If you do not hide status bar in your application, all videos would be shifted to the top. To fix this, you need to hide the status bar dynamically once a video tag appears on the page, or do not show it at all. The latter can be configured in the project settings under Development Info section in Xcode. If the corresponding video tag changes size or position on the page, you would want to call cordova.plugins.iosrtc.refreshVideos() to keep UIViews in sync. There’s also another way - call cordova.plugins.iosrtc.observeVideo(videoElement) on the video element in case you create it in your script before inserting into DOM.

One little notice: all HTML video elements have a crossed play button in the middle. If the logic of your application relies on clicking on video elements, you need to keep one little trick in mind. The UIViews let pass click events through (videoView.userInteractionEnabled = false, I checked it), however if the click is made on the “play” button, the event will not be propagated upwards. To restrict this behavior, you need to add the following CSS rule:

video::-webkit-media-controls-start-playback-button {
    display: none !important;
    -webkit-appearance: none;
}

This will hide the hapless play button and let your click events propagate.

Switching between speaker and earpiece

At last, I can’t skip the things I’ve been struggling with a lot - toggling between loud speaker and earpiece. On Android, after many failures with determining devices and switching streams, I ended up using the AudioToggle plugin. It does affect the entire device’s state, so additionally, I had to write an Android service (in Java, the language I’m not very strong at) which monitors application’s stops and resets audio state to default. Luckily, in our case it is much simpler - just call cordova.plugins.iosrtc.selectAudioOutput("earpiece") or cordova.plugins.iosrtc.selectAudioOutput("speaker") to switch to the earpiece or loud speaker correspondingly.

Updated on February 10, 2018

Since version 4.0.0 the selectAudioOutput functionality has been removed from the plugin. To change the output device, use AudioToggle or similar Cordova plugins.


With all this knowledge, you are ready to start adapting your Cordova application to the iOS platform. I tried to mention all the difficulties I met while working with this, so hope it will help. As always, thanks for reading and have fun!