Skip to content

Cordova - Media

Cordova - Audio Playback and Recording (Media)

Section titled “Cordova - Audio Playback and Recording (Media)”

The cordova-plugin-media plugin provides the ability to record and play back audio files on a device. This tutorial focuses on playing audio and controlling its playback.

Install the plugin using the Cordova CLI:

cordova plugin add cordova-plugin-media

This plugin may also require cordova-plugin-file if you are playing files from certain device locations or recording files. For basic playback from www or remote URLs, cordova-plugin-media alone might suffice initially, but cordova-plugin-file is often a good companion.

# Optional, but often useful with media:
cordova plugin add cordova-plugin-file

After adding plugins, rebuild your project: cordova build <platform>.

Place an audio file (e.g., sound.mp3) in your www/audio/ directory. For this example, create www/audio/sound.mp3. If you don’t have an MP3, you can find short, royalty-free sounds online.

In www/index.html, add buttons for controlling audio playback:

<body>
<h1>Media Player Demo</h1>
<button id="playAudioBtn">PLAY</button>
<button id="pauseAudioBtn">PAUSE</button>
<button id="stopAudioBtn">STOP</button>
<br><br>
<label for="volumeRange">Volume:</label>
<input type="range" id="volumeRange" min="0" max="1" step="0.1" value="0.5">
<br><br>
<div id="mediaStatus">Status: Idle</div>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
</body>

In www/js/index.js, implement the audio control functions. All Media object interactions must occur after deviceready.

document.addEventListener('deviceready', onDeviceReady, false);
let myMedia = null;
let mediaTimer = null; // For updating playback position, not used in this basic example
const audioFilePath = 'audio/sound.mp3'; // Relative path within www folder
// For Android, files in www are typically accessed via 'file:///android_asset/www/audio/sound.mp3'
// The plugin often handles resolving this, but be aware of platform differences for local files.
function onDeviceReady() {
console.log('Device is ready. Media API available.');
document.getElementById('playAudioBtn').addEventListener('click', playAudio);
document.getElementById('pauseAudioBtn').addEventListener('click', pauseAudio);
document.getElementById('stopAudioBtn').addEventListener('click', stopAudio);
document.getElementById('volumeRange').addEventListener('input', setVolume);
// Initialize buttons (optional)
document.getElementById('pauseAudioBtn').disabled = true;
document.getElementById('stopAudioBtn').disabled = true;
}
function updateMediaStatus(statusText) {
document.getElementById('mediaStatus').textContent = `Status: ${statusText}`;
console.log(`Media Status: ${statusText}`);
}
// Media object success callback
function mediaSuccess() {
updateMediaStatus('Action successful.');
}
// Media object error callback
function mediaError(error) {
updateMediaStatus(`Error: Code ${error.code}, Message: ${error.message}`);
console.error('Media Error:', error);
// Reset UI if playback failed critically
if (myMedia) myMedia.release(); // Release resources
myMedia = null;
document.getElementById('playAudioBtn').disabled = false;
document.getElementById('pauseAudioBtn').disabled = true;
document.getElementById('stopAudioBtn').disabled = true;
}
// Media object status callback (optional)
function mediaStatusCallback(status) {
if (status === Media.MEDIA_STARTING) updateMediaStatus('Starting...');
if (status === Media.MEDIA_RUNNING) updateMediaStatus('Playing...');
if (status === Media.MEDIA_PAUSED) updateMediaStatus('Paused.');
if (status === Media.MEDIA_STOPPED) {
updateMediaStatus('Stopped.');
// When playback finishes naturally or is stopped, release resources and reset UI
if (myMedia) myMedia.release();
myMedia = null;
document.getElementById('playAudioBtn').disabled = false;
document.getElementById('pauseAudioBtn').disabled = true;
document.getElementById('stopAudioBtn').disabled = true;
}
}
function getMediaSrc() {
// On Android, files in the 'www' folder are at 'file:///android_asset/www/'.
// On iOS, they are in the app bundle.
// The plugin usually resolves relative paths correctly for www assets.
// If playing from other locations (e.g., cordova.file.dataDirectory), provide the full native path.
if (device.platform === "Android") {
return '/android_asset/www/' + audioFilePath;
}
return audioFilePath; // For iOS and browser, relative path often works
}
function playAudio() {
if (myMedia === null) {
const src = getMediaSrc();
myMedia = new Media(src, mediaSuccess, mediaError, mediaStatusCallback);
console.log(`Playing: ${src}`);
} else {
// If paused, resume from current position
console.log('Resuming playback.');
}
myMedia.play();
document.getElementById('playAudioBtn').disabled = true;
document.getElementById('pauseAudioBtn').disabled = false;
document.getElementById('stopAudioBtn').disabled = false;
}
function pauseAudio() {
if (myMedia) {
myMedia.pause();
updateMediaStatus('Paused');
document.getElementById('playAudioBtn').disabled = false;
document.getElementById('pauseAudioBtn').disabled = true;
}
}
function stopAudio() {
if (myMedia) {
myMedia.stop(); // This will trigger MEDIA_STOPPED status, which handles release.
// No need to call myMedia.release() here if mediaStatusCallback handles it.
// UI update is also handled by mediaStatusCallback.
updateMediaStatus('Stopping...'); // Immediate feedback before async stop completes
}
}
function setVolume() {
if (myMedia) {
const volume = document.getElementById('volumeRange').value;
myMedia.setVolume(volume);
updateMediaStatus(`Volume set to ${volume}`);
}
}
  • new Media(src, mediaSuccess, mediaError, mediaStatus): Creates a new Media object.
    • src: URL of the audio file. This can be a relative path (from www), an absolute local file path (e.g., from cordova.file.dataDirectory), or a remote URL.
    • mediaSuccess: Optional callback executed when an action (play, pause, stop, record) completes successfully.
    • mediaError: Optional callback executed if an error occurs. Receives a MediaError object with code and message.
    • mediaStatus: Optional callback executed when the state of the media player changes (e.g., starting, running, paused, stopped). Receives a status code.
  • media.play(): Starts or resumes playing an audio file.
  • media.pause(): Pauses playing an audio file.
  • media.stop(): Stops playing an audio file. Playback position is typically reset.
  • media.release(): Releases underlying OS audio resources. Crucial to call this when the Media object is no longer needed to free up resources, especially after playback is finished or if the user navigates away. The example’s mediaStatusCallback for MEDIA_STOPPED handles this.
  • media.seekTo(milliseconds): Moves the playback position.
  • media.setVolume(value): Sets the volume (0.0 to 1.0).
  • media.getCurrentPosition(successCallback, errorCallback): Gets the current playback position in seconds.
  • media.getDuration(): Gets the duration of the audio file in seconds. Returns -1 if duration is unknown.
  • media.startRecord(): Starts recording an audio file.
  • media.stopRecord(): Stops recording an audio file.

The mediaError callback receives an object with a code property:

  • MediaError.MEDIA_ERR_ABORTED (1)
  • MediaError.MEDIA_ERR_NETWORK (2)
  • MediaError.MEDIA_ERR_DECODE (3)
  • MediaError.MEDIA_ERR_NONE_SUPPORTED (4)
  • Resource Management: Always call myMedia.release() when you are finished with a Media object to free up native audio resources. This is especially important for long-lived apps or apps that play multiple sounds.
  • File Paths: Be careful with file paths. Relative paths from www are generally simple. For files outside www (e.g., recorded audio, downloaded files), use their full native URI obtained from cordova-plugin-file (e.g., fileEntry.toURL()).
  • Error Handling: Implement the mediaError callback robustly.
  • Status Callbacks: Use the mediaStatus callback to react to changes in playback state (e.g., to update UI when playback finishes).
  • Multiple Sounds: If you need to play multiple sounds simultaneously or manage complex audio, consider if this plugin is sufficient or if you need a more advanced audio engine/library. This plugin is generally for simpler, single-stream playback/recording.
  • Background Playback: By default, audio may stop when the app goes into the background. Android and iOS have specific platform guidelines and Cordova plugin options (like cordova-plugin-background-mode or specific media player configurations) if background audio is required.
  • Permissions: Recording audio will require microphone permissions. The plugin typically handles prompting the user.

For comprehensive details on all methods, properties, and platform quirks, refer to the Cordova Media Plugin documentation.