EXPO AV HOOK HELP
Hey guys, so I'm busy implementing a slider for expo av, but on android, I encounter this weird bug where for a random x amount of seconds the players' position just doesn't update but the audio still plays and after x seconds everything works again.
Here's a hook I created, maybe someone can help me out a bit
```
import { useEffect, useState, useRef, useCallback } from 'react';
import { Sound } from 'expo-av/build/Audio/Sound';
import { Audio, AVPlaybackStatus } from 'expo-av';
/**
* Poll for track progress for the given interval (in miliseconds)
* @param interval - ms interval
*/
type PlayerStatus = 'PLAYING' | 'PAUSED' | 'BUFFERING' | 'ERROR' | 'LOADING';
interface ProgressState {
status: PlayerStatus;
position: number;
duration: number;
}
// eslint-disable-next-line import/prefer-default-export
export function usePlayer(updateInterval?: number) {
const [state, setState] = useState<ProgressState>({
position: 0,
duration: 0,
status: 'LOADING',
});
const playerRef = useRef<Sound | null>(new Audio.Sound());
const stateRef = useRef(state); // Helps keep track of previous state
const isUnmountedRef = useRef(true);
useEffect(() => {
isUnmountedRef.current = false;
return () => {
console.log('unmount');
isUnmountedRef.current = true;
};
}, []);
const handlePlayBackStateChange = useCallback((playbackStatus: AVPlaybackStatus) => {
if (!playbackStatus.isLoaded) {
// Update your UI for the unloaded state
if (playbackStatus.error) {
console.log(`Encountered a fatal error during playback: ${playbackStatus.error}`);
}
} else {
// Update your UI for the loaded state
let duration = 0;
if (playbackStatus.durationMillis) duration = playbackStatus.durationMillis / 1000; // The duration of the media in milliseconds
const position = playbackStatus.positionMillis / 1000; // The current position of the media in milliseconds
if (playbackStatus.isPlaying) {
// Update your UI for the playing state
if (
position === stateRef.current.position &&
duration === stateRef.current.duration &&
stateRef.current.status === 'PLAYING'
)
return;
setState({ position, duration, status: 'PLAYING' });
} else {
// Update your UI for the paused state
if (
position === stateRef.current.position &&
duration === stateRef.current.duration &&
stateRef.current.status === 'PAUSED'
)
return;
setState({ position, duration, status: 'PAUSED' });
}
if (playbackStatus.isBuffering) {
// Update your UI for the buffering state
}
if (playbackStatus.didJustFinish && !playbackStatus.isLooping) {
// The player has just finished playing and will stop. Maybe you want to play something else?
}
}
}, []);
useEffect(() => {
if (playerRef.current) {
playerRef.current.setOnPlaybackStatusUpdate(handlePlayBackStateChange);
playerRef.current.setProgressUpdateIntervalAsync(updateInterval || 1000);
} else {
console.log('not loaded');
playerRef.current = new Audio.Sound();
playerRef.current.setProgressUpdateIntervalAsync(updateInterval || 1000);
playerRef.current.setOnPlaybackStatusUpdate(handlePlayBackStateChange);
}
return () => {
playerRef.current?.setOnPlaybackStatusUpdate(null);
};
}, [handlePlayBackStateChange, updateInterval]);
const loadAudio = useCallback(async (uri: string): Promise<boolean> => {
if (isUnmountedRef.current) return false;
playerRef.current?.unloadAsync();
const loadAUdio = await playerRef.current?.loadAsync({
uri,
});
return loadAUdio?.isLoaded;
}, []);
const playAudio = useCallback(async () => {
if (isUnmountedRef.current) return;
await playerRef.current?.playAsync();
}, []);
const pauseAudio = useCallback(async () => {
if (isUnmountedRef.current) return;
await playerRef.current?.pauseAsync();
}, []);
const reset = useCallback(async () => {
if (isUnmountedRef.current) return;
isUnmountedRef.current = true;
await playerRef.current?.unloadAsync();
}, []);
const seekAudio = useCallback(async (position: number) => {
try {
if (isUnmountedRef.current) return;
await playerRef.current?.setPositionAsync(position);
} catch (error) {
console.log('🚀 ~ file: audioPlayer.ts ~ line 201 ~ seekAudio ~ error', error);
}
}, []);
return {
state,
loadAudio,
playAudio,
pauseAudio,
seekAudio,
reset,
};
}
```