ExoPlayer
ExoPlayer copied to clipboard
ExoPlayer in Jetpack Compose shows black screen when app is resumed after video is done playing
ExoPlayer Version
2.18.0
Devices that reproduce the issue
Samsung Galaxy S21 Ultra
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
Jetpack Compose implementation:
@Composable
fun VideoLayout(@RawRes rawResource: Int) {
val context = LocalContext.current
val uri = RawResourceDataSource.buildRawResourceUri(rawResource)
val mediaItem = MediaItem.fromUri(uri)
val exoPlayer = remember(context, mediaItem) {
ExoPlayer.Builder(context).build().apply {
addMediaItem(mediaItem)
prepare()
play()
repeatMode = REPEAT_MODE_OFF
}
}
DisposableEffect(exoPlayer) { onDispose { exoPlayer.release() } }
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = {
StyledPlayerView(it).apply {
player = exoPlayer
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
useController = false
}
}
)
}
- Play any video to the end (after which the last frame is kept on screen)
- Turn off the screen of the device
- Turn on the screen of the device
Expected result
The player keeps showing the last frame
Actual result
The player is showing a black screen
Media
Any video will do. Short videos are probably preferred since you need to play them to the end to reproduce the bug.
Bug Report
- [ ] You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
We can't really advise you on Compose details, but the important things that your code should ensure are:
- The player needs to be released when the Activity goes into background (=when the screen is turned off). In a normal activity this should happen in
onStopon API >= 24 andonPauseon API <= 23. - When the activity comes back into foreground (
onStarton API 24+,onResumeon API <=23) the player needs to be re-created from scratch and you can optionally seek to the previous playback position to resume from where you left off.
You can see this happening in the demo app (e.g. here, here and here), but I'm not sure how this can be translated to Compose. You may want to manage the lifecycle of the player outside of the composable function and only assign it to the created StyledPlayerView when needed.
Based on your description it sounds as if the player might not be correctly released when going into background or is not rebuilt when coming back into foreground. For example, based on the official documentation, it sounds like onDispose is not the right method to clean-up and it should rather happen inside a LifecycleEventObserver to match the requirements I listed above. At this point it becomes a generic question not really related to ExoPlayer, and you may get better answers by asking on sites like StackOverflow.
Thanks for the great reply! I'll try some stuff out
@DonnyRozendal Hello! Have you succeeded in solution finding?
No still haven't found a solution...
@DonnyRozendal I've tried to replace SurfaceView with TextureView and it helped me to prevent the last frame from getting black. But, there are several artifacts when I use it in LazyColumn
The UAMP demo app has recently been converted to Compose in this branch: https://github.com/android/uamp/tree/compose. This demo app isn't build for video playback, but maybe it helps for inspiration around how to integrate a player into a Compose view.
I think I close this issue as it seems more related to general Android developement. Built-in support for Compose is tracked by https://github.com/google/ExoPlayer/issues/9654.