Я хотел бы добавить фоновую музыку, которая воспроизводится автоматически, возможно, только с «паузой/остановкой звука».
Я пробовал искать в нескольких источниках, но все найденные мной руководства включают в себя музыку для «воспроизведения звука», которая не понадобится.





На самом деле они не показывают этого в примерах, представленных на странице expo-av, но функция Audio.Sound.createAsync позволяет выполнять множество настроек. Вы можете установить громкость, решить, должен ли он воспроизводиться, решить, должен ли он воспроизводиться при загрузке, и даже подписаться на обновления статуса воспроизведения и установить интервалы, с которыми вы будете получать эти обновления. Я переборщил и разработал функцию, возвращающую статус, позицию и продолжительность песни во время ее воспроизведения; и если вам нужно подписаться на дополнительную информацию, хук позволит вам подписаться на события обновления воспроизведения:
import { useState, useEffect, useCallback, useMemo } from 'react';
import { Audio, usePermissions } from 'expo-av';
const msToSeconds = (num) => Math.round(num / 1000);
// these should work but I found that only isPlaying works
const STATUSES = ['isBuffering', 'isPlaying', 'didJustFinished', 'isLooping'];
const getStatus = (playbackEvent) => {
if (playbackEvent.durationMillis === playbackEvent.positionMillis)
return 'finished';
const status = STATUSES.find((status) => playbackEvent[status] === true);
if (status) return status === 'didJustFinished' ? 'finished' : status;
};
export default function useAudio({
uri,
shouldPlay = false,
onPlaybackStatusUpdate,
updateIntervals = 500,
startPosition = 0,
shouldLoop = false,
}) {
const [sound, setS] = useState(null);
const [position, setPosition] = useState(0);
const [status, setStatus] = useState('isLoading');
const [duration, setDuration] = useState(0);
const handlePlaybackStatusChange = useCallback(
(playbackEvent) => {
setStatus(getStatus(playbackEvent));
setPosition(msToSeconds(playbackEvent.positionMillis||0));
// because this function is recreated everytime onPlaybuckStatusChange
// is recreated, onPlaybackStatusUpdate may need to be wrap in an
// useCallback for better performance
onPlaybackStatusUpdate?.(playbackEvent);
},
[onPlaybackStatusUpdate]
);
// cleanup function
useEffect(() => {
return async () => {
if (sound) {
// await sound.pauseAsync();
await sound.unloadAsync();
}
};
}, [sound]);
// load song on uri changes
useEffect(() => {
const loadSound = async () => {
try {
const {sound,status} = await Audio.Sound.createAsync(
uri,
{
shouldPlay,
progressUpdateIntervalMillis: updateIntervals,
positionMillis: startPosition,
isLooping: shouldLoop,
volume:1
},
handlePlaybackStatusChange
);
setS(sound);
setDuration(msToSeconds(status.durationMillis));
} catch (err) {
console.info(err);
setStatus('error')
}
};
loadSound();
}, [
uri,
handlePlaybackStatusChange,
shouldLoop,
shouldPlay,
startPosition,
updateIntervals,
]);
return { position, status, duration,sound };
}
Использование крючка (демо):
const playOnLoad = true;
const updateIntervals = 1000;
const startPosition = 1000 * 60 * 4.4;
export default function App() {
const { width } = useWindowDimensions();
const barWidth = width * 0.8;
const { position, duration, status } = useAudio({
uri: require('./song.mp3'),
shouldPlay: playOnLoad,
updateIntervals,
startPosition:0,
shouldLoop: true,
});
return (
<SafeAreaView style = {styles.container}>
<View style = {[styles.player, { width: barWidth }]}>
<Text>Sound status:{status}</Text>
<Progress.Bar progress = {position/duration || 0} width = {barWidth} color = "green" />
<View style = {styles.timeContainer}>
<Text style = {styles.currentTime}>{formatSeconds(position)}</Text>
<Text style = {styles.duration}>{formatSeconds(duration)}</Text>
</View>
</View>
</SafeAreaView>
);
}