Intro
These days, lots of mobile apps (including voice note apps, music players, and social media platforms) can record and play audio. By using libraries made to handle audio operations, you may quickly add this functionality to your React Native application.
With the help of these libraries' powerful features, you may capture, store, and play audio in iOS and Android environments.
Although you can use both Expo and React Native, Expo will be the main emphasis of this article because it makes a lot of the configuration for both iOS and Android simpler.
Step 1: Set Up a New React Native Project
Let's use Expo to create a new React Native project to get things going. Expo includes a built-in expo-av
package that offers audio recording and playback functions, along with a managed environment for developing React Native applications.
The following command can be used to start a new project:
After the project has been configured, open the project folder:
npx create-expo-app MyNewProject
Navigate to Your Project and Start the Development Server
cd MyNewProject
npx expo start
Step 2: Installing Dependencies
We will require the expo-av
library, which is a component of Expo's Audio/Video API, to record and play audio. This package offers a set of high-level, cross-platform APIs to make the process of recording and playing audio easier.
Use the following command to install expo-av
:
npx expo install expo-av
This will set up the package required to manage audio features.
Step 3: Requesting Permissions
Your app needs to ask the user for permission to use the device's microphone before it can start recording audio. Your program won't work successfully without specific permission to record audio, which is required for both iOS and Android.
By using Expo's Permissions API, you may request microphone access.
Open your App.js
file and make the necessary changes to add the request for permission:
import React, { useEffect, useState } from 'react';
import { View, Text, Button } from 'react-native';
import { Audio } from 'expo-av';
export default function App() {
useEffect(() => {
// Request microphone permission when the app is loaded
Audio.requestPermissionsAsync();
}, []);
...
}
This code will ask for the required authorization to record audio. A notification stating that microphone access is permitted appears if the request is approved.
Step 4: Recording Audio
You can now begin recording audio because you have the required authorizations. You will utilize the Audio.Recording
class from expo-av
to accomplish this. There are methods in this class for managing, pausing, and starting audio recordings.
To enable audio recording in your app, follow these steps:
import React, { useState, useRef } from 'react';
import { Button } from 'react-native';
import { Audio } from 'expo-av';
export default function App() {
const recordingRef = useRef(null);
const [isRecording, setIsRecording] = useState(false);
const [recordingURI, setRecordingURI] = useState(null);
const startRecording = async () => {
try {
setRecordingURI(null);
console.log('Starting recording..');
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
const recording = new Audio.Recording();
await recording.prepareToRecordAsync();
await recording.startAsync();
recordingRef.current = recording;
setIsRecording(true);
console.log('Recording started');
} catch (error) {
console.error('Failed to start recording:', error);
}
};
const stopRecording = async () => {
console.log('Stopping recording..');
try {
await recordingRef.current?.stopAndUnloadAsync();
} catch (error) {
// Do nothing -- we are already unloaded.
}
const uri = recordingRef.current?.getURI();
setRecordingURI(uri);
console.log('Recording stopped and stored at', uri);
recordingRef.current = null;
setIsRecording(false);
};
return (
...
)
}
Step 5: Playing Back Audio
Playing back the audio is the next step after recording it. Expo has an Audio.Sound
class for managing the playback of audio.
To play the recorded audio, you can change your app as follows:
import React, { useState, useRef } from 'react';
import { Button } from 'react-native';
import { Audio } from 'expo-av';
export function PlayRecording({ recordingURI }) {
const soundRef = useRef(null);
const [isPlaying, setIsPlaying] = useState(false);
if (isPlaying) {
return (
<Button
title="Stop Playing"
onPress={() => {
soundRef.current?.stopAsync();
soundRef.current = null;
setIsPlaying(false);
}}
/>
);
}
return (
<Button
title="Play Recording"
onPress={async () => {
console.log('Loading sound..');
const { sound } = await Audio.Sound.createAsync(
{ uri: recordingURI },
{ shouldPlay: true }
);
sound.setOnPlaybackStatusUpdate((status) => {
setIsPlaying(status.isPlaying);
if (status.didJustFinish) {
setIsPlaying(false); // Reset playing status when finished
}
});
console.log('Playing sound..');
await sound.playAsync();
soundRef.current = sound;
}}
/>
);
}
A "Play Recording" button will now show up after the recording is finished. The audio that was just captured will play when you click this button.
Step 6: Testing the Application
Now, let's test the full recording application:
import React, { useState, useEffect, useRef } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { Audio } from 'expo-av';
import { PlayRecording } from './PlayRecording';
export default function App() {
const recordingRef = useRef(null);
const [isRecording, setIsRecording] = useState(false);
const [recordingURI, setRecordingURI] = useState(null);
useEffect(() => {
// Request microphone permission when the app is loaded
Audio.requestPermissionsAsync();
}, []);
const startRecording = async () => {
try {
setRecordingURI(null);
console.log('Starting recording..');
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
const recording = new Audio.Recording();
await recording.prepareToRecordAsync();
await recording.startAsync();
recordingRef.current = recording;
setIsRecording(true);
console.log('Recording started');
} catch (error) {
console.error('Failed to start recording:', error);
}
};
const stopRecording = async () => {
console.log('Stopping recording..');
try {
await recordingRef.current?.stopAndUnloadAsync();
} catch (error) {
// Do nothing -- we are already unloaded.
}
const uri = recordingRef.current?.getURI();
setRecordingURI(uri);
console.log('Recording stopped and stored at', uri);
recordingRef.current = null;
setIsRecording(false);
};
return (
<View style={styles.container}>
<Text>Audio Recording Example</Text>
<Button
title={isRecording ? 'Stop Recording' : 'Start Recording'}
onPress={isRecording ? stopRecording : startRecording}
/>
{recordingURI && (
<View style={{ marginTop: 20 }}>
<PlayRecording recordingURI={recordingURI} />
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
You may then use your mobile device to scan the QR code or launch your app through an emulator once the Expo DevTools are loaded in your browser.
Press the "Start Recording" button to start recording audio as soon as the app launches. Click "Stop Recording" once a few seconds of recording have passed. There ought to be a URI pointing to the saved audio file visible on the screen. To play back the audio, select "Play Recording" after that.
Best Practices for Working with Audio in React Native
Request Permissions Early
It is important to obtain permissions for audio recording as early as possible in the user journey. In this manner, when users want to record, the program doesn't abruptly stop and ask for authorization.
Error Handling
When interacting with native device features, it is important to always handle mistakes with grace. Give the user guiding messages if a recording is unsuccessful or authorization is denied.
Optimize Audio Settings
You may need to change the audio settings for higher quality or smaller file sizes, depending on the use case of your app. The Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
preset is a good starting point, but feel free to explore other presets based on your needs.
Release Resources
Recall to appropriately release the resources after recording or playing audio to prevent memory leakage and battery waste.
Conclusion
You may improve the functionality and user experience of your mobile app by recording and playing audio in React Native. You can record, save, and play audio in iOS and Android applications with ease by utilizing the expo-av
package.