Create media session during playback allowing for external control (#640)

## Description
Creates a `MediaSession` during playback which allows for external
control such as via smart speakers, Google Home app, etc

Note: one limitation is that seeking previous/next items in the playlist
isn't supported. This is because Wholphin manages that independent of
the `Player`, so additional dev work is needed for this.

### Related issues
Closes #622
Might help with #415
This commit is contained in:
Ray 2026-01-07 12:49:43 -05:00 committed by GitHub
parent 79c614218d
commit 49740c47cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 10 additions and 0 deletions

View file

@ -196,6 +196,7 @@ dependencies {
implementation(libs.androidx.hilt.work)
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.media3.session)
implementation(libs.androidx.media3.datasource.okhttp)
implementation(libs.androidx.media3.exoplayer.hls)
implementation(libs.androidx.media3.ui)

View file

@ -21,6 +21,7 @@ import androidx.media3.exoplayer.DecoderCounters
import androidx.media3.exoplayer.DecoderReuseEvaluation
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.analytics.AnalyticsListener
import androidx.media3.session.MediaSession
import coil3.imageLoader
import coil3.request.ImageRequest
import coil3.size.Size
@ -134,6 +135,7 @@ class PlaybackViewModel
val player by lazy {
playerFactory.createVideoPlayer()
}
private val mediaSession: MediaSession
internal val mutex = Mutex()
val controllerViewState =
@ -177,10 +179,15 @@ class PlaybackViewModel
}
jobs.forEach { it.cancel() }
player.release()
mediaSession.release()
}
viewModelScope.launch(ExceptionHandler()) { controllerViewState.observe() }
player.addListener(this)
(player as? ExoPlayer)?.addAnalyticsListener(this)
mediaSession =
MediaSession
.Builder(context, player)
.build()
jobs.add(subscribe())
jobs.add(listenForTranscodeReason())
}
@ -1031,6 +1038,7 @@ class PlaybackViewModel
Timber.v("release")
activityListener?.release()
player.release()
mediaSession.release()
activityListener = null
}