ExoPlayer is a open-source super customizable audio/video player from Google. It is able to play DASH (Dynamic Adaptive Streaming over HTTP), HLS (HTTP Live Streaming) and SmoothStreaming; merge, loop, concatenate, cache medias — while allowing developer to define custom load control, define seamless transition between successive medias and much more. So without further delay, lets get started.
build.gradle file, include following dependencies and turn on Java 8 support.
Now lets head to UI setup. Create a layout file called
item_video. This may be inflated in
RecyclerView or a Fragment or a Activity but for now, lets assume this will be inflated in RecyclerView.
Since we are inflating our layout in
RecyclerView’s adapter, lets create a class that extends
RecyclerView.Adapter#onBindViewHolder, we will bind the video stream URL to the variable we have defined in our xml i.e
url. Optionally, if we need to know the current state of
PlayerView, we will have to implement a listener
PlayerStateCallback and pass it to the
PlayerView to get notified of the state change .
P.S- Here’s a helpful gist containing a number of streaming URLs you can use to test your implementation.
Notice how we are setting the stream URL for the video in
url variable available from the data binding library. The
app:video_url and the
app:on_state_change part in the xml file is from
callback is used to communicate the state of the video player like buffering, paused, playing or idle so that we can handle these change of state in our main code. Now for the fun part — Lets create an extension function with
@BindingAdapter annotation, that we will use to setup our
PlayerView, with the values we have passed in our xml file as the arguments.
You can also pass in the view for
ProgressBar as an argument to above extension function.
Great! Look at how clean the
RecyclerView.ViewAdapter code is! There’s barely anything there. We have successfully started streaming the videos from the test URLs.
Now for the advance part!
In order to prevent media from buffering again and again, you’ll need to implement a local cache. You can do this by creating a subclass of
DataSource.Factory and building a
Note: I have used a local
Context here, but in singleton dependencies, you should use the application context. It’s better to inject it.
And to use this cache as data source, instead of
DefaultHttpDataSoruceFactory — use the above created
Seamless transition between medias
Need a seamless buffer-free transition between successive medias? Want to have control over the looping or the playback sequences of the media? Then
MediaSource is what you need! Here’s a nice article about it.
Want to have a control on the duration of media buffered for playing or before playing? Then you’ll need to override the DefaultLoadControl. It provides a dummy constructor as well as a builder to allow you to customize the property of the ExoPlayer.