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 | |
| MEDIA_ERROR_IO | IO error during media playback | Check file path and permissions | |
| MEDIA_ERROR_MALFORMED | Malformed media file format | Validate media file or prompt user to select another | |
| MEDIA_ERROR_UNSUPPORTED | Unsupported media format or codec | Inform user to use supported 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.
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.