首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >脱机时未用于播放的Exoplayer缓存

脱机时未用于播放的Exoplayer缓存
EN

Stack Overflow用户
提问于 2018-06-03 03:37:21
回答 1查看 834关注 0票数 2

使用系外播放器2.8.1,在android版本19和23上进行测试。

我使用以下代码构造缓存和数据源工厂:

代码语言:javascript
运行
复制
private static final long DEFAULT_MAX_CACHE_SIZE = 20*1024*1024L;

    cacheEvictor = new LeastRecentlyUsedCacheEvictor(DEFAULT_MAX_CACHE_SIZE);

    cache = new SimpleCache(
            new File(context.getExternalCacheDir(), "exoplayer-cache"),
            cacheEvictor);

    uncachedDataSourceFactory = new OkHttpDataSourceFactory(
            new OkHttpClient(),
            "Android.ExoPlayer",
            null);
    dataSourceFactory =
            new CacheDataSourceFactory(
                    cache,
                    uncachedDataSourceFactory);

然后,我使用以下代码对标准HTTP音频内容进行预缓存:

代码语言:javascript
运行
复制
    new Thread (new Runnable () {
        public void run() {
            try {
                CacheUtil.cache(
                        new DataSpec(uri, DataSpec.FLAG_ALLOW_CACHING_UNKNOWN_LENGTH | DataSpec.FLAG_ALLOW_GZIP),
                        cache,
                        uncachedDataSourceFactory.createDataSource(),
                        null,
                        null);
            } catch (IOException e) {
                callback.invoke(false, "Error: " + e.getMessage());
            } catch (InterruptedException e) {
                callback.invoke(false, "Download interrupted");
            }
            callback.invoke(true);
        }
    }).start();

回调是用true调用的,因此这个过程似乎正在正确地完成。在此之后,我断开了网络连接,并尝试播放缓存的内容:

代码语言:javascript
运行
复制
    DefaultTrackSelector trackSelector = new DefaultTrackSelector();
    player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
    mediaSource =   new ExtractorMediaSource.Factory(dataSourceFactory)
            .setContinueLoadingCheckIntervalBytes(128 * 1024)       // check whether to load more every 128KB
            .createMediaSource(uri);
    mediaSource.addEventListener(handler, new DefaultMediaSourceEventListener() {
        @Override
        public void onLoadError(int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData, IOException error, boolean wasCanceled) {
            Log.i(LOG_TAG, "media load error for " + uri + ": " + error);
        }
    });
    player.addListener(new Player.DefaultEventListener() {
        boolean preparing = true;
        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState)
        {
            Log.i(LOG_TAG, "player " + uri + " state change " + playbackState + ", " + playWhenReady);
            switch (playbackState) {
                case Player.STATE_READY:
                    if (preparing) {
                        preparing = false;
                        callback.invoke(null, getInfo(player));
                    }
                    break;
                case Player.STATE_ENDED:
                    player.seekTo(0);
                    emitMessageEvent(playerId, "ended", "playback completed");
                    if (playerAutoDestroy.get(playerId)) {
                        Log.d(LOG_TAG, "onPlayerStateChanged(STATE_ENDED): Autodestroying player...");
                        destroy(playerId);
                    }
                    break;
                case Player.STATE_BUFFERING:
                    onLoadingChanged(true);
                    break;
            }
        }

        @Override
        public void onPlayerError(ExoPlaybackException error) {
            Log.i(LOG_TAG, "Playback error for " + uri + ": " + error.getMessage(), error);
            emitMessageEvent(playerId, "error", "Playback error: " + error.getMessage());
            destroy(playerId);
        }
   });
   player.prepare(mediaSource, true, true);

当我这样做时,我会得到几个媒体源错误,最后在日志中得到一个播放错误:

代码语言:javascript
运行
复制
06-02 11:20:52.839 32762-327/com.tackta.buxton I/ExoPlayerImpl: Init 93903d2 [ExoPlayerLib/2.8.1] [generic_x86, Android SDK built for x86, unknown, 23]
06-02 11:20:52.840 32762-327/com.tackta.buxton I/AudioPlayerModule: player http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3 state change 2, false
06-02 11:20:52.844 32762-32762/com.tackta.buxton I/AudioPlayerModule: media load error for http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3
06-02 11:20:52.844 32762-32762/com.tackta.buxton I/AudioPlayerModule: media load error for http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3
06-02 11:20:53.846 32762-32762/com.tackta.buxton I/AudioPlayerModule: media load error for http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3
06-02 11:20:55.848 32762-32762/com.tackta.buxton I/AudioPlayerModule: media load error for http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: Unable to connect to http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3
06-02 11:20:55.858 32762-407/com.tackta.buxton E/ExoPlayerImplInternal: Source error.
06-02 11:20:55.859 32762-327/com.tackta.buxton I/AudioPlayerModule: Playback error for http://clarkesworldmagazine.com/podpress_trac/feed/2043/0/clarkesworld_06_18_tem.mp3: null
06-02 11:20:55.863 32762-327/com.tackta.buxton I/ExoPlayerImpl: Release 93903d2 [ExoPlayerLib/2.8.1] [generic_x86, Android SDK built for x86, unknown, 23] [goog.exo.core, goog.exo.okhttp]

这段代码应该是从预加载的缓存中访问数据,还是它试图与网络服务器联系的原因?有没有一种方法告诉它使用缓存而不试图联系服务器?

EN

回答 1

Stack Overflow用户

发布于 2022-11-23 06:15:21

似乎为时已晚,但与其他开发人员共享解决方案似乎很好。你的问题的密码在下面。

代码语言:javascript
运行
复制
private final String vidUrl = "https://www.TEST-SIZTE.com/videos/video.mp4";
    private void initializePlayer(){

    if (exoPlayer == null) {
        final DataSource.Factory dataSourceFactory =
                new DefaultDataSourceFactory(requireContext(), Util.getUserAgent(requireContext(), getString(R.string.app_name)));

        final MediaSourceFactory mediaSourceFactory =
                new DefaultMediaSourceFactory(dataSourceFactory)
                        .setAdViewProvider(fragBinding.fullScreenVideoView);
        exoPlayer = new ExoPlayer.Builder(requireContext()).setMediaSourceFactory(mediaSourceFactory).build();
    }
    fragBinding.fullScreenVideoView.setPlayer(exoPlayer);
    fragBinding.fullScreenVideoView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT);
    exoPlayer.setPlayWhenReady(playWhenReady);
    mediaContentSFun();
    exoPlayer.prepare();
}

private void mediaContentSFun(){
    final MediaSource mediaSource = buildMediaSource();
    exoPlayer.setMediaSource(mediaSource, false);
}

private MediaSource buildMediaSource(){
    final SimpleCache simpleCache = ExoSimpleCache.getSimpleCacheInstance(requireActivity());

    final DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(requireContext(), requireContext().getString(R.string.app_name));
    final CacheDataSource.Factory cacheFactory = new CacheDataSource.Factory();
    cacheFactory.setCache(simpleCache);
    cacheFactory.setUpstreamDataSourceFactory(dataSourceFactory);

    final ProgressiveMediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory(cacheFactory);
    final MediaItem mediaItem = MediaItem.fromUri(vidUrl);

    final MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem);


    return new ConcatenatingMediaSource(mediaSource);
}

最后是ExoSimpleCache类,它需要用作单例。

代码语言:javascript
运行
复制
public class ExoSimpleCache {
   private static SimpleCache simpleCache;

public static SimpleCache getSimpleCacheInstance(final Context context){
    if (simpleCache == null){
        final long maxBytes = 1024L * 1024 * 1024 * 18; 
        // for 18 GB, my total needed cache size was 18GB you can change it as per your need.
        final LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(maxBytes);
        final File file = new File(context.getExternalCacheDir(), "media");

        final StandaloneDatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);
        simpleCache = new SimpleCache(file, evictor, databaseProvider);
    }
    return simpleCache;
}

}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50663053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档