HTML5 audio not playing in PhoneGap App (Possible to use Media?)

21,238

Solution 1

I've been banging my head all week, and I finally got Media to work! There are many gotchas:

As per Geevan's answer, you do need <script type="text/javascript" src="phonegap.js"></script> on your page.

Step 1:

You need to use org.apache.cordova.media version 0.2.9 or higher (I'm using 0.2.11). As of this writing, PhoneGap Build only supports up to version 0.2.8. I believe the patch notes for 0.2.9 may have resolved my issues.

Step 2:

The PhoneGap documentation for version 3.0.0 has a typo, be sure you are using at least the 3.3.0 documentation, and make sure that the following is typo-free in your config.xml:

<feature name="Media">
    <param name="android-package" value="org.apache.cordova.media.AudioHandler" />
</feature>

(the word "media" in "org.apache.cordova.media.AudioHandler" was missing in the 3.0.0 documentation)

Step 3:

If you're forced to use the CLI version of PhoneGap (NOT PhoneGap Build) due to the issue described in step 1, be sure you add the required plugins. This is described in the documentation:

> cordova plugin add org.apache.cordova.media

And add <gap:plugin name="org.apache.cordova.media" /> to your config.xml

Step 4:

You need to add "/android_asset/www/" to all of your audio file paths. Eg:

new Media('/android_asset/www/' + src);

Step 5:

Do all audio loading after the device is ready. Eg:

document.addEventListener("deviceready", Game.load);

Once I made these changes, my audio started to work! Good luck!

Solution 2

I think you should say "Works great in desktop browser", it is more a matter of support of media in the android default browser than an issue with phonegap.

According to this page, the android browser supports mp3 on some device, and ogg on others. Maybe your issue is that you're trying to use mp3 on a device only supporting ogg for media in the browser?

Using phonegap media plugin should solve the problem.

The full example in the documentation page is quite clear. You just have to copy in your page the playAudio, onSuccess and onError functions and then call playAudio whenever you want to play a file.

The html of your page could look like this :

<button class="button" id="btnYes">Yes</button>
<button class="button" id="btnNo">No</button> 

and the javasctipt (using jquery):

document.addEventListener("deviceready", function () {
    $("#btnYes").on("click", function () {
        playAudio(audio/basic/yes.mp3);
    });
    $("#btnNo").on("click", function () {
        playAudio(audio/basic/no.mp3);
    });
}, false);
var my_media = null;
var mediaTimer = null;
function playAudio(src) {
    // Create Media object from src
    my_media = new Media(src, onSuccess, onError);
    // Play audio
    my_media.play();
}
// onSuccess Callback
function onSuccess() {
    console.log("playAudio():Audio Success");
}
// onError Callback
function onError(error) {
    alert('code: ' + error.code + '\n' +
        'message: ' + error.message + '\n');
}

The calls to playAudio could also be in the onclick directly in the html, but I prefered to use jquery to start listening for clicks only once phonegap is ready.

Don't forget to include cordova.js, and if you're using phonegap 3.x don't forget to install the org.apache.cordova.media plugin

Edit:

path audio/basic/yes.mp3 assumes that the file is in the audio folder at the root of the sd card.

use /android_asset/www/audio/basic/yes.mp3 if the audio folder is located in the phonegap www folder.

Solution 3

It could be a content security problem, try with this header in your index.html. In my test project, including or excluding it makes or breaks audio playback and reading local files with $.get() or something like that

<meta http-equiv="Content-Security-Policy" content="default-src 'self' http://appvipswi.easwi.it; script-src 'self' 'unsafe-inline'; media-src 'self'">

Solution 4

Uff that was really hard and confusing ... But I finally did it!

Here is exactly what i did:

index.html

<audio id="successSound" src="sounds/sayHello.mp3" type="audio/mpeg" ></audio>
<button onclick="playAudio('successSound')">Play successSound local</button>

AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

index.js

function playAudio(id) {
var audioElement = document.getElementById(id);
var url = audioElement.getAttribute('src');
var my_media = new Media('/android_asset/www/' + url,
        // success callback
         function () { console.log("playAudio():Audio Success"); },
        // error callback
         function (err) { console.log("playAudio():Audio Error: " + err); }
);
       // Play audio
my_media.play();

}

plataform/android/res/xml.config

<feature name="Media">
        <param name="android-package" value="org.apache.cordova.media.AudioHandler" />
    </feature>

And it finally works!!! :D uhuuuuu

Share:
21,238
BR89
Author by

BR89

Rookie Android Developer with 2 apps on the Play Store.

Updated on September 21, 2020

Comments

  • BR89
    BR89 over 3 years

    Working on a basic sound board for a trip abroad. Set up everything to work fine in Browsers but wanted to use PhoneGap Build/GitHub to make it downloadable as cell service won't be available.

    Everything working great in desktop browser however once its installed on Android, the mp3 files don't play. I've read some others posts on here about the inconsistencies of mp3s on PhoneGap. Some suggestions offered using "media" in place of . I'm not sure how to swap that out in place of the code I have now. Seems to use javascript instead of just html. http://docs.phonegap.com/en/2.0.0/cordova_media_media.md.html#Media Sample of what I'm using:

    <audio id="yes" src="audio/basic/yes.mp3"></audio>
    <audio id="no" src="audio/basic/no.mp3"></audio>
    
    <button class="button" onclick="document.getElementById('yes').play()">Yes</button>
    <button class="button" onclick="document.getElementById('no').play()">No</button>
    

    Works great in browser, but not on Android. Can anyone offer a starting point to correct the audio?

    Thanks -BR

    EDIT 2-9-14

    No luck so far. The media plugin is showing as correctly installed and cordova.js is included. Here's what I've tried.

    <!DOCTYPE HTML>
    <html>
      <head>
        <title>Media Example</title>
        <link rel="stylesheet" type="text/css" href="style.css">
        <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
        <script type="text/javascript" charset="utf-8">
    
        function playAudio(url) {
    // Play the audio file at url
    var my_media = new Media(url,
        // success callback
        function() {
            console.log("playAudio():Audio Success");
        },
        // error callback
        function(err) {
            console.log("playAudio():Audio Error: "+err);
    });
    
    // Play audio
    my_media.play();
    }
        </script>
      </head>
      <body>
    
      <a href="#" class="button" onclick="playAudio('/android_asset/www/audio/basic/yes.mp3');">Yes</a>
    
      </body>
    </html>
    

    Also tried to work with the code you suggested

    <!DOCTYPE html>
    <html>
    <head>
    
    <title>Transactions</title>
    
    <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
    <script type="text/javascript">
    var my_media = null;
    var mediaTimer = null;
    function playAudio(src) {
     // Create Media object from src
     my_media = new Media(src, onSuccess, onError);
     // Play audio
     my_media.play();
     // Update my_media position every second
     if (mediaTimer == null) {
        mediaTimer = setInterval(function () {
                // get my_media position
                my_media.getCurrentPosition(
                    // success callback
                    function (position) {
                    if (position > -1) {
                        setAudioPosition((position) + " sec");
                    }
                },
                // error callback
                function (e) {
                    console.log("Error getting pos=" + e);
                    setAudioPosition("Error: " + e);
                });
            }, 1000);
        }
    }
    // onSuccess Callback
    function onSuccess() {
    console.log("playAudio():Audio Success");
    }
    // onError Callback
    function onError(error) {
     alert('code: ' + error.code + '\n' +
        'message: ' + error.message + '\n');
    }
    
    </script>
    
    
    <link rel="stylesheet" type="text/css" href="style.css">
    
    </head>
    
    <body>
    
    
    
    document.addEventListener("deviceready", function () {
    $("#Yes").on("click", function () {
        playAudio(audio/basic/yes.mp3);
    });
    $("#No").on("click", function () {
        playAudio(audio/basic/no.mp3);
    });
    
    
    <button class="button" id="Yes">Yes</button>
    <button class="button" id="No">No</button>
    
    
    
    </body>
    
    </html>
    

    Edit 2/10/14

    Unfortunately still no such luck. Most recent update below

    <!DOCTYPE html>
    <html> 
    <head>
    
    <title>Transactions</title>
    
    <!-- JavaScript -->
    <script type="text/javascript" charset="utf-8" src="cordova.js"></script> 
    <script type="text/javascript">
    
    
    document.addEventListener("deviceready", function () {
    $("#yes").on("click", function () {
        playAudio(/android_asset/www/audio/basic/yes.mp3);
    });
    $("#no").on("click", function () {
        playAudio(/android_asset/www/audio/basic/no.mp3);
    });
    }, false);
    
        var my_media = null;
    var mediaTimer = null;
    function playAudio(src) {
    // Create Media object from src
    my_media = new Media(src, onSuccess, onError);
    // Play audio
    my_media.play();
    }
    // onSuccess Callback
    function onSuccess() {
    console.log("playAudio():Audio Success");
     }
    // onError Callback
    function onError(error) {
    alert('code: ' + error.code + '\n' +
        'message: ' + error.message + '\n');
     }
    </script>
    
    <!-- CSS -->
    <link rel="stylesheet" type="text/css" href="style.css">
    
    </head>
    
    <body>
    
    
    
    
    <button class="button" id="yes">Yes</button>
    <button class="button" id="no">No</button>
    
    
    
    </body>
    
    </html>