'How to persist Expo Audio throughout react native app?
I am new to react native. I am trying to make a podcast player. While I was able to make it work in my Podcast component, when I change to other component, the audio player current status is not recognized. I am reusing AudioPlayer component (the one in green) that is working fine in the Podcast component. But how can I have access to the currently playing song from other pages like Home?
This is my AudioPlayer.js that I am trying to reuse in other components. I want to have controls like pause/play, next work from other other components. I am storing the current audio url in redux store but the only thing that I am to do so far is restart the current audio when I click pause from other component.
import React, {useState} from "react";
import { View, Text, Image, TouchableOpacity, StyleSheet } from "react-native";
import { AntDesign } from "@expo/vector-icons";
import { connect } from "react-redux";
import { Audio } from "expo-av";
import { audioPlayerAction } from "../actions";
import { radio } from "../assets/radio/radio";
import { styles } from "../assets/styles";
const audio = new Audio.Sound();
const AudioPlayer = (props) => {
// get currently playing song url from redux store
const { audioSrc, index } = props.storeState;
const [currentAudioIndex, setCurrentAudioIndex] = useState(index);
const [currentAudio, setCurrentAudio] = useState(null);
const [loaded, setLoaded] = useState(false);
const [paused, setPaused] = useState(false);
const [nowPlaying, setNowPlaying] = useState("");
const [playerStatus, setPlayerStatus] = useState(null);
Audio.setAudioModeAsync({
staysActiveInBackground: true,
});
// continue playing next song when done
const onPlaybackStatusUpdate = (playbackStatus) => {
if (playbackStatus.didJustFinish) {
next();
}
};
const play = async (url) => {
if (currentAudio !== url) {
await audio.unloadAsync();
try {
const status = await audio.loadAsync(
{
uri: url,
},
{ shouldPlay: true }
);
audio.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate);
setCurrentAudio(url);
setPlayerStatus(status);
setLoaded(true);
setPaused(false);
setNowPlaying(radio[currentAudioIndex].station);
await audio.playAsync();
} catch (error) {
console.log(error);
}
} else if (currentAudio === url && loaded === true && paused === false) {
await audio.pauseAsync();
setPaused(true);
} else if (currentAudio === url && loaded === true && paused === true) {
await audio.playAsync();
setPaused(false);
}
};
const next = async () => {
let nextIndex = index + 1 >= radio.length ? 0 : index + 1;
setCurrentAudioIndex(nextIndex);
let nextAudio = radio[nextIndex].url;
props.audioPlayerAction(nextAudio, true, null, "podcast", nextIndex);
play(nextAudio);
};
const prev = () => {
let prevSongIndex = index - 1 < 0 ? radio.length - 1 : index - 1;
let prevAudio = radio[prevSongIndex].url;
props.audioPlayerAction(prevAudio, true, null, "podcast", prevSongIndex);
play(prevAudio);
};
return (
<View style={style.container}>
<View style={style.musicTitle}>
<Text style={style.musicTitleText}>Now Playing: {nowPlaying}</Text>
</View>
<View style={style.controls}>
<TouchableOpacity onPress={() => prev()}>
<AntDesign style={style.icon} name="stepbackward" />
</TouchableOpacity>
<TouchableOpacity onPress={() => play(audioSrc)}>
<AntDesign style={style.icon} name={paused ? "play" : "pause"} />
</TouchableOpacity>
<TouchableOpacity onPress={() => next()}>
<AntDesign style={style.icon} name="stepforward" />
</TouchableOpacity>
</View>
</View>
);
};
const MapStateToProps = (state) => {
return { storeState: state.audioPlayerReducer };
};
export default connect(MapStateToProps, { audioPlayerAction })(AudioPlayer);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|