0

I have multiple audio files that my audioplayer plays one by one. At times, especially after playing them 2 or 3 times, the audio pauses in the middle. When I try to press the play/pause button, I receive an error alert displaying either 'E_AUDIO_NOPLAYER' or 'E_LOAD_ERROR.' I then have to reload the app, after which it works fine. However, the same issue reappears after some time. What's wrong here? Following is my code:

const AudioPlayer = memo(
      ({
        data,
        audioPlayerState,
        currentIdx,
        setCurrentIdx,
        setAudioPlayerState,
        audioBaseUri,
        audioFieldName,
        onNextOrPreviousPageClick,
        flatlistRef,
        onAudioFinishCb
      }) => {
        const styles = useStyles()
        const sound = useRef(new Audio.Sound())
    
        useEffect(() => {
          initializeAudioMode()
          return () => {
            sound?.current?.pauseAsync()
          }
        }, [])
    
    
        initializeAudioMode = async () => {
          try {
            await Audio.setAudioModeAsync({
              allowsRecordingIOS: false,
              interruptionModeIOS: 'DoNotMix',
              playsInSilentModeIOS: true,
              staysActiveInBackground: true
              // interruptionModeAndroid: 'DuckOthers',
              // shouldDuckAndroid: true,
              // playThroughEarpieceAndroid: true
            })
            loadAudio()
          } catch (e) {
            console.log(e)
          }
        }
    
    
        //unload previous sound on every loadAudio call
        useEffect(() => {
          return sound?.current
            ? async () => {
                await sound?.current?.unloadAsync()
                console.log('Unloading Sound')
              }
            : undefined
        }, [sound?.current])
    
    
        useEffect(() => {
          onDataChange()
        }, [data])
    
    
        onDataChange = async () => {
          await loadAudio()
        }
    
    
        loadAudio = async () => {
          try {
            const { isPlaying, volume } = audioPlayerState
            sound.current = new Audio.Sound() // to trigger sound.current useEffect which will unload prev audio
            const fieldName = getValueByKeyString(data[currentIdx], audioFieldName) // because audioFieldName can be nested e.g. 'b.c.e'
            const source = { uri: `${audioBaseUri}/${fieldName}` }
            console.log(source)
            const status = {
              shouldPlay: isPlaying,
              volume: volume,
              progressUpdateIntervalMillis:
                audioPlayerState.progressUpdateIntervalMillis ?? 1000
            }
            sound?.current?.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate)
            await sound?.current?.loadAsync(source, status)
          } catch (e) {
            debugger
            console.log(e)
            alert(JSON.stringify(e))
          }
        }
    
    
        onPlaybackStatusUpdate = async status => {
          if (status.didJustFinish && !status.isLooping) {
            let newIndex = currentIdx < data.length - 1 ? currentIdx + 1 : 0
            // for Learn Quran Tab
            if (onAudioFinishCb) {
              await onAudioFinishCb(newIndex, currentIdx)
              loadAudio()
            }
            // for Read Quran Tab
            else if (onNextOrPreviousPageClick) {
              // if last verse of the page then increment the page
              if (currentIdx === data.length - 1) {
                onNextOrPreviousPageClick(+1)
              }
              // else just increment the verse
              else {
                setCurrentIdx(newIndex)
                flatlistRef?.current?.scrollToIndex({
                  animated: true,
                  index: newIndex
                })
                loadAudio()
              }
            }
          } else {
            setAudioPlayerState({
              ...audioPlayerState,
              isPlaying: status.isPlaying,
              isBuffering: status.isBuffering,
              currentTime: status.positionMillis,
              totalTime: status.durationMillis,
              isLoaded: status.isLoaded
            })
          }
        }
    
        
        handlePlayPause = async () => {
          try {
            const { isPlaying } = audioPlayerState
            if (sound) {
              isPlaying
                ? await sound?.current?.pauseAsync()
                : await sound?.current?.playAsync()
              // set isPlaying to previous status because after unloading, the isPlaying status will change to false
              setAudioPlayerState({
                ...audioPlayerState,
                isPlaying: !isPlaying
              })
            }
          } catch (e) {
            console.log(JSON.stringify(sound.current))
            alert(JSON.stringify(e))
          }
        }
    
    
        unloadSound = async () => {
          const { isPlaying } = audioPlayerState
          if (sound?.current) {
            await sound?.current?.unloadAsync()
            // set isPlaying to previous status because after unloading, the isPlaying status will change to false
            setAudioPlayerState({
              ...audioPlayerState,
              isPlaying: isPlaying
            })
          }
        }
    
    
        MiniAudioPlayer = memo(() => {
          return (
            <View style={styles.container}>
              <View style={styles.controls}>
                {audioPlayerState.isLoaded ? (
                  <View style={[styles.controls, styles.control]}>
                    <CustomIcon
                      iconName={
                        audioPlayerState.isPlaying ? 'ios-pause' : 'ios-play-circle'
                      }
                      iconFamily='Ionicons'
                      iconSize={24}
                      iconColor='white'
                      // iconStyle={styles.control}
                      iconOnPress={handlePlayPause}
                    />
                    {audioPlayerState.isBuffering && (
                      <Loader
                        isLoading
                        // color='white'
                        // style={styles.control}
                        size={34}
                        iconOnly
                        style={styles.buffering}
                      />
                    )}
                  </View>
                ) : (
                  <Loader
                    isLoading
                    color='white'
                    style={styles.control}
                    size={24}
                    iconOnly
                  />
                )}
              </View>
            </View>
          )
        })
    
        return data ? <MiniAudioPlayer /> : null
      }
    )
    
    export default AudioPlayer
artsnr
  • 952
  • 1
  • 10
  • 27

0 Answers0