Я реализовал собственный кеш для Exoplayer2 - и перехожу с 2.11.x на 2.12.3. Я просмотрел несколько сообщений здесь, посвященных SO (например, здесь), а также различные части из последние версии документации разработчика Exoplayer2 (например, здесь). Я могу получить потоковое видео из локального или удаленного источника (например, Dropbox), и оно воспроизводится, но я не вижу, чтобы в папке, которую я назначил в качестве моего кеша, сохраняется что-либо, кроме двух файлов (и оба файла очень маленький):
5eedc471fe18491e.uid
cached_content_index.exi
Я предполагаю, что файл .exi - это индекс, который должен отслеживать сегменты кеша, а файл .uid - это сегмент, но он всегда равен 0 байтам. Так что по какой-то причине Exoplayer распознает расположение кеша, но ничего не передает в него.
В своем приложении я делаю так:
MediaSource mediaSource = getCachedMediaSourceFactory(context, listener).createMediaSource(uri);
exoPlayer.setMediaSource(mediaSource);
exoPlayer.setPlayWhenReady(true);
exoPlayer.prepare();
getCachedMediaSourceFactory () в свою очередь выглядит так:
private static ProgressiveMediaSource.Factory getCachedMediaSourceFactory(Context context, CacheDataSource.EventListener listener) {
if ( cachedMediaSourceFactory == null ) {
cachedMediaSourceFactory = new ProgressiveMediaSource.Factory(
new InTouchCacheDataSourceFactory(context,
DEFAULT_MEDIA_CACHE_FRAGMENT_SIZE_IN_BYTES,
listener));
}
return cachedMediaSourceFactory;
}
InTouchCacheDataSourceFactory, в свою очередь, выглядит так:
public class InTouchCacheDataSourceFactory implements DataSource.Factory {
private final DefaultDataSourceFactory defaultDatasourceFactory;
private final CacheDataSource.EventListener listener;
private final long maxCacheFragmentSize;
public InTouchCacheDataSourceFactory(Context context, long maxCacheFragmentSize) {
this(context, maxCacheFragmentSize, null);
}
public InTouchCacheDataSourceFactory(Context context, long maxCacheFragmentSize, CacheDataSource.EventListener listener) {
this.maxCacheFragmentSize = maxCacheFragmentSize;
this.listener = listener;
defaultDatasourceFactory =
new DefaultDataSourceFactory(context,
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, APP_NAME)));
}
@Override
public DataSource createDataSource() {
return new CacheDataSource(InTouchUtils.getMediaCache(),
defaultDatasourceFactory.createDataSource(),
new FileDataSource(),
new CacheDataSink(InTouchUtils.getMediaCache(), maxCacheFragmentSize),
CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR,
listener);
}
}
А InTouchUtils.getMediaCache выглядит так:
public static SimpleCache getMediaCache() {
if ( mediaCache == null ) {
Context context = InTouch.getInstance().getApplicationContext();
long requestedCacheSize = Long.parseLong(PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.pref_default_cache_size_key), String.valueOf(DEFAULT_MEDIA_CACHE_SIZE_IN_MB)));
File contentDirectory = new File(context.getCacheDir(), MEDIA_CACHE_DIRECTORY);
mediaCache = new SimpleCache(contentDirectory, new LeastRecentlyUsedCacheEvictor(requestedCacheSize*(1024*1024)));
}
return mediaCache;
}
Опять же, видео воспроизводится нормально, но, похоже, на самом деле потоковый файл не записывается в кеш. Почему нет?
Я также реализовал интерфейс CacheDataSource.EventListener
в своем приложении и переопределил эти два метода:
@Override
public void onCachedBytesRead(long cacheSizeBytes, long cachedBytesRead) {
Timber.d("Lifecycle: Cache read, size in bytes is: %d, bytes read was: %d", cacheSizeBytes, cachedBytesRead);
}
@Override
public void onCacheIgnored(int reason) {
switch (reason) {
case CacheDataSource.CACHE_IGNORED_REASON_ERROR:
Timber.d("Lifecycle: Cache ignored due to error");
break;
case CacheDataSource.CACHE_IGNORED_REASON_UNSET_LENGTH:
Timber.d("Lifecycle: Cache ignored due to unset length");
break;
}
}
Я не вижу вызова ни одного из методов.