Android MediaPlayer的onBufferingUpdate()仅返回100%缓冲问题处理
问题原因
- 代码逻辑存在拦截限制:你在
onBufferingUpdate回调中自定义了buffered布尔标记,第一次回调触发后就将标记置为true,后续所有缓冲更新事件都会被拦截,自然只能拿到第一次返回的100数值。 - 系统播放器兼容性问题:不同Android版本、不同厂商ROM对
MediaPlayer的缓冲回调实现逻辑存在差异,部分流媒体源(如HLS分片流)未携带Content-Length响应头时,MediaPlayer无法计算总文件大小,默认返回100作为缓冲百分比数值。 - VideoView封装限制:
VideoView内部对MediaPlayer的回调做了封装拦截,部分场景下会吞掉中间阶段的缓冲更新事件,仅在缓冲全量完成时才会将回调透传到上层。
实时获取缓冲进度的优化方案
1 修复现有代码逻辑
首先移除回调中的单次触发限制,允许接收所有缓冲更新事件,修改后的参考代码如下:
vw1.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { // 原有播放逻辑保留 if (mCurrentPosition > 0) { vw1.seekTo(mCurrentPosition); } else { vw1.seekTo(1); } vw1.start(); // 移除buffered单次触发标记 mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { @Override public void onBufferingUpdate(MediaPlayer mediaPlayer, int percent) { long t1 = System.currentTimeMillis(); mBufferingTextView.setText((t1 - t0) + ", 缓冲进度:" + percent + "%"); } }); } });
2 兼容特殊场景的通用方案
如果修复代码后依然只能拿到100%的缓冲数值,改用手动轮询的方式计算缓冲进度,兼容性覆盖绝大多数场景:
- 启动一个间隔1s的定时任务,播放过程中周期性调用
MediaPlayer的三个接口:getDuration()获取视频总时长、getCurrentPosition()获取当前播放位置、getBufferedPosition()获取已缓冲的最大时间位置 - 缓冲百分比计算公式:
int bufferPercent = (int) (mediaPlayer.getBufferedPosition() * 100f / mediaPlayer.getDuration()); - 播放结束、页面销毁时需要及时停止定时任务,避免内存泄漏。
3 高稳定性方案(推荐)
如果业务对播放兼容性要求较高,直接替换系统MediaPlayer+VideoView的实现,改用谷歌官方开源的ExoPlayer,自带AnalyticsListener监听接口,可直接获取实时缓冲进度、加载耗时、缓冲带宽等全量播放数据,适配绝大多数流媒体格式,不会出现系统播放器的兼容性问题。
内容的提问来源于stack exchange,提问作者angel_30
相关产品推荐
相关产品推荐

