In meinem letzten Artikel “Implementing Video Playback on Android Jetpack Compose” habe ich erklaert, wie man Videos mit ExoPlayer in Jetpack Compose auf Android abspielt.
Ein Leser beobachtete folgendes Verhalten: Wenn die Beispiel-App in den Hintergrund versetzt wurde, spielte sie weiter. Er fragte, wie man ExoPlayer Lifecycle-bewusst machen kann, damit das Video stoppt, wenn die App pausiert wird.
Lass uns den Code aus dem letzten Artikel rekapitulieren, der ein @Composable ist, das den ExoPlayer in einer AndroidView haelt:
@Composable
fun VideoView(videoUri: String) {
val context = LocalContext.current
val exoPlayer = ExoPlayer.Builder(LocalContext.current)
.build()
.also { exoPlayer ->
val mediaItem = MediaItem.Builder()
.setUri(videoUri)
.build()
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
}
DisposableEffect(
AndroidView(factory = {
StyledPlayerView(context).apply {
player = exoPlayer
}
})
) {
onDispose { exoPlayer.release() }
}
}Was wir brauchen, ist eine aktuelle Instanz des LocalLifecycleOwner, die uns ueber Lifecycle-Events informiert. Hier ist die vollstaendige Loesung. Ich werde die Details danach Schritt fuer Schritt erklaeren.
@Composable
fun VideoView(videoUri: String) {
val context = LocalContext.current
val exoPlayer = ExoPlayer.Builder(LocalContext.current)
.build()
.also { exoPlayer ->
val mediaItem = MediaItem.Builder()
.setUri(videoUri)
.build()
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
}
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
DisposableEffect(
AndroidView(factory = {
StyledPlayerView(context).apply {
player = exoPlayer
}
})
) {
val observer = LifecycleEventObserver { owner, event ->
when (event) {
Lifecycle.Event.ON_PAUSE -> {
exoPlayer.pause()
}
Lifecycle.Event.ON_RESUME -> {
exoPlayer.play()
}
}
}
val lifecycle = lifecycleOwner.value.lifecycle
lifecycle.addObserver(observer)
onDispose {
exoPlayer.release()
lifecycle.removeObserver(observer)
}
}
}Lass mich einige Erklaerungen geben.
Zuerst holen wir die aktuelle Instanz des LifecycleOwner:
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)Innerhalb des Scope des DisposableEffect erstellen wir einen LifecycleEventObserver:
val observer = LifecycleEventObserver { owner, event ->
when (event) {
Lifecycle.Event.ON_PAUSE -> {
exoPlayer.pause()
}
Lifecycle.Event.ON_RESUME -> {
exoPlayer.play()
}
}
}Wenn die App pausiert (in den Hintergrund geht), pausiert auch der Player. Wenn die App fortgesetzt wird (in den Vordergrund zurueckkehrt), spielt der Player weiter.
Dann fuegen wir diesen Observer zur Lifecycle-Instanz hinzu:
val lifecycle = lifecycleOwner.value.lifecycle
lifecycle.addObserver(observer)Wir benoetigen auch eine weitere Zeile fuer die ordnungsgemaesse Bereinigung: Wenn die App geschlossen wird, muss der Observer vom Lifecycle entfernt werden:
lifecycle.removeObserver(observer)Das war’s! Ich hoffe, das hilft bei deinem Projekt.
Vielen Dank fuers Lesen!