I'm looking for any example of implementing cache in ExoPlayer.
ExoPlayer has in its library different classes concerning cache and Google explain in this video that we can implement it with the CacheDataSource class, but Google doesn't provide any demo on it. Unfortunately this seems pretty complicated to use, so I'm currently looking for examples (no success on Google).
Does anyone succeed or has any info that would help ? Thanks.
Here is the solution for ExoPlayer 2.+
Create a custom cache data source factory
class CacheDataSourceFactory implements DataSource.Factory { private final Context context; private final DefaultDataSourceFactory defaultDatasourceFactory; private final long maxFileSize, maxCacheSize; CacheDataSourceFactory(Context context, long maxCacheSize, long maxFileSize) { super(); this.context = context; this.maxCacheSize = maxCacheSize; this.maxFileSize = maxFileSize; String userAgent = Util.getUserAgent(context, context.getString(R.string.app_name)); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); defaultDatasourceFactory = new DefaultDataSourceFactory(this.context, bandwidthMeter, new DefaultHttpDataSourceFactory(userAgent, bandwidthMeter)); } @Override public DataSource createDataSource() { LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(maxCacheSize); SimpleCache simpleCache = new SimpleCache(new File(context.getCacheDir(), "media"), evictor); return new CacheDataSource(simpleCache, defaultDatasourceFactory.createDataSource(), new FileDataSource(), new CacheDataSink(simpleCache, maxFileSize), CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR, null); } }
And the player
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); SimpleExoPlayer exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); MediaSource audioSource = new ExtractorMediaSource(Uri.parse(url), new CacheDataSourceFactory(context, 100 * 1024 * 1024, 5 * 1024 * 1024), new DefaultExtractorsFactory(), null, null); exoPlayer.setPlayWhenReady(true); exoPlayer.prepare(audioSource);
It works pretty well.
Here is an example which replaces demo data source with OkHttp, default is no cache https://github.com/b95505017/ExoPlayer/commit/ebfdda8e7848a2e2e275f5c0525f614b56ef43a6 https://github.com/b95505017/ExoPlayer/tree/okhttp_http_data_source So, you just need to configure OkHttp cache properly and requests should be cached.
I've implemented it like this in the renderer builder
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024; private static final int BUFFER_SEGMENT_COUNT = 160; final String userAgent = Util.getUserAgent(mContext, appName); final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); final Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);* Cache cache = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 10)); DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent); CacheDataSource cacheDataSource = new CacheDataSource(cache, dataSource, false, false); ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri , cacheDataSource , allocator , BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE , new Mp4Extractor());