ExoPlayer,泛化 SimpleCache 行为
ExoPlayer, generalize SimpleCache behaviour
我正在使用 ExoPlayer 2 播放来自网络的音乐。现在我想用漂亮的SimpleCache
class来缓存下载的音乐。我的问题如下:每次我请求播放歌曲时,服务器 returns 都会给我一个不同的 URL(也是同一首歌曲),它被 SimpleCache
用作密钥。因此,SimpleCache
为每个 URL 创建一个新的缓存文件(即同一首歌曲的不同文件)。
如果有一种方法可以询问我为特定 url 生成的缓存文件的密钥是什么,那就太好了。你知道这样做的方法吗?
SimpleCache
class 是 final
,所以我不能覆盖它的方法。
编辑,粗略的解决方案:
我创建了一个 CacheDataSource
的副本,并在方法 open(DataSpec)
中更改了这一行,它负责生成密钥:
key = dataSpec.key != null ? dataSpec.key : uri.toString();
由于一些 uri
的参数,我可以生成相同的密钥,这些参数对于为同一首歌曲检索的每个 url 都是相等的。这个解决方案解决了我的问题,但并不是对所有可能的情况都如此通用和可利用。
CacheDataSource
已按照 this comment 中的说明使用:
private DataSource.Factory buildDataSourceFactory(final boolean useBandwidthMeter) {
return new DataSource.Factory() {
@Override
public DataSource createDataSource() {
LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(100 * 1024 * 1024);
SimpleCache simpleCache = new SimpleCache(new File(getCacheDir(), "media_cache"), evictor);
return new CacheDataSource(
simpleCache,
buildMyDataSourceFactory(useBandwidthMeter).createDataSource(),
CacheDataSource.FLAG_BLOCK_ON_CACHE,
10 * 1024 * 1024
);
}
};
}
private DefaultDataSource.Factory buildMyDataSourceFactory(boolean useBandwidthMeter) {
return new DefaultDataSourceFactory(PlayerActivity.this, userAgent, useBandwidthMeter ? BANDWIDTH_METER : null);
}
这是解决方案(在 exoplayer 2.10.2 上工作,但不确定是否适用于早期版本)。
要创建您的来源:
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, getString(R.string.app_name)));
CacheDataSourceFactory cacheDataSourceFactory =
new CacheDataSourceFactory(downloadUtil.getDownloadCache(context), dataSourceFactory,
new FileDataSourceFactory(),
new CacheDataSinkFactory(downloadUtil.getDownloadCache(context), CacheDataSink.DEFAULT_FRAGMENT_SIZE),
0,null,new CacheKeyProvider());
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory).createMediaSource(your_uri);
其中 CacheKeyProvider()
是您自己实现的 CacheKeyFactory
。 class 将定义将用作密钥的内容。我的看起来像这样:
public class CacheKeyProvider implements CacheKeyFactory
{
@Override
public String buildCacheKey(DataSpec dataSpec) {
if (dataSpec.key!=null) return dataSpec.key;
else return generate_key(dataSpec.uri);
}
private String generate_key(Uri uri){
String string = uri.toString();
String[] parts = string.split("\?");
String part1 = parts[0];
String part2 = parts[1];
return part1;
}
}
在我的例子中,当我的 url 发生变化时,我正在检索任何没有改变的东西,并将其用作密钥。
从 ExoPlayer 2.10.0 开始,它添加了 ProgressiveMediaSource
class,它取代了 ExtractorMediaSource
(已弃用)。
使用 Factory
class 创建 ProgressiveMediaSource 时,您可以调用方法 setCustomCacheKey(String)
.
它正是我所需要的!
我正在使用 ExoPlayer 2 播放来自网络的音乐。现在我想用漂亮的SimpleCache
class来缓存下载的音乐。我的问题如下:每次我请求播放歌曲时,服务器 returns 都会给我一个不同的 URL(也是同一首歌曲),它被 SimpleCache
用作密钥。因此,SimpleCache
为每个 URL 创建一个新的缓存文件(即同一首歌曲的不同文件)。
如果有一种方法可以询问我为特定 url 生成的缓存文件的密钥是什么,那就太好了。你知道这样做的方法吗?
SimpleCache
class 是 final
,所以我不能覆盖它的方法。
编辑,粗略的解决方案:
我创建了一个 CacheDataSource
的副本,并在方法 open(DataSpec)
中更改了这一行,它负责生成密钥:
key = dataSpec.key != null ? dataSpec.key : uri.toString();
由于一些 uri
的参数,我可以生成相同的密钥,这些参数对于为同一首歌曲检索的每个 url 都是相等的。这个解决方案解决了我的问题,但并不是对所有可能的情况都如此通用和可利用。
CacheDataSource
已按照 this comment 中的说明使用:
private DataSource.Factory buildDataSourceFactory(final boolean useBandwidthMeter) {
return new DataSource.Factory() {
@Override
public DataSource createDataSource() {
LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(100 * 1024 * 1024);
SimpleCache simpleCache = new SimpleCache(new File(getCacheDir(), "media_cache"), evictor);
return new CacheDataSource(
simpleCache,
buildMyDataSourceFactory(useBandwidthMeter).createDataSource(),
CacheDataSource.FLAG_BLOCK_ON_CACHE,
10 * 1024 * 1024
);
}
};
}
private DefaultDataSource.Factory buildMyDataSourceFactory(boolean useBandwidthMeter) {
return new DefaultDataSourceFactory(PlayerActivity.this, userAgent, useBandwidthMeter ? BANDWIDTH_METER : null);
}
这是解决方案(在 exoplayer 2.10.2 上工作,但不确定是否适用于早期版本)。 要创建您的来源:
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, getString(R.string.app_name)));
CacheDataSourceFactory cacheDataSourceFactory =
new CacheDataSourceFactory(downloadUtil.getDownloadCache(context), dataSourceFactory,
new FileDataSourceFactory(),
new CacheDataSinkFactory(downloadUtil.getDownloadCache(context), CacheDataSink.DEFAULT_FRAGMENT_SIZE),
0,null,new CacheKeyProvider());
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory).createMediaSource(your_uri);
其中 CacheKeyProvider()
是您自己实现的 CacheKeyFactory
。 class 将定义将用作密钥的内容。我的看起来像这样:
public class CacheKeyProvider implements CacheKeyFactory
{
@Override
public String buildCacheKey(DataSpec dataSpec) {
if (dataSpec.key!=null) return dataSpec.key;
else return generate_key(dataSpec.uri);
}
private String generate_key(Uri uri){
String string = uri.toString();
String[] parts = string.split("\?");
String part1 = parts[0];
String part2 = parts[1];
return part1;
}
}
在我的例子中,当我的 url 发生变化时,我正在检索任何没有改变的东西,并将其用作密钥。
从 ExoPlayer 2.10.0 开始,它添加了 ProgressiveMediaSource
class,它取代了 ExtractorMediaSource
(已弃用)。
使用 Factory
class 创建 ProgressiveMediaSource 时,您可以调用方法 setCustomCacheKey(String)
.
它正是我所需要的!