0

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.

stehvanin
  • 11
  • 2

0 Answers0