You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ExoPlayer遇网络问题后从头重试播放?

ExoPlayer网络中断后基于缓存恢复播放的实现方法

问题场景

我实现了一个简易ExoPlayer,加载代码如下:

List<MediaItem> mediaItems = new ArrayList<>(playlist.size());

for (String url : playlist) {
    mediaItems.add(MediaItem.fromUri(url));
}

player.setMediaItems(mediaItems);
player.prepare();
player.setRepeatMode(player.REPEAT_MODE_ONE);

该播放器可正常运行,且已实现离线播放功能。目前遇到的问题是:有时出现网络问题会导致播放器停止,能否基于已缓存内容恢复或从头开始播放?

解决方案

1. 捕获播放错误并判断缓存可用性

给ExoPlayer添加监听,捕获网络类播放错误,同时检查当前媒体的缓存状态,若有缓存则尝试恢复播放:

player.addListener(new Player.Listener() {
    @Override
    public void onPlayerError(PlaybackException error) {
        // 识别网络相关错误
        if (error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED 
            || error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_TIMEOUT) {
            MediaItem currentItem = player.getCurrentMediaItem();
            if (currentItem != null && isMediaCached(currentItem)) {
                // 从头播放缓存内容
                player.seekTo(0);
                player.play();
            }
        }
    }
});

2. 实现缓存状态检查方法

通过你的缓存实例(如SimpleCache)判断媒体是否已缓存:

private boolean isMediaCached(MediaItem mediaItem) {
    Cache cache = ...; // 替换为你已初始化的缓存实例
    CacheKey cacheKey = DefaultCacheKeyFactory.getInstance().buildCacheKey(mediaItem);
    long cachedLength = cache.getCachedLength(cacheKey);
    long totalDuration = player.getDuration();
    
    // 只要有缓存内容(或已缓存完整媒体)就返回true
    return cachedLength > 0 && (totalDuration == C.LENGTH_UNSET || cachedLength >= totalDuration);
}

3. 配置自动重试策略

通过自定义LoadControl让播放器在网络波动时自动重试加载,避免直接停止:

DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
    .setRetryDelayMs(2000) // 每次重试间隔2秒
    .setMaxRetryCount(3) // 最多重试3次
    .build();

ExoPlayer player = new ExoPlayer.Builder(context)
    .setLoadControl(loadControl)
    .build();

4. 强制切换离线播放模式

如果网络长期中断,可以切换到仅使用缓存的数据源,确保播放器仅从缓存读取内容:

private void switchToOfflinePlayback() {
    Cache cache = ...; // 你的缓存实例
    DataSource.Factory offlineDataSource = new CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory())
        .setFlags(CacheDataSource.FLAG_BLOCK_ON_CACHE); // 强制从缓存读取
    
    ProgressiveMediaSource offlineSource = new ProgressiveMediaSource.Factory(offlineDataSource)
        .createMediaSource(player.getCurrentMediaItem());
    
    player.setMediaSource(offlineSource);
    player.prepare();
    player.play();
}

内容的提问来源于stack exchange,提问作者Rodrigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:07:29