Here’s a quick tutorial to get you started playing an mp3 file in an Android app that was built using React Native. This tutorial was developed using Linux (Ubuntu 16.04), React Native 0.61.5, and the React Native Sound package 0.11.0.
First, make your project directory. Let’s call it AudioTmp. In a terminal window, do this:
npx react-native init AudioTmp
cd AudioTmp
All of the following commands assume you’ve got your terminal window open, and you’re standing in the root directory of your project (in AudioTmp
, where App.js
is located).
You’ll need some extra packages, so run these install commands:
npm install typescript@
npm install eslint@^5.0.0
npm install react-native-sound
Next, as described in the React Native Sound documentation, use the link
command:
react-native link react-native-sound
This “links” the library where needed into the android
and ios
directories.
Now add an mp3 file to your Android project:
mkdir android/app/src/main/res/raw
cp john_bartmann_04_earning_happiness.mp3 android/app/src/main/res/raw
You can download a copy of John Bartmann’s “Earning Happiness” mp3 file here. It has a public domain license; let’s thank John Bartmann for making his cool “Earning Happiness” music open source (original source at Free Music Archive)!
Next, make the utils
directory under your project root:
mkdir utils
Add a new file called SoundPlayer.js
in the utils
directory. Here’s the source for that:
/**
* Really simple demo of https://www.npmjs.com/package/react-native-sound
*/
const Sound = require('react-native-sound');
/**
* Audio credit:
* https://freemusicarchive.org/music/John_Bartmann/Public_Domain_Soundtrack_Music_Album_One/earning-happiness
* "Earning Happiness" by John Bartmann licensed under a CC0 1.0 Universal License
* https://creativecommons.org/publicdomain/zero/1.0/
*/
const FILENAME = 'john_bartmann_04_earning_happiness.mp3';
class SoundPlayer {
constructor(props) {
console.log("SoundPlayer constructor");
};
stopSound() {
console.log('SoundPlayer.stopSound');
this.whoosh.stop();
this.whoosh.release();
}
playSound() {
console.log('SoundPlayer.playSound');
let me = this;
me.whoosh = new Sound(FILENAME, Sound.MAIN_BUNDLE, error => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// loaded successfully
console.log(
'duration in seconds: ' +
me.whoosh.getDuration() +
'number of channels: ' +
me.whoosh.getNumberOfChannels()
);
me.whoosh.play(success => {
if (success) {
console.log('successfully finished playing');
} else {
console.log('playback failed due to audio decoding errors');
}
});
});
}
}
export default SoundPlayer;
Replace the code in App.js
with this code:
/**
* Simple demo of https://www.npmjs.com/package/react-native-sound
* The app plays an included mp3 file when the user clicks on 'Play' button.
* It stops the playback when the user clicks on the 'Stop' button.
*/
import React from 'react';
import {
StyleSheet,
View,
Text,
Button
} from 'react-native';
import {
Colors
} from 'react-native/Libraries/NewAppScreen';
/** Keep all sound functionality in separate utils area */
import SoundPlayer from './utils/SoundPlayer';
class App extends React.Component {
constructor(props) {
super(props);
this.soundPlayer = new SoundPlayer();
}
onPlayPress() {
console.log('onPlayPress method');
this.soundPlayer.playSound();
}
onStopPress() {
console.log('onPlayPress method');
this.soundPlayer.stopSound();
}
render() {
return (
<View style={styles.body}>
<Text style={styles.sectionTitle}>Click button to Play</Text>
<View style={styles.buttonStyle}>
<Button style={styles.buttonStyle}
onPress={this.onPlayPress.bind(this)}
title="Play"
/>
</View>
<Text style={styles.sectionTitle}>Click button to Stop</Text>
<View style={styles.buttonStyle}>
<Button buttonStyle={styles.buttonStyle}
onPress={this.onStopPress.bind(this)}
title="Stop"
/>
</View>
</View>
);
}
};
const styles = StyleSheet.create({
body: {
backgroundColor: Colors.white,
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
backgroundColor: 'gainsboro'
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
color: Colors.black,
padding: 20,
backgroundColor: 'gainsboro' /* See https://reactnative.dev/docs/colors */,
},
buttonStyle: {
padding: 20,
backgroundColor: 'gainsboro' /* See https://reactnative.dev/docs/colors */,
}
});
export default App;
Run the Android Emulator:
emulator -no-snapshot -avd Galaxy_Nexus_API_28
Start your Metro
server:
npx react-native start
Install the app in your Android Emulator:
npx react-native run-android
I see these warnings at my command line, but everything seems to work okay:
error React Native CLI uses autolinking for native dependencies, but the following modules are linked manually:
- react-native-sound (to unlink run: "react-native unlink react-native-sound")
This is likely happening when upgrading React Native from below 0.60 to 0.60 or above. Going forward, you can unlink this dependency via "react-native unlink <dependency>" and it will be included in your app automatically. If a library isn't compatible with autolinking, disregard this message and notify the library maintainers.
Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md
info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
Jetifier found 875 file(s) to forward-jetify. Using 8 workers...
Then it just works! You can hit the Play
and Stop
buttons to play the audio.
The source code for this project is available at github.
One remark: when I initially created this project, I didn’t use the link
command, because the React Native documentation indicated it was not needed for version 0.60. However, that turned out to be untrue! You can save yourself time by doing it the way I’ve done it in this tutorial. When using link
, the demo worked immediately, and I didn’t have to make any changes to gradle
files.
Here’s a view of the demo app: