I'm new to React Native and I'm using the expo-audio library (from Expo SDK 50+) to play sounds in my app. The sound playback works perfectly in the web preview, but when I run it on Expo Go or an Android emulator, the sound plays only once — subsequent button presses don't trigger the sound again.
Has anyone else experienced this issue or found a workaround to replay the sound reliably on mobile devices?
import { useAudioPlayer } from 'expo-audio';
import React, { useState } from 'react';
import { Alert, Button, Image, Modal, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
const home = () => {
const [userNameModalVisibility, setUserNameModalVisibility] = useState(false);
const [settingModal, setSettingModal] = useState(false);
const [music, setMusic] = useState(true);
const [audio, setAudio] = useState(true);
const [userName, setUserName] = useState('NONE');
const musicSource = require('../assets/sounds/homebackground.wav');
const musicPlayer = useAudioPlayer(musicSource);
const settingAudio = require('../assets/sounds/settingbutton.wav');
const settingAudioPlayer = useAudioPlayer(settingAudio);
const ouchAudio = require("../assets/sounds/ouch.wav");
const ouchAudioPlayer = useAudioPlayer(ouchAudio);
const dooropenAudio = require("../assets/sounds/dooropening.wav");
const dooropenPlayer = useAudioPlayer(dooropenAudio);
const musicSetting = () => {
setMusic(!music);
music ? musicPlayer.pause() : musicPlayer.play();
}
const audioPlayer = (currentAudio: string) => {
if (currentAudio !== '' && audio) {
switch(currentAudio) {
case 'ouch':
ouchAudioPlayer.play();
break;
case 'dooropen':
dooropenPlayer.play();
break;
case 'settingButton':
settingAudioPlayer.play();
break;
}
}
}
return (
<SafeAreaProvider>
<SafeAreaView>
{/* simplified view content */}
<TouchableOpacity onPress={() => audioPlayer('ouch')}>
<Text>Play Ouch Sound</Text>
</TouchableOpacity>
</SafeAreaView>
</SafeAreaProvider>
);
}
export default home;
You need to return to the beginning of your audio before you can play it again because "expo-audio does not reset the playback position when the audio finishes" like it is in expo-av. There's a note about it on the docs here (check note after Usage -> playing sounds).
Try this (directly from your code)
import { useAudioPlayer } from 'expo-audio';
import React, { useState } from 'react';
import { Alert, Button, Image, Modal, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
const home = () => {
const [userNameModalVisibility, setUserNameModalVisibility] = useState(false);
const [settingModal, setSettingModal] = useState(false);
const [music, setMusic] = useState(true);
const [audio, setAudio] = useState(true);
const [userName, setUserName] = useState('NONE');
const musicSource = require('../assets/sounds/homebackground.wav');
const musicPlayer = useAudioPlayer(musicSource);
const settingAudio = require('../assets/sounds/settingbutton.wav');
const settingAudioPlayer = useAudioPlayer(settingAudio);
const ouchAudio = require("../assets/sounds/ouch.wav");
const ouchAudioPlayer = useAudioPlayer(ouchAudio);
const dooropenAudio = require("../assets/sounds/dooropening.wav");
const dooropenPlayer = useAudioPlayer(dooropenAudio);
const musicSetting = () => {
setMusic(!music);
music ? musicPlayer.pause() : musicPlayer.play();
}
const audioPlayer = (currentAudio: string) => {
if (currentAudio !== '' && audio) {
switch(currentAudio) {
case 'ouch':
ouchAudioPlayer.seekTo(0); // add this line
ouchAudioPlayer.play();
break;
case 'dooropen':
dooropenPlayer.seekTo(0); // and this line
dooropenPlayer.play();
break;
case 'settingButton':
settingAudioPlayer.seekTo(0);
settingAudioPlayer.play();
break;
}
}
}
return (
<SafeAreaProvider>
<SafeAreaView>
{/* simplified view content */}
<TouchableOpacity onPress={() => audioPlayer('ouch')}>
<Text>Play Ouch Sound</Text>
</TouchableOpacity>
</SafeAreaView>
</SafeAreaProvider>
);
}
export default home;