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.
Step 1 - Install Media Plugin
Section titled “Step 1 - Install Media Plugin”Install the plugin using the Cordova CLI:
cordova plugin add cordova-plugin-mediaThis 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-fileAfter adding plugins, rebuild your project: cordova build <platform>.
Step 2 - Prepare an Audio File
Section titled “Step 2 - Prepare an Audio File”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.
Step 3 - Prepare the UI
Section titled “Step 3 - Prepare the UI”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>Step 4 - Implement JavaScript Logic
Section titled “Step 4 - Implement JavaScript Logic”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 exampleconst 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 callbackfunction mediaSuccess() { updateMediaStatus('Action successful.');}
// Media object error callbackfunction 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}`); }}Key Media Object Methods and Concepts
Section titled “Key Media Object Methods and Concepts”new Media(src, mediaSuccess, mediaError, mediaStatus): Creates a new Media object.-
src: URL of the audio file. This can be a relative path (fromwww), an absolute local file path (e.g., fromcordova.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 aMediaErrorobject withcodeandmessage.
-
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’smediaStatusCallbackforMEDIA_STOPPEDhandles 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.
MediaError Codes
Section titled “MediaError Codes”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)
Best Practices and Considerations
Section titled “Best Practices and Considerations”- Resource Management: Always call
myMedia.release()when you are finished with aMediaobject 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
wwware generally simple. For files outsidewww(e.g., recorded audio, downloaded files), use their full native URI obtained fromcordova-plugin-file(e.g.,fileEntry.toURL()). - Error Handling: Implement the
mediaErrorcallback robustly. - Status Callbacks: Use the
mediaStatuscallback 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-modeor 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.