kotlin
196 lines · 2 tabs
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
}
}
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()
}
}
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.
Related snips
kotlin
package com.example.myapp
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
Dependency injection with Hilt
kotlin
android
hilt
by Alex Chen
3 tabs
kotlin
package com.example.myapp.ui
import androidx.lifecycle.*
import kotlinx.coroutines.launch
class UserViewModel(
LiveData transformations and mediators
kotlin
android
livedata
by Alex Chen
1 tab
kotlin
package com.example.myapp.utils
import android.os.Build
import android.os.StrictMode
import android.os.Trace
import timber.log.Timber
Performance optimization and profiling
kotlin
android
performance
by Alex Chen
2 tabs
kotlin
package com.example.myapp.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
App widgets for home screen
kotlin
android
widget
by Alex Chen
2 tabs
kotlin
package com.example.myapp.data.repository
import com.example.myapp.data.local.PostDao
import com.example.myapp.data.local.PostEntity
import com.example.myapp.data.remote.ApiService
import com.example.myapp.models.Post
Unit testing with JUnit and MockK
kotlin
android
testing
by Alex Chen
2 tabs
kotlin
package com.example.myapp.utils
import android.app.NotificationChannel
import android.app.NotificationChannelGroup
import android.app.NotificationManager
import android.app.PendingIntent
Notification channels and categories
kotlin
android
notifications
by Alex Chen
1 tab
Share this code
Here's the card — post it anywhere.