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 th
To resolve the problem of multiple videos or processes trying to access the same cache, you need a true Singleton. A reliable way would be to do it this way:
object VideoCache {
private var sDownloadCache: SimpleCache? = null
private const val maxCacheSize: Long = 100 * 1024 * 1024
fun getInstance(context: Context): SimpleCache {
val evictor = LeastRecentlyUsedCacheEvictor(maxCacheSize)
if (sDownloadCache == null) sDownloadCache = SimpleCache(File(context.cacheDir, "koko-media"), evictor)
return sDownloadCache as SimpleCache
}
}
which you can now use:
private val simpleCache: SimpleCache by lazy {
VideoCache.getInstance(context)
}
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());
In addition to Bao Le's answer, here's ready to use Kotlin version of CacheDataSourceFactory
that keeps one instance of SimpleCache
to solve the problem of multiple Cache objects writing to the same directory.
class CacheDataSourceFactory(private val context: Context,
private val maxCacheSize: Long,
private val maxFileSize: Long) : DataSource.Factory {
private val defaultDatasourceFactory: DefaultDataSourceFactory
private val simpleCache: SimpleCache by lazy {
val evictor = LeastRecentlyUsedCacheEvictor(maxCacheSize)
SimpleCache(File(context.cacheDir, "media"), evictor)
}
init {
val userAgent = Util.getUserAgent(context, context.packageName)
val bandwidthMeter = DefaultBandwidthMeter()
defaultDatasourceFactory = DefaultDataSourceFactory(context,
bandwidthMeter,
DefaultHttpDataSourceFactory(userAgent, bandwidthMeter))
}
override fun createDataSource(): DataSource {
return CacheDataSource(simpleCache,
defaultDatasourceFactory.createDataSource(),
FileDataSource(),
CacheDataSink(simpleCache, maxFileSize),
CacheDataSource.FLAG_BLOCK_ON_CACHE or CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR,
null)
}
}
I answered this similar question here: https://stackoverflow.com/a/58678192/2029134
Basically, I use this library: https://github.com/danikula/AndroidVideoCache To cache file from URL Then 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.