Making navigator.getUserMedia work on Android Cordova… by accident.

hand holding a microphone

I built an app, using Apache Cordova, that consumes Amazon APIs to make it voice-powered. I had it working on Android and Windows using the navigator.getUserMedia API. I even demonstrated it at a conference. Then I was preparing to demo it at another event a few months later, plugged in my new phone to sideload the app to it… and I couldn’t get it to record audio.

What was I doing wrong? I immediately thought it was because I switched from stock Android on a Nexus 6P to whatever voodoo was inside a Samsung Galaxy S8. I started making sure I had all my Android permissions right and in the right places. I checked config.xml, my Androidmanifest.xml. I scoured Stack Overflow. I couldn’t get mic access. Oddly enough, my app wasn’t even asking for me to approve it.

Many hours of trials and tribulations later, I tried to retrace the steps I’d followed in initially working out how to make the app. Before I settled on navigator.getUserMedia I’d tried the core media plugin to capture audio.

What I didn’t like about it was that it recorded files to disk, not just a blob to memory. Also, I needed the files in memory in a specific format. Since I’d already done web-based projects that could generate that output with recorder.js and navigator.getUserMedia, I tried that. And it worked fine.

What I didn’t realize at that point was that just using navigator.getUserMedia by itself wouldn’t prompt the app to ask for the necessary audio permissions on first run. Without the app asking and me confirming, the navigator.getUserMedia API couldn’t get access to the microphone.

So WHY did it work the first time? Using the Cordova core media plugin did it. When I had been testing EARLY on in my development process, the first recording using that plugin caused the app to request the permissions and access it needed. Once it had done that, the app had those permissions for the rest of my development and demonstration cycle.

I worked up a kludgy hack to use the media plugin to record a 100ms file on Android devices, just to get those permissions requested, every time I loaded the app to a new device (or changed its name and package name in config.xml). That worked but I needed something more elegant.

That’s where the audioinput 3rd party plugin came in. By using it, and cannibalizing its WAV file demo, I was able to get the necessary audio and have permissions requested. By abstracting it and a navigator.getUserMedia fallback for Windows desktop to push the same kind of data to the I/O routines for the Amazon APIs, my app works again.

And by changing app and package names in the config, I’ve been able to test it on the same phone to ensure permissions get requested (though I’ve also used a second phone just to be safe).

Leave a Reply

Your email address will not be published. Required fields are marked *