1

I have searched for cache in/of ExoPlayer but i neither understoond them nor could implement them correctly.

In this asked question for using cache in Exoplayer there are some answers with sample code. The first answer that i'm not able to implement it is in part two of sample code which said to use the class DefaultHttpDataSourceFactory that i suppose it was changed with the class DefaultHttpDataSource.Factory() that does not seem much of a problem but the main problem i faced was this line of code

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);

that says use class ExtractorMediaSource which there is not calss by this name, i even did not find in depricated classes of exoplayer document. Almost evetything has changed in exoplayer in version 2.18.0. For instance, the part that we should set MediaSource for exoplayer now it is sepreated into two parts:

final DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, "agent name"); //part one
final ProgressiveMediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory(dataSourceFactory); //part two

I hope you have seen the differences and my problem with this solution

And now next solution and its problem: This dear friend suggest to use This Library which sound good and some how solved my problem but what this dependency compile 'com.danikula:videocache:2.7.1' actually does is to download the video and save it in app folder. since android Pie(9) and new privacy plicy of google and android phone producers, they do not allow to access app folder.

And the same issue with other solutions that are in Kotlin, the classes in exoplayer are missing.

What i want: I want to use cache in exoplayer2(or cache of exoplayer2) like Glide that save image in app cache i want to implement similar functionality for my exoplayer2, i have searched almost everywhere.

Note: I use these dependecies of ExoPlayer:

implementation 'com.google.android.exoplayer:exoplayer-core:2.18.0'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.18.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.18.0'
implementation 'com.google.android.exoplayer:exoplayer:2.18.0'

I am finished with my app just need to figure out this part of it.

StackOverflower
  • 369
  • 2
  • 12

2 Answers2

0

Use Builder class to create player object and set MediaSourceFactory to caching like this:

            val databaseProvider = StandaloneDatabaseProvider(context)
        context.getExternalFilesDir("voice/$artistId/$albumNumber")?.let {
            simpleCache = SimpleCache(
                it,
                NoOpCacheEvictor(),
                databaseProvider
            )
            val defaultDataSourceFactory = DefaultDataSource.Factory(context)
            val cacheDataSourceFactory = CacheDataSource.Factory()
                .setCache(simpleCache!!)
                .setUpstreamDataSourceFactory(defaultDataSourceFactory)
            player = ExoPlayer
                .Builder(context)
                .setMediaSourceFactory(DefaultMediaSourceFactory(cacheDataSourceFactory))
                .build()
        } ?: kotlin.run {
            player = ExoPlayer.Builder(context).build()
        }
0
const val CACHE_DIR_NAME = "cached_audio"
const val MAX_CACHE_SIZE = 256 * 1024 * 1024L//256MB

class MediaCache private constructor(context: Context) {

    val cacheFactory: CacheDataSource.Factory

    init {
        cacheFactory = setupExoPlayerCache(context)
    }

    companion object {
        @Volatile
        private lateinit var instance: MediaCache

        fun getInstance(context: Context): MediaCache {
            synchronized(this) {
                if (!::instance.isInitialized) {
                    instance = MediaCache(context)
                }
                return instance
            }
        }
    }

    @SuppressLint("UnsafeOptInUsageError")
    private fun setupExoPlayerCache(context: Context): CacheDataSource.Factory {
        val cacheEvictor = LeastRecentlyUsedCacheEvictor(MAX_CACHE_SIZE)
        val databaseProvider = StandaloneDatabaseProvider(context)
        val cache = SimpleCache(
            File(context.cacheDir, CACHE_DIR_NAME),
            cacheEvictor, databaseProvider
        )
        val upstreamFactory = DefaultDataSource.Factory(context)
        return CacheDataSource.Factory().apply {
            setCache(cache)
            setUpstreamDataSourceFactory(upstreamFactory)
            setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
        }
    }
}

and then everywhere you pass media source to exoplayer:

            val mediaItem = MediaItem.fromUri(uri)

            val mediaSourceFactory =
                ProgressiveMediaSource.Factory(MediaCache.getInstance(this@PlaybackService).cacheFactory)
            val mediaSource = mediaSourceFactory.createMediaSource(mediaItem)

            player.setMediaSource(mediaSource, true)
Hadi Ahmadi
  • 1,924
  • 2
  • 17
  • 38