Implement a Cache for ExoPlayer

In this article, let's learn how to implement caching when streaming with ExoPlayer. For your convenience, this article provides code samples in both Java and Kotlin.

In this article, let's learn how to implement caching when streaming with ExoPlayer. For your convenience, this article provides code samples in both Java and Kotlin.

ExoPlayer

ExoPlayer is an alternative to Android's MediaPlayer for audio and video playback, both locally and over the internet.

YouTube implements ExoPlayer for its media playback. 

For those unaware, ExoPlayer supports features not currently supported by Android’s MediaPlayer API, including DASH and SmoothStreaming adaptive playbacks. Unlike the MediaPlayer API, ExoPlayer is easy to customize, extend, and can be updated through Play Store application updates.

ExoPlayer has a long list of pros and a few cons which you can read about over here before you use it for your project, but to keep this article concise, let's get to the point and implement caching with ExoPlayer.

Why Caching?

A Cache is usually a small amount of data, stored locally at the client's end to prevent repetitive requests to the backend. This helps in saving resources and improves performance by avoiding network calls when not needed.  

When streaming media, a cache is important to avoid downloading the media file over and over again to play it to the user. For instance, in the default implementation of ExoPlayer, the media file is downloaded each time the user closes and opens the app. To avoid this, let's implement caching.

Basic ExoPlayer Setup

The first step is to add ExoPlayer to your app's build.gradle file. At the time of writing this article, the latest version of ExoPlayer was 2.18.0. While implementing it, check out its release notes for the version you need to use.

Once this is done, sync your project and go to the application class in your project.

Cache Setup in Application Class

If you don't have an application class, create one for your project with help from Android Developer Docs or this codepath. Refer to the GitHub Repo of this project linked below if you'd like a simple example of the same.

Now, in your app's application class, create variables for the following objects - a SimpleCache, a LeastRecentlyUsedCacheEvictor, and a StandaloneDatabaseProvider and initialize them in the onCreate() method of this class.

Make sure to create this cache in your application class and not in activities or fragments. While this would work the first time, it will throw an error stating that a cache already exists when you reopen the activity/cache.

Using ExoPlayer

Now that the basic setup is done, let's go ahead and start using ExoPlayer. For this example, we'll only be dealing with video files, but a GitHub repository is provided below which has a simple implementation for streaming of both video and audio files.

In the XML file of your fragment/activity, create a StyledPlayerView.

If you'd prefer not to use StyledPlayerView, you can check out the other UI components ExoPlayer offers like PlayerControlView or TimeBar. If you're a pro in design and would like to create one yourself, please go ahead - ExoPlayer provides this option as well. There are a few guides online to help you make ExoPlayer look like YouTube's media player. A StyledPlayerView can be used for both video and audio playback and for this reason we'll make use of this view for this article.

Now, in the Activity or Fragment, you can create an ExoPlayer instance, attach it to the player view created in the layout and start using it. The following lines of code will help you implement this with view binding.

The first step is to create an ExoPlayer instance outside the constructor of your Activity/Fragment. For this example, let's name it player.

Let's look at the function to initialize the ExoPlayer initVideoPlayer which can be called from the onViewCreated() of your Activity/Fragment. You can change where you want to call this based on your requirements. Before calling this, make sure that you have a valid string in mediaURI. For instance, I have used this -

mediaURI = "https://download.samplelib.com/mp4/sample-30s.mp4"

The next step is to ensure that you release the player once you're done with using it. This can be done in the onDestroy() of your Fragment. Based on your use case, you can release the player whenever needed.

That's it. For you're convenience please find the code for the entire fragment in both Java and Kotlin below.

You may now run your project and test if it's working as expected.

Tips to Test Cache Working

  1. Open the app, and then play the video.
  2. Turn off your internet, and try playing the video.
  3. If you're able to play the video even when you're offline, your implementation works 💖

End words

Found something wrong? Please raise an issue on GitHub.

If you need any help, you can check out our sample media player project that's been implemented with ExoPlayer over here.

If you still have any questions, feel free to reach out to us on Twitter or raise an issue on GitHub and we'll get back to you as soon as we can.

Hope you enjoyed this article. Subscribe for more ✌