android - DummyDataSource无法打开: Android ExoPlayer

标签 android caching video-streaming exoplayer exoplayer2.x

我正在尝试从 URL 流式传输视频并同时将它们保存在缓存中。

我正在使用 Android Studio 的 DataBaseInspector 来检查缓存,它似乎可以工作,但并非一直有效。

有时当我尝试播放视频时会出现此错误:

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 是一个注入(inject) Hilt 的 Singleton:

    @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 的足够内容,如果在第一个流 session 期间视频不存在,它应该将视频下载到缓存中...那么这个错误是什么以及如何修复它?

我第一次使用此代码时它起作用了,然后我清除了所有内容并重试但没有成功。

最佳答案

好吧,我肯定是错误地删除了 DefaultDataSourceFactory 并且忘记将 UpstreamDataSource 设置回 CacheDataSource 实例。

现在一切正常,希望这对其他人有帮助。

在代码中我们需要添加以下内容:

DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, Util.getUserAgent(context, context.getString(R.string.app_name)));
cacheDataSource.setUpstreamDataSourceFactory(defaultDataSourceFactory);

通过观看此视频,我还了解了很多关于 ExoPlayer 的知识 video ,尽管那是 2018 年的 exoplayer 版本 2.8。

我目前使用的是最新版本,即2.12.3。

关于android - DummyDataSource无法打开: Android ExoPlayer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65824855/

相关文章:

安卓 java.lang.IllegalArgumentException : path must be convex

c# - 如何处理 RadioGroup.SetOnCheckedChangeListener?

audio - 从OpenTok服务器下载的视频没有声音

IOS 网页 View 和视频

android - 错误 : Cannot find setter for field. - java.util.ArrayList 中的大小 - Room 中的嵌入式 ArrayList 无法编译

Android从 picasso 获取图像到位图数组

java - 无限跨度 : locking in remote transactional cache

在 ASP Classic 中缓存记录集?

android - 如何在 Android 中创建离线第一个 RecyclerView?以及如何只更新最新的数据?

linux - 如何解决通过 gstreamer udpsink 流式传输 h.264 时的图像问题