MediaPlayer: Simplified Video Playback on Android
Playing videos is a common requirement in Android apps. In this tutorial learn about handling video playback via the MediaPlayer API on Android. By Bhavesh Misri.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
MediaPlayer: Simplified Video Playback on Android
25 mins
- Getting Started
- Understanding the code
- MediaPlayer
- Playing Video From Local Resources
- MediaPlayer is prepared
- Improving the UX
- Interacting with the SeekBar
- Playing Video from the Gallery
- Playing the video after it has been downloaded
- Releasing the Resources
- Executing Asynchronously
- Streaming a Video From a URL
- Digital Right Management
- DRM MediaPlayer
- Where To Go From Here?
Releasing the Resources
MediaPlayer
API consumes a lot of resources. So, you should always release those resources by calling release()
.
As per the official Android documentation, you should release the resources whenever your app is in background or stopped state. Failing to could lead to continuous battery consumption for the device and playback failure for other apps if multiple instances of the same codec aren't supported. It could also degrade the device's performance in general.
In onDestroy()
, replace // TODO (11) with:
handler.removeCallbacks(runnable)
mediaPlayer.release()
Here you remove the runnable from the thread or message queue by calling removeCallbacks()
. If you didn't, your runnable would keep executing in the background.
Build and Run. It looks like nothing changed, but you ensured the resources release when the user kills the app.
Executing Asynchronously
Asynchronous code is very important for Android apps. You may have not noticed, but currently, you are loading the video asynchronously.
In most cases, videos are heavy and take time to load, therefore, you need to make the code asynchronous. When that happens, MediaPlayer
will lead the app to ANR, or Application Not Responding, state. In short, your app will become non-responsive and crash.
To load the media file asynchronously what you did was using prepareAsync()
instead of prepare()
inside the surfaceCreated()
function. In other words, if you try to use prepare()
in that line and run the app, it will be there loading for a long time.
Seriously, that's it! That's all you had to do.
Next, you'll implement asynchronously streaming a video from a URL.
Streaming a Video From a URL
Fortunately, you don't have to make many changes to prepare MediaPlayer
asynchronously and stream a video from a URL.
In surfaceCreated()
, replace setDataSource()
with:
setDataSource(URL)
Then, in surfaceCreated()
replace prepare()
with prepareAsync()
.
After you make those changes, surfaceCreated()
will look like this:
override fun surfaceCreated(surfaceHolder: SurfaceHolder) {
mediaPlayer.apply {
setDataSource(URL)
setDisplay(surfaceHolder)
prepareAsync()
}
}
Nice! Now your MyTube app can play videos from res directory, gallery and even stream a video from a URL.
Before you finish, there's one more topic you need to explore: DRM, or Digital Right Management.
Digital Right Management
DRM, or Digital Right Management, technologies are a set of tools that protect or encrypt video and audio files. There are many technologies to help with that, such as Microsoft's PlayReady and Google's Widevine. Working with DRM-protected files is a topic worthy of it's own tutorial.
MediaPlayer
added support to play DRM protected videos in Android 8 with API 26. If you want to play a DRM protected video, either you have to set your app's minSdkVersion to 26, or annotate your class with @RequiresApi(Build.VERSION_CODES.O).
DRM MediaPlayer
Because DRM mostly relies on the security-by-obscurity principle, it's hard to get your hands on any DRM protected media files. You won't play a DRM protected file as it's too complicated for this tutorial. Instead, you'll see an overview of the changes you have to make to play a DRM protected file.
Take a look at onCreate()
again. You'll see this:
mediaPlayer.setOnDrmInfoListener(this)
This line of code tells MediaPlayer
it could be accessing a DRM protected file. You don't have to worry about the app crashing if the media file is not DRM protected: It takes care of that itself. If the media file is DRM protected the app invokes onDrmInfo()
.
After that, inside onDrmInfo()
replace // TODO (12) with :
mediaPlayer?.apply {
// 1
val key = drmInfo?.supportedSchemes?.get(0)
key?.let {
// 2
prepareDrm(key)
// 2
val keyRequest = getKeyRequest(
null, null, null,
MediaDrm.KEY_TYPE_STREAMING, null
)
provideKeyResponse(null, keyRequest.data)
}
}
Here you:
- Fetch the UUID, or key, of the DRM scheme in use. There are several types of DRM protection schemes. Examine the map of UUIDs in
drmInfo?.supportedSchemes?.get(0)
and retrieve the supported schemes. Schemes supported depend mainly on the device and OEM, if you ever get a DRM, you will need to dive deeper on this topic. - Pass this retrieved key to
prepareDrm()
to prepare the DRM. - Get the decrypt key from the licensed server using
getKeyRequest()
. - Then provide the key response from the license server to the DRM engine plugin using
provideKeyResponse()
.
Android Studio will most likely ask you to import the DRM library, so add the following line to the top of your file with your other imports:
import android.media.MediaDrm
This code is only for demonstration purposes. Because of this, it won't affect the app since you don't have access to any DRM protected files.
If you ever have to work with a DRM protected media file, a better alternative would be using ExoPlayer
because it provides more functionalities.
Where To Go From Here?
Congratulations on your first MediaPlayer app! You can download the final project using the Download Materials button at the top or bottom of this tutorial.
In this tutorial, you covered some basics of MediaPlayer
like:
- Understanding
MediaPlayer
and its states. - Playing video from the res/raw folder.
- Playing video from a URL.
- Async Programming.
- Best practices for media player.
- Digital Right Management.
While you covered a lot in this tutorial, there's still more to learn. For a next step, explore ExoPlayer. Google created ExoPlayer, a library that lets you take advantage of features not yet supported by MediaPlayer
API, such as DASH and SmoothStreaming. To learn more about ExoPlayer check out our ExoPlayer tutorial.
I hope you enjoyed this tutorial. If you have any questions or comments, please join the discussion below. :]