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

列表中实现VideoView播放.m3u8视频时滚动触发MediaPlayer异常求助

解决VideoView加载.m3u8滚动列表时的FileNotFoundException问题

我之前在开发列表视频播放功能时也踩过这个坑,咱们来拆解一下问题和解决办法:

为什么会出现这个错误?

Android原生的VideoView底层依赖的MediaPlayer对HLS(.m3u8)这种流媒体格式的支持非常有限,尤其是在旧版本系统上。另外当列表滚动触发视图复用时,旧的VideoView实例可能没有正确释放资源,导致新的数据源设置时出现ContentResolver无法识别HTTPS流媒体路径的错误——毕竟ContentResolver主要是用来处理本地内容或系统内置内容提供者的,不是为网络流媒体设计的。

解决方案推荐

1. 替换为ExoPlayer(最靠谱的方案)

Google官方推荐用ExoPlayer来处理各种流媒体格式,包括HLS,它的兼容性和稳定性都比原生VideoView好太多。

  • 首先添加依赖(在app的build.gradle里):
implementation "com.google.android.exoplayer:exoplayer-core:2.X.X"
implementation "com.google.android.exoplayer:exoplayer-hls:2.X.X" // HLS支持模块

(注:把2.X.X替换成最新版本号)

  • 布局里用PlayerView替代VideoView:
<com.google.android.exoplayer2.ui.PlayerView
    android:id="@+id/player_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
  • 在Adapter的ViewHolder里初始化和管理ExoPlayer:
public class VideoViewHolder extends RecyclerView.ViewHolder {
    private PlayerView playerView;
    private SimpleExoPlayer player;

    public VideoViewHolder(View itemView) {
        super(itemView);
        playerView = itemView.findViewById(R.id.player_view);
    }

    public void bind(String videoUrl) {
        // 初始化ExoPlayer
        if (player == null) {
            player = new SimpleExoPlayer.Builder(itemView.getContext()).build();
            playerView.setPlayer(player);
        }
        // 准备HLS媒体源
        MediaItem mediaItem = MediaItem.fromUri(videoUrl);
        player.setMediaItem(mediaItem);
        player.prepare();
        // 可选:自动播放
        // player.play();
    }

    // 回收时释放资源
    public void release() {
        if (player != null) {
            player.release();
            player = null;
        }
    }
}
  • 在Adapter里重写视图回收方法:
@Override
public void onViewRecycled(@NonNull VideoViewHolder holder) {
    super.onViewRecycled(holder);
    holder.release();
}

2. 如果你非要用VideoView(不推荐)

如果因为某些原因必须用VideoView,那要做好资源释放和格式兼容处理:

  • 首先,在Android 4.1+系统上,原生MediaPlayer有限支持HLS,但需要确保视频的编码格式是系统支持的。
  • 然后,在列表视图回收时必须彻底释放VideoView的资源:
@Override
public void onViewRecycled(@NonNull VideoViewHolder holder) {
    super.onViewRecycled(holder);
    holder.videoView.stopPlayback();
    holder.videoView.setVideoURI(null); // 清空数据源
}
  • 另外,加载视频时可以尝试用Uri.parse()来处理路径,而不是直接传字符串:
holder.videoView.setVideoURI(Uri.parse(videoUrl));

3. 基础配置检查

  • 确保manifest里已经申请了网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
  • 如果是Android 9(API 28)及以上,检查是否允许明文网络(如果你的m3u8是HTTPS的话其实不需要,但如果是HTTP的话需要):
    在manifest的application标签里添加:
android:usesCleartextTraffic="true"

这样处理后,滚动列表时的错误应该就能解决了,优先推荐用ExoPlayer,毕竟原生VideoView在流媒体场景下的局限性太大了。

内容的提问来源于stack exchange,提问作者Vikramsinh Gaikwad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:40:07