Skip to content

March 3, 2012

2

Audio Player made with PhoneGap and jQuery Mobile

by nady

From this tutorial you will find out how to play and record files from your device.

Final result

Download Sources

In the sources you will find an audio sample that I’ve put in assets/audio folder. In www/img you will find the icons that I’ve used for the player buttons.

Open index.html and add the following code for the page:

[html]
<div data-role="page">
<div data-role="header" data-position="fixed">
<h1>DigitalNoiz</h1>
</div>
<div data-role="content">
<h2>Media Player</h2>
<div id="audioPosition">
<input type="range" name="slider" id="slider" value="0" min="0" max="100" data-highlight="true" disabled />
</div>
<div data-role="controlgroup" data-type="horizontal">
<input type="button" id="play" data-role="button" data-icon="audio-play" data-iconpos="notext" value="Play" />
<input type="button" id="pause" data-role="button" data-icon="audio-pause" data-iconpos="notext" value="Pause" disabled />
<input type="button" id="stop" data-role="button" data-icon="audio-stop" data-iconpos="notext" value="Stop" />
<input type="button" id="rewind" data-role="button" data-icon="audio-rewind" data-iconpos="notext" value="Rewind" />
<input type="button" id="record" data-role="button" data-icon="audio-record" data-iconpos="notext" value="Record">
</div>
<div id="recording"></div>
</div>
</div>
[/html]

The slider from audioPosition div will show the current position of the audio that is played. The default starting point is 0 and the range goes from 0 to 100. I’ve disabled the slider for the user to not be able to change it’s position. Because I don’t want to show the range input that comes with the slider widget from jQuery Mobile I’ve added the following code in css/style.css:

[css]
#slider{
display:none;
}

div.ui-slider{
margin:0;
width:100%;
}
[/css]

In order to group buttons horizontal use data-role="controlgroup" data-type="horizontal" attributes.
The buttons have custom icons and they don’t display text by using data-iconpos="notext" attribute.
To create custom icons that you can use in data-icon attribute use in your css rules the class ui-icon-unique-name, where unique-name could be any unique name you think of, like audio-play. To maintain consistency with the rest of the icons, use icons with the resolution 18×18 pixels. We have five buttons so we need five icons.

[css]
.ui-icon-audio-play {
background-image: url("../img/18/play.png");
}

.ui-icon-audio-pause {
background-image: url("../img/18/pause.png");
}

.ui-icon-audio-stop {
background-image: url("../img/18/stop.png");
}

.ui-icon-audio-rewind {
background-image: url("../img/18/rewind.png");
}

.ui-icon-audio-record {
background-image: url("../img/18/record.png");
}
[/css]

Because many devices have very high resolution displays, add an media query like -webkit-min-device-pixel-ratio: 2 to target high resolution and use icons with the resolution 36×36 pixels and set the background size to 18x18px to fit the icon.

[css]
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
.ui-icon-audio-play {
background-image: url("../img/36/play.png");
background-size: 18px 18px;
}

.ui-icon-audio-pause {
background-image: url("../img/36/pause.png");
background-size: 18px 18px;
}

.ui-icon-audio-stop {
background-image: url("../img/36/stop.png");
background-size: 18px 18px;
}

.ui-icon-audio-rewind {
background-image: url("../img/36/rewind.png");
background-size: 18px 18px;
}

.ui-icon-audio-record {
background-image: url("../img/36/record.png");
background-size: 18px 18px;
}
}
[/css]

For the recording div add the following style:

[css]
#recording{
font-weight: bold;
color:#f00;
}
[/css]

Now to make this basic interface for the audio player to work open js/script.js and add this variables that we need to play, pause, stop an watch position of an audio file.

[js]
/* Audio player */
var audio = null;
var audioTimer = null;
var pausePos = 0;
[/js]

Create a function playAudio with a file parameter.

[js]
/* play audio file */
function playAudio(file){
audio = new Media(file, function(){ // success callback
console.log("playAudio():Audio Success");
}, function(error){ // error callback
alert(‘code: ‘ + error.code + ‘\n’ +
‘message: ‘ + error.message + ‘\n’);
});

// get audio duration
var duration = audio.getDuration();

// set slider data
if( duration > 0 ){
$(‘#slider’).attr( ‘max’, Math.round(duration) );
$(‘#slider’).slider(‘refresh’);
}

// play audio
audio.play();

audio.seekTo(pausePos*1000);

// update audio position every second
if (audioTimer == null) {
audioTimer = setInterval(function() {
// get audio position
audio.getCurrentPosition(
function(position) { // get position success
if (position > -1) {
setAudioPosition(position);
}
}, function(e) { // get position error
console.log("Error getting pos=" + e);
//setAudioPosition(duration);
}
);
}, 1000);
}
}
[/js]

The Media object permits us to deal with audio files on a device.

[js]
audio = new Media(file, onSuccess, onError);
[/js]

To obtain the duration of the audio file use getDuration() method. After you get the duration, change the max attribute for the slider with the integer resulted from rounding the duration. All the changes made to the slider from js must be refreshed to be applied.

Use the play() method to start playing an audio file.

If the audio file was paused you need to ensure that it starts from it’s paused position, use seekTo(ms) method to move the position within the file. Multiply with 1000 the pausePos that is in seconds in order to obtain miliseconds.

Every one second get the current position using getCurrentPosition(onSuccess, onError) method and set the slider accordingly.

[js]
/* set audio position */
function setAudioPosition(position) {
pausePos = position;
position = Math.round(position);
$(‘#slider’).val(position);
$(‘#slider’).slider(‘refresh’);
}
[/js]

To pause and stop the audio file use the following functions:

[js]
/* pause audio */
function pauseAudio() {
if (audio) {
audio.pause();
}
}

/* stop audio */
function stopAudio() {
if (audio) {
audio.stop();
audio.release();
}
clearInterval(audioTimer);
audioTimer = null;
pausePos = 0;
}
[/js]

The release() method releases the audio resources. This should be called when you no longer need the Media resource.

To record an audio file use the startRecord() method.

[js]
/* record audio file */
function recordAudio(file){
audioRec = new Media(file, function(){ // success callback
console.log("recordAudio():Audio Success");
}, function(error){ // error callback
alert(‘recording error : ‘ + error.message);
});

// start recording
audioRec.startRecord();

// stop recording after 10 seconds
setTimeout(function(){
audioRec.stopRecord();
audioRec.release();
}, 10000);
}
[/js]

This function starts recording and it stops after 10 seconds.

In the onDeviceReady() function bind the click event for every button and add the corresponding functionality functions , enable and disable the buttons accordingly.

[js]
// Phonegap is loaded and can be used
function onDeviceReady(){
var play_btn = $(‘#play’);
var pause_btn = $(‘#pause’);
var stop_btn = $(‘#stop’);
var rewind_btn = $(‘#rewind’);
var record_btn = $(‘#record’);

play_btn.click(function(){
playAudio("/android_asset/audio/sample.mp3");

$(this).button(‘disable’);
pause_btn.button(‘enable’);
});

pause_btn.click(function(){
pauseAudio();

$(this).button(‘disable’);
play_btn.button(‘enable’);
});

stop_btn.click(function(){
stopAudio();
// reset slider
$(‘#slider’).val(0);
$(‘#slider’).slider(‘refresh’);

pause_btn.button(‘disable’);
play_btn.button(‘enable’);
});

rewind_btn.click(function(){
stopAudio();
playAudio("/android_asset/audio/sample.mp3");

play_btn.button(‘enable’);
pause_btn.button(‘disable’);
});

record_btn.click(function(){
stopAudio();
$(this).button(‘disable’);
play_btn.button(‘enable’);
pause_btn.button(‘disable’);

var recsec = 10;
recordAudio(‘record.mp3′);
var rectxt = setInterval(function(){
var recording = $(‘#recording’);
if(recsec == 0) {
clearInterval(rectxt);
recording.text(‘Play recording’);
record_btn.button(‘enable’);
playAudio(‘record.mp3′);
} else {
recording.text(‘Stop recording in ‘ + recsec + ‘ seconds’ );
–recsec;
}
},1000);
});
}
[/js]

I’ve tested this code on an Android device and our audio sample is set on the android_asset folder.
When the record button is clicked it invokes recordAudio('record.mp3') that will create a record.mp3 file on the sdcard when the recording is over. It also displays how many seconds remain to record and when the recording is over the new audio file is played.

Enjoy your music in your own audio player.

Read more from Android, Mobile
2 Comments Post a comment
  1. Apr 1 2012

    Hi, uploaded app – but no music played… (Samsung Galaxy S with Android 2.3).
    m.linkmatrix.eu/download/player
    Any idea what I did wrong?

    Help would be appreciated. Thanks in advance.

    Reply
    • nady
      Apr 4 2012

      Hi, check that the version of phonegap from www/js matches the one you’re using in your app, I’m using phonegap 1.4.1. Otherwise check in your Android LogCat to see if there are any errors.

      Reply

Leave a Reply

required
required

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments