React Native Expo应用音频无法重复播放问题求助
解决Expo Audio仅能播放一次的问题
问题核心:使用useAudioPlayer创建的播放器,首次播放完毕后会停留在音频结尾位置,再次调用play()不会触发从头播放,导致后续点击无法播放音效。
解决方法
每次播放音效前,先将音频位置重置到起始点,或者直接使用replayAsync()方法(该方法会自动重置位置并播放)。由于replayAsync()是异步方法,需要将处理函数改为异步函数。
修改后的代码
import { View, Text, StyleSheet } from "react-native"; import React, { useContext } from "react"; import Task from "./../Task/Task"; import { ModalContext } from "@/context/ModalContext"; import ModalText from "@/components/ModalText/ModalText"; import { PlayerInformationContext } from "@/context/PlayerInformation"; import { appText } from "@/assets/data"; import { useAudioPlayer } from "expo-audio"; const audioSource = require("./../../assets/sounds/game-bonus.mp3"); const Tasks = () => { const player = useAudioPlayer(audioSource); const { money, correctAnswersCount, seenAdsCount, language, canPlaySound, handleCorrectAnswers, handleSeenAdsCount, setMoney, } = useContext(PlayerInformationContext); const { toggleModal, setModalContent } = useContext(ModalContext); // 改为异步函数 const handleTaskCompletion = async ( taskCount, rewardAmount, resetCount, modalText ) => { if (taskCount === 10) { if (canPlaySound) { // 使用replayAsync重置并播放 await player.replayAsync(); } setMoney(money + rewardAmount); resetCount(0); setModalContent(<ModalText text={modalText} canShowButton={true} />); toggleModal(); } else { setModalContent( <ModalText text={appText[language].rewardWarningMessage} canShowButton={true} /> ); toggleModal(); } }; return ( <View style={styles.container}> <Text style={styles.container_Text}>{appText[language].tasks}</Text> <Task title={appText[language].task1} credit="50" itemsLeft={correctAnswersCount} onPress={() => handleTaskCompletion( correctAnswersCount, 50, handleCorrectAnswers, appText[language].earned50Coin ) } /> <Task title={appText[language].task2} credit="75" itemsLeft={seenAdsCount} onPress={() => handleTaskCompletion( seenAdsCount, 75, handleSeenAdsCount, appText[language].earned75Coin ) } /> </View> ); }; export default Tasks; const styles = StyleSheet.create({ container: { width: "100%", height: "100%", alignItems: "center", justifyContent: "flex-start", }, container_Text: { width: "100%", marginTop: 40, textAlign: "center", color: "white", fontWeight: "bold", fontSize: 32, }, });
另一种可选方案
如果不想使用异步函数,也可以手动重置播放位置后再播放:
if (canPlaySound) { player.setPositionAsync(0); player.play(); }
这种方式无需修改函数为异步,但setPositionAsync是异步操作,可能存在极少数情况下播放位置还没重置就开始播放的问题,推荐使用replayAsync的方案。
内容的提问来源于stack exchange,提问作者Ozan
相关产品推荐
相关产品推荐

