Building a Voice Recorder App for Android and IOS with Monaca Using Capacitor and cordova-plugin-media

Alvaro Saldanha
The Web Tub
Published in
6 min readJul 26, 2024
Photo by Jonathan Farber on Unsplash

Introduction

Have you ever wanted to incorporate microphone or webcam functionality into your Monaca app? With the cordova-plugin-media plugin, it’s easier than you might think! In this beginner-friendly tutorial, we’ll walk you through the process of creating a simple voice recorder app using Monaca and cordova-plugin-media.

By the end of this guide, you’ll have a fully functional voice recorder app that allows users to record audio, stop the recording, and play back the recorded audio. Let’s get started!

Main Screen of Application

Step 1: Set Up the HTML Structure

We’ll be using the Framework7 template for this tutorial. Here’s the HTML structure for our voice recorder app. This is home.f7:

<template>
<div class="page" data-name="home">
</div>
</template>
<script>
export default () => {
return $render;
}
</script>

And this is the HTML for voiceRecorder.f7:

<template>
<div class="page" data-name="catalog">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">Voice Recorder</div>
</div>
</div>
<div class="page-content">
<!-- Display buttons based on recording status -->
${ status == 'ready' ?
$h`<button class="button button-large button-fill" @click=${start}>Start Recording</button>` :
$h`<button class="button button-large button-fill" @click=${stop}>Stop Recording</button>`
}
<p>
${ playable &&
$h`
<div class="block-title">Recorded Audio</div>
<button class="button button-large button-fill" @click=${listen}>Play</button>
`
}
</p>
</div>
</div>
</template>

In this structure, we have a “Start Recording” button that initiates the audio recording when clicked. Once the recording starts, the button changes to “Stop Recording.” After stopping the recording, a “Play” button appears, allowing users to listen to the recorded audio.

The visibility of the buttons is controlled by the `status` and `playable` variables, which we’ll discuss in the JavaScript section.

Initial Screen Before Recording

Step 2: Implement the JavaScript Functionality

Now, let’s dive into the JavaScript code that powers our voice recorder app.

Overall Structure

<script>
export default (props, { $update }) => {
// Your code goes here

return $render;
}
</script>

All the code we write will be inside this structure.

Variables

First, let’s define the variables we’ll be using throughout the app:

// Object for recording
let recorder;
// Recording status
let status = "ready";
// Play button status
let playable = false;
let mediaRec; // cordova-plugin-media recorder

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

function onDeviceReady() {
// Cordova is now fully loaded. Now you can safely use Cordova plugins.
console.log("Cordova is ready, and the Media plugin can be used.");
}
  • `recorder`: This variable will store the `MediaRecorder` object used for recording audio.
  • `status`: Represents the current recording status (“ready” or “recording”).
  • `playable`: Determines whether the “Play” button should be visible or not.
  • ‘mediaRec’: To be able to use the cordova-plugin-media plugin.

Start Recording

When the “Start Recording” button is clicked, the `start` function is called:

// Start recording
const start = async (e) => {
e.preventDefault();
// cordova-plugin-media for recording
const src = "myRecording.wav"; // File name to store the recording
mediaRec = new Media(src,
() => console.log("Record Success"),
(err) => console.error("Record Error:", err)
);
mediaRec.startRecord();
status = 'recording';
$update();
};

Here’s what happens in the `start` function:

  1. We initialize the file name for the recording to "myRecording.wav".

2. We create a new Media object named mediaRec using the cordova-plugin-media plugin. The Media constructor takes three arguments:

  • src: The name of the file where the recording will be stored.
  • A success callback function: This will be called when the recording starts successfully and logs “Record Success” to the console.
  • An error callback function: This will be called if there is an error starting the recording and logs the error message to the console.

3. We start the recording by calling the startRecord method on the mediaRec object.

4. We update the `status` variable to “recording” to reflect the current recording state.

5. Finally, we call `$update()` to update the UI based on the new status.

Screen During Recording

Stop Recording

When the “Stop Recording” button is clicked, the `stop` function is called:

// Stop recording
const stop = (e) => {
e.preventDefault();
mediaRec.stopRecord();
status = 'ready';
playable = true;
$update();
}

In the `stop` function:

  1. We stop the recording by calling `mediaRec.stopRecord()`.

2. We reset the `status` variable to “ready” to indicate that recording has stopped.

3. We set `playable` to `true` to make the “Play” button visible.

4. We call `$update()` to update the UI based on the new status and playable state.

Play Recorded Audio

When the “Play” button is clicked, the `listen` function is called:

// Play recorded audio
const listen = async () => {
// Use cordova-plugin-media for playback
mediaRec.play();
}

The listen function simply calls mediaRec.play().

Play Recording Screen

Step 3: Complete Code

Here’s the complete code for our voice recorder app:

<template>
<div class="page" data-name="catalog">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">Voice Recorder</div>
</div>
</div>
<div class="page-content">
<!-- Display buttons based on recording status -->
${ status == 'ready' ?
$h`<button class="button button-large button-fill" @click=${start}>Start Recording</button>` :
$h`<button class="button button-large button-fill" @click=${stop}>Stop Recording</button>`
}
<p>
${ playable &&
$h`
<div class="block-title">Recorded Audio</div>
<button class="button button-large button-fill" @click=${listen}>Play</button>
`
}
</p>
</div>
</div>
</template>
<script>
export default (props, { $update }) => {
let recorder;
let status = 'ready';
let playable = false;
let mediaRec; // cordova-plugin-media recorder

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

function onDeviceReady() {
// Cordova is now fully loaded. Now you can safely use Cordova plugins.
console.log("Cordova is ready, and the Media plugin can be used.");
}

// Start recording
const start = async (e) => {
e.preventDefault();
// cordova-plugin-media for recording
const src = "myRecording.wav"; // File name to store the recording
mediaRec = new Media(src,
() => console.log("Record Success"),
(err) => console.error("Record Error:", err)
);
mediaRec.startRecord();
status = 'recording';
$update();
};

// Stop recording
const stop = (e) => {
e.preventDefault();
mediaRec.stopRecord();
status = 'ready';
playable = true;
$update();
}

// Play recorded audio
const listen = async () => {
// Use cordova-plugin-media for playback
mediaRec.play();
}

return $render;
}
</script>Note: If you want to use the webcam instead of the microphone, keep in mind that iOS does not allow embedding camera video in wkWebView. As a result, using the webcam will lead to a full-screen view. If you need to use the camera video, consider using the https://github.com/cordova-rtc/cordova-plugin-iosrtc?tab=readme-ov-file plugin, which provides a getUserMedia-like API. However, be aware that there are some differences, such as the `dataavailable` event being called only once.

Conclusion

Congratulations! You’ve successfully built a voice recorder app using Monaca and the cordova-plugin-media plugin.

With this app, users can record audio, stop the recording, and play back the recorded audio. You can further enhance this app by allowing users to save the recorded audio, upload it to the cloud, or apply it to an audio tag.

The possibilities are endless! We hope this tutorial has provided you with a solid foundation for incorporating microphone functionality into your Monaca apps. Happy coding!

Link to repository with code: https://github.com/monaca-samples/voice-recorder/tree/main

--

--