我已经在
ExoPlayer
中搜索了缓存,但我既不理解它们,也无法正确实现它们。
在这个关于 在 Exoplayer 中使用缓存的问题中有一些带有示例代码的答案。 第一个答案我无法实现它是在示例代码的第二部分中,它说使用类
DefaultHttpDataSourceFactory
,我认为它是用类DefaultHttpDataSource.Factory()
更改的,这似乎不是什么大问题但我面临的主要问题是这行代码
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
SimpleExoPlayer exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
MediaSource audioSource = new ExtractorMediaSource(Uri.parse(url),
new CacheDataSourceFactory(context, 100 * 1024 * 1024, 5 * 1024 * 1024), new DefaultExtractorsFactory(), null, null);
exoPlayer.setPlayWhenReady(true);
exoPlayer.prepare(audioSource);
这说使用类
ExtractorMediaSource
,但没有这个名称的类,我什至在exoplayer文档的已弃用类中没有找到。 exoplayer 在 2.18.0 版本中几乎所有内容都发生了变化。例如,我们应该为exoplayer设置MediaSource
的部分现在被分为两部分:
final DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, "agent name"); //part one
final ProgressiveMediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory(dataSourceFactory); //part two
我希望您已经看到了此解决方案的差异和我的问题
现在下一个解决方案及其问题:
这位亲爱的朋友建议使用这个库,这听起来不错,并且解决了我的问题,但这个依赖项
compile 'com.danikula:videocache:2.7.1'
实际上所做的是下载视频并将其保存在应用程序文件夹中。由于 android Pie(9)
以及谷歌和 Android 手机制造商的新隐私政策,他们不允许访问应用程序文件夹。
Kotlin 中的其他解决方案也存在同样的问题,exoplayer 中的类丢失了。
我想要什么
我想在 exoplayer2 中使用缓存(或 exoplayer2 的缓存),例如
Glide
将图像保存在应用程序缓存中我想为我的 exoplayer2 实现类似的功能,我几乎到处搜索过。
注意:我使用
ExoPlayer
的这些依赖项:
implementation 'com.google.android.exoplayer:exoplayer-core:2.18.0'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.18.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.18.0'
implementation 'com.google.android.exoplayer:exoplayer:2.18.0'
我已经完成了我的应用程序,只需要弄清楚它的这一部分。
const val CACHE_DIR_NAME = "cached_audio"
const val MAX_CACHE_SIZE = 256 * 1024 * 1024L//256MB
class MediaCache private constructor(context: Context) {
val cacheFactory: CacheDataSource.Factory
init {
cacheFactory = setupExoPlayerCache(context)
}
companion object {
@Volatile
private lateinit var instance: MediaCache
fun getInstance(context: Context): MediaCache {
synchronized(this) {
if (!::instance.isInitialized) {
instance = MediaCache(context)
}
return instance
}
}
}
@SuppressLint("UnsafeOptInUsageError")
private fun setupExoPlayerCache(context: Context): CacheDataSource.Factory {
val cacheEvictor = LeastRecentlyUsedCacheEvictor(MAX_CACHE_SIZE)
val databaseProvider = StandaloneDatabaseProvider(context)
val cache = SimpleCache(
File(context.cacheDir, CACHE_DIR_NAME),
cacheEvictor, databaseProvider
)
val upstreamFactory = DefaultDataSource.Factory(context)
return CacheDataSource.Factory().apply {
setCache(cache)
setUpstreamDataSourceFactory(upstreamFactory)
setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
}
}
}
然后在任何地方将媒体源传递给 exoplayer:
val mediaItem = MediaItem.fromUri(uri)
val mediaSourceFactory =
ProgressiveMediaSource.Factory(MediaCache.getInstance(this@PlaybackService).cacheFactory)
val mediaSource = mediaSourceFactory.createMediaSource(mediaItem)
player.setMediaSource(mediaSource, true)
使用 Builder 类创建播放器对象并将 MediaSourceFactory 设置为缓存,如下所示:
val databaseProvider = StandaloneDatabaseProvider(context)
context.getExternalFilesDir("voice/$artistId/$albumNumber")?.let {
simpleCache = SimpleCache(
it,
NoOpCacheEvictor(),
databaseProvider
)
val defaultDataSourceFactory = DefaultDataSource.Factory(context)
val cacheDataSourceFactory = CacheDataSource.Factory()
.setCache(simpleCache!!)
.setUpstreamDataSourceFactory(defaultDataSourceFactory)
player = ExoPlayer
.Builder(context)
.setMediaSourceFactory(DefaultMediaSourceFactory(cacheDataSourceFactory))
.build()
} ?: kotlin.run {
player = ExoPlayer.Builder(context).build()
}