#android #caching #video-streaming #exoplayer #exoplayer2.x
#Android #кэширование #потоковое видео #exoplayer #exoplayer2.x
Вопрос:
Я пытаюсь транслировать видео с URL-адресов и одновременно сохранять их в кэше.
Я использую DataBaseInspector Android Studio для проверки кэша, и, похоже, он работает, но не все время.
Иногда у меня возникает эта ошибка при попытке воспроизвести видео :
2021-01-21 10:27:12.956 26648-28069/test.com.test E/ExoPlayerImplInternal: Playback error
com.google.android.exoplayer2.ExoPlaybackException: Source error
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:554)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:238)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.io.IOException: DummyDataSource cannot be opened
at com.google.android.exoplayer2.upstream.DummyDataSource.open(DummyDataSource.java:39)
at com.google.android.exoplayer2.upstream.cache.CacheDataSource.openNextSource(CacheDataSource.java:764)
at com.google.android.exoplayer2.upstream.cache.CacheDataSource.open(CacheDataSource.java:579)
at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1017)
at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
При чтении ошибки мы видим исключение IOException, поэтому я проверил путь в кэше, и снова он иногда работает… Ключи, которые я регистрирую во внутренней базе данных exoplayer, — это URL-адреса (я позволяю exoplayer выполнять всю работу, но после я проверил себя).
Вот мой код :
@Inject
public VideoCacheManager(@NonNull SimpleCache simpleCache, @ActivityContext Context context) {
this.simpleCache = simpleCache;
this.context = context;
cacheDataSource = new CacheDataSource.Factory();
cacheDataSource.setCache(simpleCache);
Log.d(TAG, "VideoCacheManager: cache size left : " simpleCache.getCacheSpace());
cacheDataSource.setEventListener(new CacheDataSource.EventListener() {
@Override
public void onCachedBytesRead(long cacheSizeBytes, long cachedBytesRead) {
Log.d(TAG, "onCachedBytesRead: cached bytes read : " cachedBytesRead);
}
@Override
public void onCacheIgnored(int reason) {
Log.d(TAG, "onCacheIgnored: cache ignored : " reason);
}
});
}
public MediaSource buildMediaSource(MediaItem mediaItem) {
return new ProgressiveMediaSource.Factory(cacheDataSource).createMediaSource(mediaItem);
}
А SimpleCache — это синглтон, введенный с помощью Hilt :
@Provides
@Singleton
public static SimpleCache simpleCache(@ApplicationContext Context context) {
return new SimpleCache(context.getApplicationContext().getCacheDir(), leastRecentlyUsedCacheEvictor(), exoDatabaseProvider(context));
}
@Provides
@Singleton
public static LeastRecentlyUsedCacheEvictor leastRecentlyUsedCacheEvictor() {
return new LeastRecentlyUsedCacheEvictor(exoPlayerCacheSize());
}
@Provides
@Singleton
public static Long exoPlayerCacheSize() {
return (long) (500 * 1024 * 1024);
}
@Provides
@Singleton
public static ExoDatabaseProvider exoDatabaseProvider(@ApplicationContext Context context) {
return new ExoDatabaseProvider(context);
}
И в моем классе ExoPlayer у меня есть простой метод :
public void prepare(MediaItem mediaItem) {
lastMediaItem = mediaItem;
Log.d(TAG, "prepare: media item : " mediaItem.playbackProperties);
MediaSource mediaSource = videoCacheManager.buildMediaSource(mediaItem);
Log.d(TAG, "prepare: source : " mediaSource.getInitialTimeline());
simpleExoPlayer.prepare(mediaSource);
}
Я достаточно прочитал об exoplayer, и предполагается, что он загружает в кэш видео, если оно не существует, во время первого сеанса потоковой передачи… Итак, что это за ошибка и как ее исправить?
В первый раз, когда я использовал этот код, он сработал, затем я все очистил и повторил попытку без успеха.
Ответ №1:
Хорошо, я просто, должно быть, удалил DefaultDataSourceFactory
по ошибке и забыл вернуть an UpstreamDataSource
к CacheDataSource
экземпляру.
Теперь все работает нормально, надеюсь, это поможет другим.
В коде нам нужно добавить это :
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, Util.getUserAgent(context, context.getString(R.string.app_name)));
cacheDataSource.setUpstreamDataSourceFactory(defaultDataSourceFactory);
Я также многое узнал о ExoPlayer
просмотре этого видео, несмотря на то, что оно было выпущено в 2018 году с версией exoplayer 2.8.
На данный момент я использую последнюю версию, то есть 2.12.3.