You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 01:45:00