Есть ли способ добавить фоновую музыку без добавления кнопки «Воспроизвести музыку» с помощью Expo AV?

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

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

Умерло ли Create-React-App?
Умерло ли Create-React-App?
В этом документальном фильме React.dev мы исследуем, мертв ли Create React App (CRA) и какое будущее ждет этот популярный фреймворк React.
Освоение React Native: Пошаговое руководство для начинающих
Освоение React Native: Пошаговое руководство для начинающих
React Native - это популярный фреймворк с открытым исходным кодом, используемый для разработки мобильных приложений. Он был разработан компанией...
В чем разница между react native и react ?
В чем разница между react native и react ?
React и React Native - два популярных фреймворка для создания пользовательских интерфейсов, но они предназначены для разных платформ. React - это...
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
Хуки React: что это такое и как их использовать
Хуки React: что это такое и как их использовать
Хуки React - это мощная функция библиотеки React, которая позволяет разработчикам использовать состояние и другие возможности React без написания...
0
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На самом деле они не показывают этого в примерах, представленных на странице 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>
  );
}

Другие вопросы по теме