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
}
}
package com.example.myapp.services
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.session.MediaSessionCompat
import androidx.media.MediaBrowserServiceCompat
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
class AudioPlayerService : MediaBrowserServiceCompat() {
private lateinit var player: ExoPlayer
private lateinit var mediaSession: MediaSessionCompat
private lateinit var mediaSessionConnector: MediaSessionConnector
override fun onCreate() {
super.onCreate()
player = ExoPlayer.Builder(this).build()
val sessionActivityPendingIntent = packageManager
?.getLaunchIntentForPackage(packageName)
?.let { sessionIntent ->
PendingIntent.getActivity(
this,
0,
sessionIntent,
PendingIntent.FLAG_IMMUTABLE
)
}
mediaSession = MediaSessionCompat(this, "AudioPlayerService")
.apply {
setSessionActivity(sessionActivityPendingIntent)
isActive = true
}
sessionToken = mediaSession.sessionToken
mediaSessionConnector = MediaSessionConnector(mediaSession).also {
it.setPlayer(player)
}
}
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot {
return BrowserRoot("root", null)
}
override fun onLoadChildren(
parentId: String,
result: Result<MutableList<MediaBrowserCompat.MediaItem>>
) {
result.sendResult(mutableListOf())
}
override fun onDestroy() {
super.onDestroy()
mediaSession.release()
mediaSessionConnector.setPlayer(null)
player.release()
}
}
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.