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

ExoPlayer 2.18.0版本实现类Glide视频缓存功能问题咨询

ExoPlayer 2.18.0 本地缓存实现方案

你遇到的类缺失、API不匹配问题均来自ExoPlayer大版本迭代的API重构,2.18版本已经完全移除了旧版的ExtractorMediaSource、ExoPlayerFactory、旧版DataSourceFactory相关类,直接按以下步骤实现即可达到类Glide的自动缓存效果,缓存文件存储在应用专属缓存目录,完全适配Android 9+隐私规则,无需额外申请存储权限,也不需要引入第三方缓存库。


前置说明

你当前引入的ExoPlayer依赖已经包含所有缓存相关模块,无需新增依赖。第三方AndroidVideoCache库已停止维护多年,存在系统兼容、代理冲突等问题,不建议使用,直接用ExoPlayer官方自带的缓存实现即可。

第一步:初始化全局唯一缓存实例

SimpleCache实例必须全局单例,重复创建会触发文件锁冲突、缓存失效甚至崩溃,在自定义Application类中完成初始化:

Kotlin 实现

class MyApp : Application() {
    companion object {
        // 可自行调整缓存上限,示例设置为1GB
        private const val MAX_CACHE_SIZE = 1024 * 1024 * 1024L
        lateinit var videoCache: SimpleCache
            private set
    }

    override fun onCreate() {
        super.onCreate()
        // 缓存目录放在应用私有缓存路径下,无权限问题
        val cacheDir = File(cacheDir, "exo_video_cache")
        if (!cacheDir.exists()) cacheDir.mkdirs()
        // 采用LRU淘汰策略,超出缓存上限自动删除最久未使用的缓存文件
        val evictor = LeastRecentlyUsedCacheEvictor(MAX_CACHE_SIZE)
        val dbProvider = StandaloneDatabaseProvider(this)
        videoCache = SimpleCache(cacheDir, evictor, dbProvider)
    }
}

Java 实现

public class MyApp extends Application {
    private static final long MAX_CACHE_SIZE = 1024 * 1024 * 1024L;
    private static SimpleCache videoCache;

    @Override
    public void onCreate() {
        super.onCreate();
        File cacheDir = new File(getCacheDir(), "exo_video_cache");
        if (!cacheDir.exists()) cacheDir.mkdirs();
        CacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(MAX_CACHE_SIZE);
        DatabaseProvider dbProvider = new StandaloneDatabaseProvider(this);
        videoCache = new SimpleCache(cacheDir, evictor, dbProvider);
    }

    public static SimpleCache getVideoCache() {
        return videoCache;
    }
}

初始化完成后,记得在AndroidManifest.xml的<application>标签下添加android:name=".MyApp"属性,保证应用启动时初始化缓存实例。

第二步:构造支持缓存的数据源工厂

替换旧示例中已经废弃的CacheDataSourceFactory,按新版API构造带缓存逻辑的数据源:

Kotlin 实现

// 基础网络数据源
val httpDataSourceFactory = DefaultHttpDataSource.Factory()
    .setUserAgent("your-app-name")
    .setAllowCrossProtocolRedirects(true)
// 包装为缓存数据源
val cachedDataSourceFactory = CacheDataSource.Factory()
    .setCache(MyApp.videoCache)
    .setUpstreamDataSourceFactory(httpDataSourceFactory)
    // 缓存策略:优先读取本地缓存,缓存不存在时拉取网络并自动写入缓存,缓存读取失败时自动回退到网络请求
    .setFlags(CacheDataSource.FLAG_BLOCK_ON_CACHE or CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)

Java 实现

DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory()
        .setUserAgent("your-app-name")
        .setAllowCrossProtocolRedirects(true);
CacheDataSource.Factory cachedDataSourceFactory = new CacheDataSource.Factory()
        .setCache(MyApp.getVideoCache())
        .setUpstreamDataSourceFactory(httpDataSourceFactory)
        .setFlags(CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);

第三步:初始化播放器、构造媒体源

旧版ExtractorMediaSource已被ProgressiveMediaSource替代,对应普通MP4、MOV等渐进式视频的播放逻辑如下:

Kotlin 实现

// 初始化轨道选择器
val trackSelector = DefaultTrackSelector(this)
// 2.18版本直接通过Builder构造ExoPlayer,无需旧版ExoPlayerFactory
val player = ExoPlayer.Builder(this)
    .setTrackSelector(trackSelector)
    .build()
// 构造带缓存的媒体源
val mediaSource = ProgressiveMediaSource.Factory(cachedDataSourceFactory)
    .createMediaSource(MediaItem.fromUri(yourVideoUrl))
// 绑定播放器到控件、准备播放
playerView.player = player
player.setPlayWhenReady(true)
player.setMediaSource(mediaSource)
player.prepare()

Java 实现

DefaultTrackSelector trackSelector = new DefaultTrackSelector(this);
ExoPlayer player = new ExoPlayer.Builder(this)
        .setTrackSelector(trackSelector)
        .build();
MediaSource mediaSource = new ProgressiveMediaSource.Factory(cachedDataSourceFactory)
        .createMediaSource(MediaItem.fromUri(Uri.parse(yourVideoUrl)));
playerView.setPlayer(player);
player.setPlayWhenReady(true);
player.setMediaSource(mediaSource);
player.prepare();

如果需要播放DASH流媒体,只需要把ProgressiveMediaSource.Factory替换为DashMediaSource.Factory即可,缓存逻辑完全通用。


注意事项

  • 缓存逻辑和Glide完全一致:相同URL的视频第二次播放时会直接读取本地缓存,不会重复发起网络请求。
  • 不要重复创建SimpleCache实例,否则会触发文件锁异常,导致缓存失效、播放崩溃。
  • 如果需要实现视频预加载、秒开功能,可以使用CacheWriter提前将视频片段写入缓存,后续播放时直接读取本地文件。
  • 不需要为缓存申请任何存储权限,应用私有目录的读写在所有Android版本上都不受隐私政策限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:24:21