Skip to main content

Working with Media Playback

1. Playing Audio with MediaPlayer

Property Description Values
setDataSource() Sets the data source (file path or URL) for the MediaPlayer String (file path or URL)
prepare() Prepares the MediaPlayer for playback void
start() Begins playback of the audio void
pause() Pauses the current playback void
stop() Stops the current playback void
release() Releases the resources used by MediaPlayer void

Example: Basic Audio Playback

import android.media.MediaPlayer
import java.io.IOException

class AudioPlayer {
    private var mediaPlayer: MediaPlayer? = null

    fun playAudio(filePath: String) {
        try {
            mediaPlayer = MediaPlayer()
            mediaPlayer?.setDataSource(filePath)
            mediaPlayer?.prepare()
            mediaPlayer?.start()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    fun pauseAudio() {
        mediaPlayer?.pause()
    }

    fun stopAudio() {
        mediaPlayer?.stop()
        mediaPlayer?.release()
        mediaPlayer = null
    }
}
Note: Ensure the audio file path is accessible and the app has necessary permissions to read from storage.

2. Controlling Playback

Property Description Values
playbackState Current state of the media player PLAYING, PAUSED, STOPPED
playbackPosition Current position in the media stream (in milliseconds) Long
duration Total duration of the media (in milliseconds) Long
isPlaying Indicates if media is currently playing Boolean

Example: Controlling Playback State

val player = ExoPlayer.Builder(context).build()
player.playbackState // Returns PLAYING, PAUSED, or STOPPED
player.seekTo(10000) // Seek to 10 seconds
player.play() // Start playback
player.pause() // Pause playback
Note: Use player.seekTo() to jump to a specific position in the media.
Warning: Ensure that player.play() is called after setting up the media source to begin playback.

3. Managing MediaPlayer Lifecycle

State Description Methods Notes
Idle Initial state before calling setDataSource() setDataSource(), prepare() Can transition to Initialized
Initialized After setDataSource() is called prepare(), release() Can transition to Prepared or Idle
Prepared After prepare() completes successfully start(), pause(), stop() Can transition to Started, Paused, or Stopped
Started When playback is active pause(), stop(), seekTo() Can transition to Paused or Stopped
Paused Playback is paused start(), stop() Can transition back to Started or Stopped
Stopped Playback has stopped prepare(), release() Can transition to Prepared or Idle
Error Playback error occurred release() Must call release() to exit this state

Example: MediaPlayer Lifecycle Management

class MediaPlaybackManager {
    private val mediaPlayer = MediaPlayer()

    fun playMedia(uri: Uri) {
        try {
            mediaPlayer.setDataSource(context, uri)
            mediaPlayer.prepare()
            mediaPlayer.start()
        } catch (e: Exception) {
            Log.e("MediaPlayer", "Error preparing media", e)
            mediaPlayer.release()
        }
    }

    fun pauseMedia() {
        if (mediaPlayer.isPlaying) {
            mediaPlayer.pause()
        }
    }

    fun stopMedia() {
        mediaPlayer.stop()
        mediaPlayer.reset()
    }

    fun releaseMedia() {
        mediaPlayer.release()
    }
}
Note: Always call release() when done to free up resources.
Warning: Never call prepare() on the main thread — use prepareAsync() instead.

4. Playing Video with VideoView

Property Values Description
videoURI String URI of the video to be played
videoPath String File path of the video to be played
setOnPreparedListener MediaPlayer.OnPreparedListener Callback when video is ready to play
setOnCompletionListener MediaPlayer.OnCompletionListener Callback when video finishes playing

Example: Setting up VideoView in Kotlin

import android.net.Uri
import android.os.Bundle
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val videoView = findViewById<VideoView>(R.id.videoView)
        val videoPath = "android.resource://$packageName/${R.raw.sample_video}"
        val uri = Uri.parse(videoPath)

        videoView.setVideoURI(uri)
        videoView.start()
    }
}
Note: Ensure that the video file is placed in the res/raw directory for local playback.
Warning: VideoView does not support all video formats. It is recommended to use MP4 or 3GP formats for better compatibility.

5. Using MediaController

The MediaController class in Android provides a standardized way to control media playback from a remote source, such as a notification or a media transport control. It allows you to send commands like play, pause, skip, and more.

Property Description Notes
mediaSession Instance of MediaSessionCompat Required to bind the controller to a session
transportControls Instance of TransportControls Used to send playback commands to the session

Example: Initializing MediaController

val mediaSession = MediaSessionCompat(this, "MediaSession")
val mediaController = MediaControllerCompat(this, mediaSession.sessionToken)

// Set up transport controls
val transportControls = mediaController.transportControls

Example: Controlling Playback

// Play media
transportControls.play()

// Pause media
transportControls.pause()

// Skip to next item
transportControls.skipToNext()

// Skip to previous item
transportControls.skipToPrevious()
Note: The MediaController requires a valid session token to communicate with the media session.
Warning: Ensure that MediaSessionCompat is properly initialized before creating the controller.

6. Handling Playback Errors

Error Type Description Handling Strategy Code Example
MEDIA_ERROR_UNKNOWN Generic error code for unknown media errors Log the error and notify user
override fun onError(errorCode: Int, error: String?) {
    Log.e("MediaPlayer", "Unknown media error: $error")
}
MEDIA_ERROR_IO IO error during media playback Check file path and permissions
override fun onError(errorCode: Int, error: String?) {
    if (errorCode == MediaPlayer.MEDIA_ERROR_IO) {
        // Retry or switch to alternative media source
    }
}
MEDIA_ERROR_MALFORMED Malformed media file format Validate media file or prompt user to select another
override fun onError(errorCode: Int, error: String?) {
    if (errorCode == MediaPlayer.MEDIA_ERROR_MALFORMED) {
        // Show error dialog to user
    }
}
MEDIA_ERROR_UNSUPPORTED Unsupported media format or codec Inform user to use supported formats
override fun onError(errorCode: Int, error: String?) {
    if (errorCode == MediaPlayer.MEDIA_ERROR_UNSUPPORTED) {
        // Suggest alternative media formats
    }
}

Example: Error Handling in MediaPlayer

class MediaErrorHandler : MediaPlayer.OnErrorListener {
    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        when (what) {
            MediaPlayer.MEDIA_ERROR_UNKNOWN -> {
                Log.e("MediaPlayer", "Unknown error occurred")
            }
            MediaPlayer.MEDIA_ERROR_IO -> {
                Log.e("MediaPlayer", "IO error occurred")
            }
            MediaPlayer.MEDIA_ERROR_MALFORMED -> {
                Log.e("MediaPlayer", "Malformed media file")
            }
            MediaPlayer.MEDIA_ERROR_UNSUPPORTED -> {
                Log.e("MediaPlayer", "Unsupported media format")
            }
        }
        return true
    }
}
Note: Always return true from onError to indicate that the error has been handled.
Warning: Never attempt to resume playback after a MEDIA_ERROR_UNKNOWN as it might lead to further instability.

7. Managing Audio Focus

Property Description Values
audioFocusRequest Request object for audio focus AudioFocusRequest
onAudioFocusChange Callback when audio focus changes (focusChange: Int) -> Unit

Example: Requesting Audio Focus

val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
    .setOnAudioFocusChangeListener { focusChange ->
        when (focusChange) {
            AudioManager.AUDIOFOCUS_LOSS -> {
                // Pause playback
            }
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
                // Pause playback temporarily
            }
            AudioManager.AUDIOFOCUS_GAIN -> {
                // Resume playback
            }
        }
    }
    .build()

val result = audioManager.requestAudioFocus(focusRequest)
Note: Always release audio focus when done to allow other apps to use it.

Example: Releasing Audio Focus

audioManager.abandonAudioFocusRequest(focusRequest)

8. Playing Audio in Background

Property Description Values
mediaSession Session for managing media playback MediaSessionCompat
mediaPlayer MediaPlayer instance for audio playback MediaPlayer
audioAttributes Audio attributes for playback AudioAttributes.Builder()

Example: Setting up background audio playback

val mediaPlayer = MediaPlayer()
mediaPlayer.setDataSource("https://example.com/audio.mp3")
mediaPlayer.prepare()
mediaPlayer.start()
Note: Ensure android.permission.FOREGROUND_SERVICE is declared in manifest for background playback.
Warning: Do not use MediaPlayer in UI thread to avoid blocking the main thread.
Permission Description Status
android.permission.FOREGROUND_SERVICE Required for background audio playback NEW
android.permission.WAKE_LOCK Prevents device from sleeping during playback NEW

9. Using ExoPlayer

ExoPlayer is a powerful media playback library for Android, offering more control and flexibility than the built-in MediaPlayer. It supports a wide range of media formats and provides features like adaptive streaming, subtitles, and custom renderers.

Feature Description Notes
Player ExoPlayer Main interface for media playback
DataSource DefaultDataSourceFactory Handles media data fetching
Renderer MediaCodecVideoRenderer Renders video content
TrackSelector DefaultTrackSelector Selects audio/video tracks

Example: Basic ExoPlayer Setup

val player = ExoPlayer.Builder(context).build()
val mediaItem = MediaItem.Builder()
    .setUri("https://example.com/video.mp4")
    .build()
player.setMediaItem(mediaItem)
player.prepare()
player.play()

Example: Setting Up Player with Custom DataSource

val dataSourceFactory = DefaultDataSourceFactory(context, "user-agent")
val player = ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(dataSourceFactory))
    .build()
Note: Ensure you have the necessary permissions in AndroidManifest.xml for network access if streaming media.
Warning: Always release the ExoPlayer instance to free up resources when done.

Key Features of ExoPlayer

  • Supports DASH, HLS, and SmoothStreaming adaptive streaming
  • Customizable renderers for audio/video
  • Subtitle support (SRT, VTT)
  • Supports multiple audio tracks and languages
  • Can handle live streams

10. Implementing Playback Controls

Control Description Code Example
Play Starts or resumes media playback mediaPlayer.start()
Pause Pauses the currently playing media mediaPlayer.pause()
Stop Stops the media playback and resets to beginning mediaPlayer.stop()
SeekTo Seeks to a specific position in the media mediaPlayer.seekTo(5000)
SetVolume Sets the volume level for playback mediaPlayer.setVolume(0.5f, 0.5f)
Note: Ensure that the MediaPlayer is in a valid state before calling these control methods.

11. Using Media3 Library

Example: Basic Media3 Player Setup

import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.util.EventLogger

val player = ExoPlayer.Builder(context).build()
val dataSourceFactory = DefaultDataSource.Factory(context)
val mediaItem = MediaItem.fromUri("https://example.com/audio.mp3")
player.setMediaItem(mediaItem)
player.prepare()
player.play()
Property Description Values
ExoPlayer.Builder Creates a new ExoPlayer instance context
setMediaItem Sets the media item to be played MediaItem
prepare Prepares the player for playback void
play Starts playback of the media void
Note: Media3 is the modern media playback library for Android, replacing ExoPlayer 2.x.
Warning: Ensure you have proper permissions for audio playback in your manifest.

Key Features of Media3

  • Supports multiple media formats (MP4, WebM, HLS, DASH)
  • Handles adaptive streaming
  • Provides extensive customization options
  • Integrates well with Android Jetpack components

Was this article helpful?