所以,这就是问题所在。我在我的反应项目中使用音频 html5 元素。问题的典型流程是:歌曲正在播放。用户在某个时间按下暂停(假设时间是 1.20)。用户锁定手机。几分钟后,用户解锁他的手机,按下“播放”按钮,这里会发生什么:mediaPositionState 将当前时间计算为先前(1.20)加上音频的当前时间,而不是仅计算当前时间。即使更换歌曲,这个额外的 1.20 也会保留。我试图在下面的 useEffect 中控制它
useEffect(() => {
const audioEl = audioRef.current;
if (audioEl) {
audioEl.addEventListener('timeupdate', updateTime);
audioEl.addEventListener('loadeddata', updatePositionState);
}
return () => {
if (audioEl) {
audioEl.removeEventListener('timeupdate', updateTime);
audioEl.removeEventListener('loadeddata', updateTime);
updatePositionState();
}
};
}, []);
但它只有在用户专注于音频时才能正常工作。
我也有以下代码:
function updatePositionState() {
if (navigator.mediaSession?.setPositionState) {
navigator.mediaSession.setPositionState({
duration: audioRef.current?.duration ?? 0.0,
position: audioRef.current?.currentTime ?? 0.0,
});
}
}
const createMediaSession = (state: AudioStateType) => {
if (navigator.mediaSession) {
navigator.mediaSession.metadata = new MediaMetadata({
title: state.currentSongName,
artist: state.currentArtistName,
album: state.currentAlbumName,
artwork: [
{
sizes: '300x300',
src: `http://storage.musicstream.app/cover/${state.currentAlbumCoverId}`,
},
],
});
navigator.mediaSession.setActionHandler('play', function () {
dispatch({ type: 'resume' });
updatePositionState();
});
navigator.mediaSession.setActionHandler('pause', function () {
dispatch({ type: 'pause' });
updatePositionState();
});
navigator.mediaSession.setActionHandler('seekto', function (details) {
dispatch({ type: 'manual_update_time', time: details.seekTime });
updatePositionState();
});
navigator.mediaSession.setActionHandler('previoustrack', () => {
return 0;
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
return 0;
});
}
};
我不知道如何正常描述这个问题,让我们假设当用户刷出 MediaSession 通知时,mediaposition 搞砸了。如果你问,我会提供更多代码。我还提供了屏幕截图(尽管我试图强制出现类似的问题:它将时间显示为曲目的结尾)。
通过请求添加 updateTime 函数仅用于更新 react.Context 中的状态
const updateTime = () => {
if (audioRef.current) {
dispatch({ type: 'update_time', time: audioRef.current.currentTime });
}
};
此外,完整的减速器看起来像这样(我认为这不会有帮助):
function audioReducer(state: AudioStateType, action: Action): AudioStateType {
switch (action.type) {
case 'fetch_and_play': {
play(action.songData?.currentSongId).then(() => {
dispatch({
type: 'play',
songData: {
...action.songData,
length: audioRef.current?.duration,
},
});
});
return state;
}
case 'play': {
createMediaSession({ ...state, ...action.songData });
return { ...state, ...action.songData };
}
case 'pause': {
pause();
return { ...state, songIsPaused: true };
}
case 'resume': {
resume();
return { ...state, songIsPaused: false };
}
case 'update_time': {
return { ...state, currentTime: action.time };
}
case 'manual_update_time': {
if (audioRef.current) {
audioRef.current.currentTime = action.time;
return { ...state, currentTime: action.time };
} else {
return state;
}
}
default: {
return state;
}
}
}
我制作了一个代码框,您可以在其中看到我的问题。https://codesandbox.io/s/wizardly-wiles-87qi1?file=/src/App.js 为了真正理解请使用安卓手机