ExoPlayer for media playback

Alex Chen Jan 2026
2 tabs
package com.example.myapp.ui.player

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.myapp.databinding.ActivityVideoPlayerBinding
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.DefaultDataSource
import com.google.android.exoplayer2.util.Util

class VideoPlayerActivity : AppCompatActivity() {

    private lateinit var binding: ActivityVideoPlayerBinding
    private var player: ExoPlayer? = null
    private var playWhenReady = true
    private var currentPosition = 0L
    private var currentWindow = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityVideoPlayerBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val videoUrl = intent.getStringExtra("video_url")
        videoUrl?.let { initializePlayer(it) }
    }

    private fun initializePlayer(videoUrl: String) {
        player = ExoPlayer.Builder(this)
            .build()
            .also { exoPlayer ->
                binding.playerView.player = exoPlayer

                val mediaItem = MediaItem.fromUri(videoUrl)
                exoPlayer.setMediaItem(mediaItem)

                // Restore playback state
                exoPlayer.playWhenReady = playWhenReady
                exoPlayer.seekTo(currentWindow, currentPosition)

                exoPlayer.addListener(object : Player.Listener {
                    override fun onPlaybackStateChanged(state: Int) {
                        when (state) {
                            Player.STATE_BUFFERING -> {
                                binding.progressBar.visibility = android.view.View.VISIBLE
                            }
                            Player.STATE_READY -> {
                                binding.progressBar.visibility = android.view.View.GONE
                            }
                            Player.STATE_ENDED -> {
                                // Video ended
                            }
                            Player.STATE_IDLE -> {
                                // Player idle
                            }
                        }
                    }

                    override fun onPlayerError(error: PlaybackException) {
                        // Handle playback error
                        showError(error.message ?: "Playback error")
                    }

                    override fun onIsPlayingChanged(isPlaying: Boolean) {
                        if (isPlaying) {
                            // Active playback
                        } else {
                            // Paused
                        }
                    }
                })

                exoPlayer.prepare()
            }
    }

    private fun releasePlayer() {
        player?.let { exoPlayer ->
            playWhenReady = exoPlayer.playWhenReady
            currentPosition = exoPlayer.currentPosition
            currentWindow = exoPlayer.currentMediaItemIndex
            exoPlayer.release()
        }
        player = null
    }

    override fun onStart() {
        super.onStart()
        if (Util.SDK_INT > 23) {
            intent.getStringExtra("video_url")?.let { initializePlayer(it) }
        }
    }

    override fun onResume() {
        super.onResume()
        if (Util.SDK_INT <= 23 || player == null) {
            intent.getStringExtra("video_url")?.let { initializePlayer(it) }
        }
    }

    override fun onPause() {
        super.onPause()
        if (Util.SDK_INT <= 23) {
            releasePlayer()
        }
    }

    override fun onStop() {
        super.onStop()
        if (Util.SDK_INT > 23) {
            releasePlayer()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        releasePlayer()
    }

    private fun showError(message: String) {
        // Show error toast or dialog
    }
}
2 files · kotlin Explain with highlit

ExoPlayer is a flexible media player supporting diverse formats and protocols. I create instances with ExoPlayer.Builder(context).build() and configure with MediaItem. Setting player.setMediaItem() and player.prepare() initializes playback. PlayerView displays video with controls. Listeners handle state changes via Player.Listener. Adaptive streaming works with DASH, HLS, and SmoothStreaming. Custom renderers extend capabilities. Caching reduces bandwidth with CacheDataSource. Background audio uses MediaSession for integration with system UI. ExoPlayer handles complex scenarios like DRM, captions, and 360-degree video. It's more customizable than MediaPlayer for modern streaming requirements.