EDIT: I'm using react-native-track-player": "^3.2.0"
I have an issue with "react-native-track-player".
The audio files in my app are played via this function:
async function setUpNewTrack() {
try {
await TrackPlayer.reset()
await TrackPlayer.add({
id: podcastEpisode._id,
url: podcastEpisode.attributes.audio,
title: podcastEpisode.attributes.title,
artist: podcastEpisode.attributes.author,
artwork: podcastEpisode.attributes.image || podcastEpisode.relationships.podcast.data.image,
description: podcastEpisode.attributes.description || podcastEpisode.attributes.content,
})
setCurrentPlayingPodcast(podcastEpisode)
if (podcastPlaybackTime !== 0) {
await TrackPlayer.seekTo(podcastPlaybackTime)
}
await TrackPlayer.play()
setCurrentPlayingPodcastId(podcastEpisode._id)
setCurrentlyPlayPodcast(podcastEpisode._id)
} catch (error) {
Alert.alert("Error", "There was an error playing the podcast")
console.error({
message: "Error in PodcastMediaPlayer.tsx: setUpNewTrack",
error,
})
}
}
So when the user press "Play" button, this function is executed. And it works fine unless the podcastEpisode.attributes.audio
is not valid. Because the links are controlled by third-party, sometimes they get deleted and stop working, and I cannot do anything about it.
My problem with "react-native-track-player" is that the playback state after the executing TrackPlayer.play()
it is connecting
and even tho it will never connect, because the link is broken, TrackPlayer.play()
function doesn't throw an error.
So I'm wondering how to handle this kind of situations, when the audio link doesn't work, is there some way to make TrackPlayer.play()
to throw an error if it cannot connect for some time, some kind of timeout?
I tried to solve it with creating a timeout if the TrackPlayer.play()
promise is not resolved, but I guess no matter if the playBackState
is playing
or connecting
the promise from TrackPlayer.play()
is considered as resolved.
This is my failed attempt to fix the issue:
const playerLoadingTimeout = new Promise(
(_resolve, reject) =>
setTimeout(() => reject(new Error("We couldn't load the podcast.")), 10000), // 10 seconds
)
await Promise.race([TrackPlayer.play(), playerLoadingTimeout])
.then((res) => console.log(res))
.catch((err) => Alert.alert("OHO !", err.message))
I have also tried to follow the playbackState
and use timer, so if the playbackState
is connecting
more than 10 seconds, to restart the player, but it didn't worked.
function handleLongConnection() {
const timeout = setTimeout(() => {
try {
if (playBackState === State.Connecting || playBackState === State.Buffering) {
Alert.alert("Error", "There was an error playing the podcast")
TrackPlayer.reset()
}
} catch (error) {
console.log("THERE IS AN ERROR", error)
}
}, 10000)
return () => clearTimeout(timeout)
}
useEffect(() => {
return handleLongConnection()
}, [playBackState])
I have also noticed, that sometimes when I call TrackPlayer.reset()
the playbackState
actually change to State.Pause
instead of State.None
as it suppose to. This have been a problem on iOS, on Android, when I call TrackPlayer.reset()
the playbackState
change to idle
which is alright, as I can track when the track has stopped.