Blog Infos
Author
Published
Topics
Published

Background

With the growth in usage of video consumption & data needs there is also an increased need to watch videos offline. Users can view their downloaded videos even when they are offline like while they’re on a plane, or in places with low internet connectivity alongside providing a secure way to access and preventing it from directly getting stored on the user’s storage forever.

How it Works then?

With Google ExoPlayer we can easily add the capability of downloading media (m3u8) for offline playback
Here, we keep chunks of the video in the device cache rather than downloading the entire file, and all of those arrays of chunks are mapped to the video URL
Example URL = [c1,c2,c3,c4…]

Now, whenever Exoplayer tries to access this video URL, it can either be served straight via URL via Network Call or we can use the video chunks we obtained to play that video directly without any buffer overhead i.eOffline playback
Many of the apps, including Netflix, Amazon Prime Video, and YouTube, operate using a very similar technique.

Overview of how ExoPlayer Offline Download works

  • Download Service: This is a default download service packaged with an Exoplayer that acts as a wrapper over DownloadManager and forwards commands to it. Also, this service helps in keeping the ExoPlayer Downloads running even when the app is in the background.
  • Download Manager: As its name suggest this is the manager that helps with Managing multiple downloads, loading and storing download states, starting and stopping downloads
  • HTTP Data Source: This is an interface that helps to download the media content from the provided URI(data source) over an HTTP connection
  • Cache: When the download manager specified above downloads any chunk of data i.e video content it is stored inside the device cache using Cache Data Source

 

High-Level Flow for Offline Download

 

As shown in the above flow we are using many different classes to help with downloading videos offline i.e

Download Tracker: This a multi-utility class that is a wrapper over ExoPlayer Download Manager & Download Service also it helps to handle, track & manage any kind of download operations i.e

  • Starting / Stopping Download
  • Tracking any offline download
  • Querying Content (In progress/ Already downloaded)

Download Dialog Helper: This is a wrapper over ExoPlayer’s internal Download Helper that is responsible for

  • Initializing and removing downloads.
  • Extracts track information from the media
  • Shows Selection menu for downloading media track
  • Creates download requests based on the selected tracks.

Track Selection Dialog: This is Download Popup Dialog that presents the user with the option to select which Video & Audio Track to download

Offline Download Service: This is a wrapper over the ExoPlayer original DownloadServicethat helps to manage all Exoplayer download operations i.e

  • Start/Stop Download
  • Pause/Resume Download
  • Remove Download
  • Track/Display the Status(via notification) of the in-progress download

Terminal State Notification Helper: This is a helper to track the download status which notifies whenever the download state changes alongside this help to notify users via notification of the progress of the download with the help of OfflineDownloadService

We need to make sure to add all these boilerplate codes as it is needed to be added to add offline support download Code Ref below 👇

public void toggleDownload(
FragmentManager fragmentManager,
MediaItem mediaItem,
RenderersFactory renderersFactory
) {
Download download = downloads.get(checkNotNull(mediaItem.localConfiguration).uri);
if (download != null && download.state != Download.STATE_FAILED) {
DownloadService.sendRemoveDownload(
/* context= */ context,
/* DownloadService= */ OfflineVideoDownloadService.class,
/* id= */ download.request.id,
/* foreground= */ false
);
} else {
if (startDownloadDialogHelper != null) {
startDownloadDialogHelper.release();
}
DownloadHelper helper =
DownloadHelper.forMediaItem(
context,
mediaItem,
renderersFactory,
dataSourceFactory
);
startDownloadDialogHelper =
new StartDownloadDialogHelper(
/* fragmentManager= */fragmentManager,
/* downloadHelper= */ helper,
/* mediaItem= */mediaItem
);
}
}

Job Offers

Job Offers


    Senior Android Developer

    SumUp
    Berlin
    • Full Time
    apply now

    Senior Android Engineer

    Carly Solutions GmbH
    Munich
    • Full Time
    apply now

OUR VIDEO RECOMMENDATION

No results found.

Jobs

This method is a part of Download Tracker that helps to start/stop any download

Internally these methods further make use of the

  • Download Service: To remove the media item that has already been downloaded
  • Download Dialog Helper: To start a fresh download as mentioned above this helper helps in initializing the download, Extracting the track information & showing that information in form of a dialog post through which the user can download the selected track
Playing downloaded content offline
ExoPlayer player = ExoPlayer.Builder(this).build()
player?.playWhenReady = true
val mediaSource = downloadTracker?.getDownloadRequest(Uri.parse(VIDEO_URL))!!.let {
DownloadHelper.createMediaSource(
it,
DemoUtil.getDataSourceFactory(this)
)
}
player?.setMediaSource(mediaSource)
player?.prepare()

This method is to initialise the ExoPlayer to play the media content that we downloaded earlier. Here Download Tracker helps up get the download request for the media that we downloaded using the video URL & further that download request is used to create a media source and we use the cache data source to fetch the downloaded content from the cache

Some Additional thoughts?

There are many in-depth configurations & experimentation that can be done along with this. This is a basic implementation of how to download a video offline & play it.
Do let me know in the comments how you have worked on ExoPlayer & its various amazing features.

Thank you for reading, stay tuned for amazing articles!

Catch me up at: https://twitter.com/its_pra_tick

Do not forget to clap, happy coding 🙂

This article was previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
In this part of our series on introducing Jetpack Compose into an existing project,…
READ MORE
blog
This is the second article in an article series that will discuss the dependency…
READ MORE
blog
Let’s suppose that for some reason we are interested in doing some tests with…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu