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.

4.6 (5) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

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.

Playing video selected from gallery

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.

All Done!

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:

  1. 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.
  2. Pass this retrieved key to prepareDrm() to prepare the DRM.
  3. Get the decrypt key from the licensed server using getKeyRequest().
  4. 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.

All done!

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. :]