Manage MediaPlayer state and resources

This document covers two areas with potential pitfalls.

  • State. With "Medialayer`, certain operations are valid only in specific states. Incorrect operations can cause exceptions or unexpected behavior.

  • Resources When you make configuration changes, such as screen rotation, You must release a MediaPlayer object to free up system resources and avoid resource exhaustion.

Manage state

MediaPlayer is state-based. That is, it has an internal state that you must always be aware of when you write your code, because certain operations are only valid when the player is in specific states. If you perform an operation while in the wrong state, the system may throw an exception or cause other undesirable behaviors.

The state diagram in the MediaPlayer class documentation clarifies which methods move the MediaPlayer from one state to another. For example:

  • When you create a new MediaPlayer, it is in the Idle state.
  • You initialize it by callingsetDataSource(), which changes it to the Initialized state.
  • You prepare it using either the prepare() or prepareAsync() method.
  • When the MediaPlayer is done preparing, it enters the Prepared state, which means you can call start() to make it play the media.

At that point, as the diagram illustrates, you can move between the Started, Paused and PlaybackCompleted states by calling such methods as start(), pause(), and seekTo(), among others.

When you call stop(), however, notice that you cannot call start() again until you prepare the MediaPlayer again.

Always keep the state diagram in mind when writing code that interacts with a MediaPlayer object, because calling its methods from the wrong state is a common cause of bugs.

Release the MediaPlayer

A MediaPlayer can consume valuable system resources. Therefore, you should always take extra precautions to make sure you are not hanging on to a MediaPlayer instance longer than necessary. When you are done with it, you should always call release() to make sure any system resources allocated to it are properly released.

For example, if you are using a MediaPlayer and your activity receives a call to onStop(), you must release the MediaPlayer, because it makes little sense to hold on to it while your activity is not interacting with the user (unless you are playing media in the background, which is discussed in the next section).

When your activity is resumed or restarted, of course, you need to create a new MediaPlayer and prepare it again before resuming playback.

Here's how you should release and then nullify your MediaPlayer:

Kotlin

mediaPlayer?.release()
mediaPlayer = null

Java

mediaPlayer.release();
mediaPlayer = null;

As an example, consider the problems that arise if you forget to release the MediaPlayer when your activity stops, but create a new one when the activity starts again. When the user changes the screen orientation (or changes the device configuration in another way), the system restarts the activity by default. You might quickly consume all of the system resources as the user rotates the device back and forth between portrait and landscape, because at each orientation change, you create a new MediaPlayer that you never release.

For more information about runtime restarts, see Handling Runtime Changes.

You may be wondering what happens if you want to continue playing "background media" even when the user leaves your activity, much in the same way that the built-in Music application behaves. In this case, what you need is a MediaPlayer controlled by a Service, as discussed in the next section

Learn more

Jetpack Media3 is the recommended solution for media playback in your app. Read more about it.

These pages cover topics relating to recording, storing, and playing back audio and video: