Twitter: raymondcamden


Address: Lafayette, LA, USA

Cordova Media API Example

06-23-2014 6,240 views Mobile, JavaScript, HTML5 15 Comments

A few months ago I launched a new GitHub repo (https://github.com/cfjedimaster/Cordova-Examples) as a way to try to collect my various Cordova examples together under one roof. I had planned to add to it regularly but - life - as you know - gets in the way. I've finally gotten around to adding another example, this one for the Media API.

Specifically, my example looks at how to play a MP3 file that is shipped with your application. You would think this would be trivial. Assuming I've got a folder under www called sounds and a MP3 file called something.mp3, you would think this would do it:

var media = new Media("sounds/something.mp3", null, mediaError);
media.play();

Unfortunately, this breaks in Android. Why? Because Android. (No, no, I kid, sorry.) Specifically Android requires slightly different "pathing" to get to the same source. Specifically it requires this in front of the path: /android_asset/www/

So what I did was write a simple utility function that makes use of the Device API. Consider:

document.addEventListener('deviceready', onDeviceReady, false);

function onDeviceReady() {
	document.querySelector("#playMp3").addEventListener("touchend", playMP3, false);
};

function playMP3() {
    var mp3URL = getMediaURL("sounds/button-1.mp3");
    var media = new Media(mp3URL, null, mediaError);
    media.play();
}

function getMediaURL(s) {
    if(device.platform.toLowerCase() === "android") return "/android_asset/www/" + s;
    return s;
}

function mediaError(e) {
    alert('Media Error');
    alert(JSON.stringify(e));
}

All I've done is sniff for the Android platform and modify the passed-in path value to add the Android prefix. I did not test this outside of iOS and Android so I can't say if it will work in Blackberry or Firefox, but, it gives you a basic idea of how to use a MP3 in your application.

You can find the source for this particular project here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/mp3. As a reminder, you can clone the entire repository, and when you make a new Cordova project, simply use the --copy-from attribute to copy in my source code.

15 Comments

  • Commented on 06-23-2014 at 4:47 PM
    It makes me sad that I wrote this blog post (http://simonmacdonald.blogspot.ca/2011/05/using-me...) back in 2011 and the state of the Media API still hasn't progressed.
  • Commented on 06-23-2014 at 7:59 PM
    Just curious - what would you like to see added?
  • Commented on 06-23-2014 at 9:39 PM
    I just wanted it normalized so that you don't have to do things like "if android" in your code.
  • Dawesi #
    Commented on 06-24-2014 at 2:54 AM
    I've heard the Intel crosswalk webview replacement is miles better than the standard one for audio, have you used crosswalk at all with pg/cordova?

    https://crosswalk-project.org
  • Commented on 06-24-2014 at 9:12 AM
    @Simon: Ah. Query - and yeah - I could test this and will in a bit - but it seems odd that if you do an XHR to /foo.txt, it works (afaik). So it's just the Media object resolving / to app root in Android versus www.

    @Dawesi: It looks Crosswalk would be used instead of Cordova, not with it. Am I reading right?
  • Dawesi #
    Commented on 06-24-2014 at 5:10 PM
    @Ray, Apparently you can embed cakewalk in cordova also giving you a bunch of HTML5 full feature apis out of the box (webgl, audio, etc) and the browser is faster, you your app loads and runs snappier...

    This would mean you could do things like slow down the track (for musician practice) without pitch bending and other music metadata beyond the basics so you can do waveforms and alike... and then use webgl for visualising those waveforms....

    so I'm just starting to look into this, so was wondering if you or any of the internal Adobe guys had looked at cakewalk in this context.
  • Dawesi #
    Commented on 06-24-2014 at 5:34 PM
    eg: https://github.com/crosswalk-project/crosswalk-cor...
  • Commented on 06-24-2014 at 9:33 PM
    Oh interesting. I can't speak to if any of the Adobe folks are looking at this. I'm not on the PhoneGap team and am just doing documentation stuff - nothing related to PhoneGap, or web standards, at all.
  • Nathan #
    Commented on 06-25-2014 at 6:32 AM
    Hi Raymond. Great article, thanks for spending the time to post it.

    I have a quick question regarding uri path used to store content if you don't mind. In your example you have used '/android_asset/www/', which would (I'm assuming) store the data on the devices internal memory. What would be the preferred path to use to store data on the devices external memory? I've seen file:/// and content:// and even /Android/data/<package-name> (for Android only) used, is there a best practice method that works across devices (possibly across iOS and Android?)

    Many regards!
  • Commented on 06-25-2014 at 8:37 AM
    "which would (I'm assuming) store the data on the devices internal memory. "
    to be clear, I'm not storing anything. I shipped a MP3 with my app itself. Which, I guess, is "storing" it, but the Media call itself is not storing anything.

    The use of /android_asset/www is only there because on Android, the path requires it.
  • Khan Cross #
    Commented on 06-27-2014 at 5:51 AM
    Hi. Can you post one with multiple variables?
  • Commented on 06-27-2014 at 8:53 AM
    Why? It should work relatively similar. If you don't see that, share code via a pastebin.
  • Commented on 08-03-2014 at 9:44 PM
    Does the Cordova dev team has no plan to improve Media API? I mean, getting rid of it entirely and implementing something that is closer to HTML5/ W3C standards.

    As Simon MacDonald pointed out, things havent changed since 2011.
  • Commented on 08-03-2014 at 9:52 PM
    The Cordova "dev team" is anyone and everyone. Cordova is open source so if this is something you care about it, you could try to improve it yourself, right?
  • Siddharth #
    Commented on 08-16-2014 at 9:26 PM
    I agree with Simon. Conditionally testing for platform is no good. Also how do I release the resource occupied by the media file.

    For example:

    function playAudio(audioTrack){
    var media = new Media(path_to_audioTrack);
    media.play();
    // Now the standard media.release() does not work as intended.
    // If media.release() is included after the media.play(), the user cant hear
    // the audio being played. I tried with releasing after time interval, but no success
    }

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty