Android Media ch. 1: Intro to ExoPlayer
Help for Junior Android Developers
Let’s use ExoPlayer to create an Android app from scratch that can play videos. We will do this in 5 easy steps. ExoPlayer is a library built on top of Android’s media API (
ExoPlayer makes it extremely easy to play an .mp3 or .mp4 file. If instead you want to play a more advanced file format or exert more granular control over your user’s experience, ExoPlayer also gives you great flexibility. Now, the 5 steps:
- Create an Android Studio project and name it Moving Water.
- In gradle, add ExoPlayer dependency
- In the manifest, request Internet permission
- Change your layout file to include the
MainActivity, create an ExoPlayer instance and pass it the video URL to play
Step 1: Create project Moving Water in Android Studio
See the following three figures for how-to:
Step 2: In gradle, add ExoPlayer dependency
Make sure your root
build.gradle file has jcenter repo. The “Android” view in Android Studio displays the file as build.gradle(Project:MovingWater)
In the build.gradle file of the app module add the ExoPlayer dependency.
- My version is r2.4.0. Check the release notes for the latest version.
In the manifest, request Internet permission
Step 4: Add SimpleExoPlayerView to your layout file
Change your activity_main.xml file to this:
Step 5: Create an ExoPlayer Instance
In MainActivity, we are going to create an ExoPlayer instance and pass it the video URL to play. But since this is the final step, I want to entertain you and tell you about video streaming just a little bit before I send you on your way.
Say you go on to build a cool video app and it gets downloaded by millions of users. As you can imagine some of your users may have great internet connectivity, while others may have spotty connectivity that oscillate between great and okay, while others still may have poor connectivity. Before ExoPlayer, pleasing all these different users was hopeless for individual app creators and small companies. If you have a high quality video file, the guy with fancy wifi will be happy but the guy with spotty internet will spend most of his time waiting for the video to load. And oh forget about the guy with poor connection.
What ExoPlayer does to solve the problem is allow apps to download small chunks of media at a time, say 2 second long chunks. For each chunk ExoPlayer decides whether to download higher quality or lower quality media based on the user’s internet bandwidth. So if a user’s connection is spotty, now she may get a lower quality 2 seconds chunk and then 2 seconds later she gets a higher quality video chunk and so on — the beauty being her viewing experience is smoother than it might have been because ExoPlayer continuously tracks internet bandwidth.
Our goal in this step is still to simply create an instance of ExoPlayer and pass the video file to it. To instantiate
SimpleExoPlayer (“the player”) we need a
TrackSelector is actually what’s responsible for choosing which file chunks to download based on perceived bandwidth changes. So, for example, if a high quality chunk would take too long to download, the
TrackSelector will choose something of lower quality to show the user. And since each chunk is usually about 2 to 12 seconds long, it’s not so bad if the user gets a lower quality chunk of media once in while for the benefit of a smooth experience.
TrackSelector needs to be given a set of tracks. That’s where
TrackSelection.Factory comes in. Here we select the set of tracks we need. For example, our app will specify
AdaptiveTrackSelection since we want to adapt chunk quality based on internet bandwidth to maximize a smooth viewing experience for the user. So we mention bandwidth a lot. Someone needs to track bandwidth changes so that the
TrackSelector can select based on bandwidth changes. To do this we will pass a
BandwidthMeter to the
AdaptiveTrackSelection( BandwidthMeter )
onStart of your
MainActivity, add the following code snippet
player is a field outside of your
onStart method — I’m just checking if you are awake.
Woot! Woot! We have a working Player. But it’s not yet attached to any display. So let’s add a display for your users.
When it comes to displaying video content to your users, you have a lot of options —
Surface. To use any of those views for displaying your content to your users, just call
player.setVideoSurface respectively. Again, ExoPlayer is all about freedom, especially for those who want highly customized control. However since we are not looking for customization, we are using the out of the box
Now you can connect the player to the view:
Ok, now for the final stretch. At this point we have a player and a surface to display our content, but we don’t have any content. I want to show my users the Moving Water movie. So what do I do?
To pass content to ExoPlayer we use
MediaSource. Basically you pass the URI of the video you want to play to the
MediaSource and then pass the
MediaSource to ExoPlayer. Why
MediaSource? Well, that’s actually a heavy question.
MediaSource is flexible enough to do both simple things and fancy things. You can create playlists, loops, etc. etc. etc. One particular case of interest for large companies, for example, is adaptive streaming. Large companies tend to have fancy servers that can provide adaptive content: in other words, they have URLs for users that can adapt streaming content over fast, slow, and spotty connectivity. If you were building your app for one such company, you would use an adaptive
MediaSource such as
HlsMediaSource. But for our present example I will use
ExtractorMediaSource which will simply extract and play my mp4/mp3 media. (DASH is the international standard, HLS is for Apple and SmoothStreaming is for Microsoft; and yes there are more formats out there).
Similar to ExoPlayer for instantiating,
MediaSource needs a few objects to do its job: namely a
BandwidthMeter to track internet connectivity and an
ExtractorsFactory to determine how to extract the data from server. Add the following code to your
And then inside
Voila! Now you can run the app and it should play the Moving Water video for you!
You may want to protect against orientation changes. To do that just override
onRestoreInstanceState in your
I almost forgot something very important. You must release the player when you are done with it. A good place to do that is in onStop or in onPause depending on your android version. Before API 24 do it in onPause otherwise do it in onStop