The Cordova/Ionic combo has been working well to add new features that work cross-platform and with using web standards and popular frameworks (AngularJS). 2015 was still a bumpy ride in the Hybrid app space with Ionic maturing to a 1.0 release, and major releases for iOS, Cordova and Android which each caused a few issues.

Real-time video seemed like one of those features which was a little cutting edge in the mobile browser to get working in a Cordova app. After adding image and audio messages to the chat feature in my Ionic app the next big feature to add, if possible, was real-time video. There are some plugins which require native code, but I didn’t want to go down that path.

A a pure JavaScript solution that runs in the browser was the goal initially. This restricts to the latest versions of Android and iOS which support WebRTC, but there is the option of adding Cordova plugins to support older versions later (Or the lazy option of waiting until most phone browsers do support it).

WebRTC also requires a server component for discovery. Three of the options I found are:

For this project I didn’t want the additional complexity of the self-hosted signalling and TURN server. I didn’t want to pay the minimum $50/month for OpenTok just to have a tinker and a demo running, which left Twilio. I was more than happy to go with them as I’m planning on using their other API’s down the track, and given their existing infrastructure and position in the marketplace they should be able to provide a robust solution.

I’ve been using TS (TypeScript) in my Ionic project, so the first step was to create a Angular controller in TypeScript to encapsulate all the video functionality. I started by butchering the quick-start code provided by Twilio into an Angular controller using TS/ES6 syntax.

The first step in the code is to request and access token from Twilio. As I’m using Parse for the backend, this meant creating a Cloud Code function to call which would return the token with the Parse user Id set as the token identity.

Parse.Cloud.define(‘GetTwilioToken’, function (request, response) {
  // Create an access token which we will sign and return to the client,
  // containing the grant we just created
  var token = new AccessToken(Config.TWILIO_ACCOUNT_SID, Config.TWILIO_API_KEY, Config.TWILIO_API_SECRET)
  // Assign the identity to the token
  token.identity = request.user.id
  // Grant the access token Twilio Video capabilities
  var grant = new ConversationsGrant()
  grant.configurationProfileSid = Config.TWILIO_CONFIGURATION_SID
  token.addGrant(grant)
  // Serialize the token to a JWT string and include it in a JSON response
  response.success({
    identity: identity,
    token: token.toJwt()
  })
})
There was bit of a trick to get this working as it needs the Twilio AccessToken module. I pulled in the twilio node module it lives in, but the Parse Cloud Code isn’t a normal node environment. So I created a small Webpack setup to bundle up just the AcccessToken and its required dependencies into a single file which can be used from the Parse Cloud Code.

Next was reworking the quick start code to have an Ionic model which displays when something video related was happening, i.e. an incoming invite, outgoing invite or ongoing call.

After getting it working nicely in Chrome on the desktop the moment of truth was deploying it to my Android phone. Drum roll…

And it didn’t work. Dammit, was this last couple of days work in vain? Looking at the adb logs in LogRabbit showed up a few errors but none with an obvious actionable outcome. After removing filter of only showing logs from my app a much more useful error of not having the android.permission.CAMERA permission appeared.

After creating possibly the most simple Cordova plugin to exist, https://github.com/campers/android-camera-permission I had my Ionic app running on an Android phone and Chrome desktop doing real-time video with each other!