iOS 中页面隐藏和显示时,播放audio行为异常
原因:在某些iOS版本中【iOS12.0.1亲测有坑】,当我们监听页面隐藏和显示事件,在隐藏时调用pause() 暂停,显示时调用play()恢复播放。当 按下home键,页面进入系统后台时
,pause()正常调用,audio被正常暂停,但是但再次进入页面,显示事件中调用play()就会出现异常了,
第一种异常,如果,我们只是单纯的调用 audioElem.play()
,不会抛出任何错误,但是audio实际却没有真正播放,无任何声音;
第二种异常,如果我们每次在显示事件中执行如下代码中任意一种场景,都会在很多情况下会抛出一个 AbortError
异常,极少数情况才会正常播放。
//监听页面显示隐藏事件
addPageVisibilityListener(() => {
// 隐藏时暂停
audioElem.pause()
},() => {
// 显示时恢复播放
// 重新直接赋值src
audioElem.src = "https://b.mp3"
audioElem.play()
// 或者load
// audioElem.load()
// audioElem.play()
})
复制代码
解决:这两种异常行为应该都是iOS 12.0.1系统本身的bug。我们可以通过如下2中方式来避免这种两种异常的发生,
方式1, 显示load(),并监听canplaythrough,推荐使用这种方式
const playAudio = () => {
audioElem1.removeEventListener('canplaythrough', playAudio)
let p = audioElem.play()
if (p !== undefined) {
p.catch((e) => {
console.log(e)
})
}
}
//监听页面显示隐藏事件
addPageVisibilityListener(() => {
// 隐藏时暂停
audioElem.pause()
},() => {
// 显示时恢复播放
audioElem.load()
audioElem.addEventListener('canplaythrough', playAudio)
})
复制代码
方式2,通过setTimeout以及retry来hack避免这种异常发生
let playAudio = (retry: boolean) => {
let p = audioElem.play();
if (p !== undefined) {
p.catch((e) => {
if (retry) {
setTimeout(() => {
playAudio(false);
}, 0);
}
});
}
}
//监听页面显示隐藏事件
addPageVisibilityListener(() => {
// 隐藏时暂停
audioElem.pause()
},() => {
// 显示时恢复播放
setTimeout(() => {
playAudio(true)
}, 500)
})
复制代码