背景
项目中文章页是使用的webview + h5
页面。
由于新出的专栏文章页嵌套了一些视频,接到了用户反馈的关于播放器的一些问题。
iOS
点击播放器全屏按钮,视频进入全屏后,大概播放几秒钟之后,会自动退出全屏模式。
实际上在 iOS 中,播放器进入全屏模式下,使用的是 iOS 系统原生的播放器。(业务中我们的播放器 controls 控制条是自己封装的,但在 iOS 全屏模式下,自己封装的控制条其实都看不到了,都是系统的控制条)
原因
初次调试,客户端同学以为是视频格式的问题,由于业务中一直使用的是 .m3u8
格式的视频,尝试换成 .mp4
格式(mp4格式加载缓慢),并没有什么效果。
后来又调试发现,其实不是视频格式的问题。而是业务中使用了第三方的 dsbridge
导致的问题。具体是为啥,还不清楚。
由于项目中H5和客户端通讯,主要使用的就是 dsbridge
,目前也不可能把这个库换掉。
解决方案:
所以和客户端讨论后,最终的方案是,在点击全屏按钮的时候,调用客户端的视频全屏播放功能。
这时候闪退的问题解决了。
但是…..又有新的问题出现了。
偶现,用户进去全屏后,观看一段时间视频,再退出全屏模式,视频进度不准确。但实际上 h5 在收到客户端退出全屏但通知后,就对 video 的 currentTime 做了修改。理论上不会进度不同步。
目前还没有找到解决方法。
import dsbridge from 'dsbridge'
enableFullScreen (videoeData) {
// iOS 点击全屏按钮时,调用客户端的全屏功能
if (this.config.useAppPlayerWhenFullScreen) {
const payload = {
status: videoeData.playing ? 'playing' : 'pause', // 当前的播放状态,playing 播放中, pause 暂停, end 结束全屏
data: {
currentTime: this.player.current, // 当前播放进度
src: this.config.source // 视频资源
}
}
if (dsbridge.hasNativeMethod('article.callAVPlayer')) {
dsbridge.call('article.callAVPlayer', payload, (res) => {
const result = typeof res === 'string' ? JSON.parse(res) : res
const data = result.data || {}
const currentTime = parseInt(data.currentTime)
this.$refs.player.seek(currentTime) // 设置播放器跳到指定播放位置
})
}
}
}
复制代码
安卓
安卓端 非全屏和全屏模式使用的都是 h5的播放器。
然而,h5的播放器在安卓的webview内也是有一些问题的。
第一个问题:进入全屏后,看一段时间后就自动锁屏了(应该是h5 的播放器没有触发系统的常亮功能)。
还好这个问题解决起来比较简单,就是让客户端同学定义一个方法,我在点击全屏的时候,通知客户端,不要熄屏;退出全屏的时候,再告诉客户端,可以恢复正常的熄屏功能。
复制代码
第二个问题:进入全屏后,再退出全屏,页面自动回到顶部了。这个不知道为啥会这样。
解决方案就是,在点击全屏时,记录一下当前屏幕的滚动高度。退出全屏时,再设置当前页面滚动到指定位置,原本以为,这样会有一个闪烁的情况。结果竟然无缝衔接,一点也看不出来是主动设置页面滚动到指定位置,简直完美?
enableFullScreen (videoeData) {
// 点击全屏按钮时,记录当前页面的滚动位置
this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// 安卓进入全屏播放,需要告诉客户端不熄屏
if (dsbridge.hasNativeMethod('common.isKeepScreenOn')) {
dsbridge.call('common.isKeepScreenOn', 'true')
}
},
cancelFullScreen () {
// 安卓退出全屏后,关闭屏幕常亮模式
if (dsbridge.hasNativeMethod('common.isKeepScreenOn')) {
dsbridge.call('common.isKeepScreenOn', 'false')
}
// 由于安卓退出全屏后,默认情况下页面会自动回到顶部,这里需要处理一下
if (utils.isInAndroidApp()) {
document.documentElement.scrollTop = this.scrollTop
document.body.scrollTop = this.scrollTop
}
}
复制代码