Using cache in ExoPlayer Using cache in ExoPlayer android android

Using cache in ExoPlayer


Here is the solution for ExoPlayer 2.+

Create a custom cache data source factory

public class CacheDataSourceFactory implements DataSource.Factory {    private final Context context;    private final DefaultDataSourceFactory defaultDatasourceFactory;    private final long maxFileSize, maxCacheSize;    public 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.


By default ExoPlayer do not cache media (video, audio, etc...). For example if you want to play an online video file, each time ExoPlayer will open a connection, read data then play it.

Fortunately, it provides us some interfaces and implementation classes to support caching media in our app.

You can write your own cache which implement given interfaces from ExoPlayer. To make it simple I will guide you how to enable cache by using implementation classes.

Step 1: Specify a folder which contains your media files, in Android for smaller cache folder (less than 1MB), you should use getCacheDir, otherwise you can specify your prefer cache folder, getFileDir for example.

Step 2: Specify a size for the cache folder, and policies when the size is reached out. There are 2 APIs

  • NoOpCacheEvictor that doesn't ever evict/remove cache files. Based on location of your cache folder, if it's in internal storage, the folder will be removed when users clear app data or uninstall app.
  • LeastRecentlyUsedCacheEvictor that will evict/remove least recently used cache files first. For example if your cache size is 10MB, when the size is reached out, it will automatically find and remove files which least recently used.

Put it together

val renderersFactory = DefaultRenderersFactory(context.applicationContext)val trackSelector = DefaultTrackSelector()val loadControl = DefaultLoadControl()val player = ExoPlayerFactory.newSimpleInstance(context, renderersFactory, trackSelector, loadControl)player.addListener(this)// Specify cache folder, my cache folder named media which is inside getCacheDir.val cacheFolder = File(context.cacheDir, "media")// Specify cache size and removing policiesval cacheEvictor = LeastRecentlyUsedCacheEvictor(1 * 1024 * 1024) // My cache size will be 1MB and it will automatically remove least recently used files if the size is reached out.// Build cacheval cache = SimpleCache(cacheFolder, cacheEvictor)// Build data source factory with cache enabled, if data is available in cache it will return immediately, otherwise it will open a new connection to get the data.val cacheDataSourceFactory = CacheDataSourceFactory(cache, DefaultHttpDataSourceFactory("ExoplayerDemo"))val uri = Uri.parse("Put your media url here")val mediaSource = ExtractorMediaSource.Factory(cacheDataSourceFactory).createMediaSource(uri)player.prepare(mediaSource)


I answered this similar question here: https://stackoverflow.com/a/58678192/2029134

Basically, I use this library: https://github.com/danikula/AndroidVideoCacheTo cache file from URLThen put it in ExoPlayer.

Here is the sample code:

String mediaURL = "https://my_cool_vid.com/vi.mp4";SimpleExoPlayer exoPlayer = ExoPlayerFactory.newSimpleInstance(getContext());HttpProxyCacheServer proxyServer = HttpProxyCacheServer.Builder(getContext()).maxCacheSize(1024 * 1024 * 1024).build();String proxyURL = proxyServer.getProxyUrl(mediaURL);DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getContext(),                Util.getUserAgent(getContext(), getActivity().getApplicationContext().getPackageName()));exoPlayer.prepare(new ProgressiveMediaSource.Factory(dataSourceFactory)                .createMediaSource(Uri.parse(proxyURL)););

Hope that helps.