如何使用ExoPlayer播放URL音频时同步缓存 待URL失效后从缓存播放
ExoPlayer 短有效期URL音频边播边缓存实现方案
要实现临时URL音频边播边存、URL过期后仍可从本地读取缓存播放的需求,直接使用ExoPlayer原生缓存组件即可完成,核心是不要用默认的URL作为缓存key,避免URL过期后匹配不到已有缓存。
实现步骤
1. 自定义缓存Key工厂
因为你的音频URL有效期只有5分钟,不同时间获取的同一音频URL不同,所以需要用音频对应的固定唯一标识(比如后端返回的音频ID)作为缓存key:
class CustomCacheKeyFactory(private val audioUniqueId: String) : CacheKeyFactory { override fun buildCacheKey(dataSpec: DataSpec, mediaItem: MediaItem): String { // 直接返回固定的音频唯一ID作为缓存匹配key return audioUniqueId } }
2. 全局初始化缓存实例
在Application层级初始化单例缓存,避免多实例导致的缓存读写冲突、缓存丢失问题:
class MyApp : Application() { companion object { // 全局缓存实例,最大缓存空间设为100MB,可按需调整 lateinit var exoCache: SimpleCache } override fun onCreate() { super.onCreate() val cacheEvictor = LeastRecentlyUsedCacheEvictor(1024 * 1024 * 100) exoCache = SimpleCache(cacheDir, cacheEvictor) } }
3. 构建带缓存能力的数据源
将HTTP数据源和缓存数据源包装结合,实现边播边写缓存:
// 1. 构建基础HTTP数据源工厂,按需配置UA、请求头等 val httpSourceFactory = DefaultHttpDataSource.Factory() .setUserAgent("your_app_name") // 2. 包装缓存数据源工厂,传入自定义key工厂 val cacheSourceFactory = CacheDataSource.Factory() .setCache(MyApp.exoCache) .setUpstreamDataSourceFactory(httpSourceFactory) // 传入当前播放音频的固定唯一ID .setCacheKeyFactory(CustomCacheKeyFactory(currentAudioId)) .setFlags( CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR or CacheDataSource.FLAG_BLOCK_ON_CACHE )
4. 绑定到ExoPlayer播放
val exoPlayer = ExoPlayer.Builder(context) .setMediaSourceFactory(DefaultMediaSourceFactory(cacheSourceFactory)) .build() // 传入当前的临时音频URL即可 val mediaItem = MediaItem.fromUri(tempAudioUrl) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play()
注意事项
- 只要同一音频的
audioUniqueId不变,哪怕后续URL更新/过期,ExoPlayer会优先读取本地已有缓存,不会发起新的网络请求 - 可通过
MyApp.exoCache.isCached(audioUniqueId, 0, C.LENGTH_UNSET)判断当前音频是否已经完全缓存 - 不要每次播放都新建
SimpleCache实例,必须保持全局单例
内容的提问来源于stack exchange,提问作者Maksym Tsikal
相关产品推荐
相关产品推荐

