使用系外播放器2.8.1,在android版本19和23上进行测试。
我使用以下代码构造缓存和数据源工厂:
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音频内容进行预缓存:
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调用的,因此这个过程似乎正在正确地完成。在此之后,我断开了网络连接,并尝试播放缓存的内容:
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);
当我这样做时,我会得到几个媒体源错误,最后在日志中得到一个播放错误:
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]
这段代码应该是从预加载的缓存中访问数据,还是它试图与网络服务器联系的原因?有没有一种方法告诉它使用缓存而不试图联系服务器?
发布于 2022-11-23 06:15:21
似乎为时已晚,但与其他开发人员共享解决方案似乎很好。你的问题的密码在下面。
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类,它需要用作单例。
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;
}
}
https://stackoverflow.com/questions/50663053
复制相似问题