Maybe some of you are shaking your head at the fact that we need to use some external library for such a common task. Well, Android does provide us with the MediaPlayer class, but its options are not sufficient in most cases.
Exoplayer is an open-source library from Google, which, unlike MediaPlayer, is more stable, much more customizable and easier to use.
The first step we need to do is to add a new library to an existing project. Currently, the latest version of the library is 2.18.1. You can check the latest release version here https://github.com/google/ExoPlayer/releases.
The next step is to create a @Composable function, which will be stretched over the entire screen area and will represent the space for placing the player. In this composable, we will create an Exoplayer object using the ExoPlayer.Builder call, to which we need to send the context of the given composable. Subsequently, we will additionally edit it:
When we have the exoplayer object set up correctly, we need to create some @Composable that will contain the UI of the playing video and its controls. Currently, the Exoplayer library is not yet adapted for Compose, but we can adapt it ourselves 🙂 using @Composable AndroidView, in which we can insert the classic view that we would use in the case of using xml, in our case StyledPlayerView.
Using the apply function, we can set the same parameters for this "composed view" as we could set for the view in the xml file. According to the resizeMode parameter, we can set the span of the video. In this case, the size of the video is adjusted to the size of the screen, keeping the original aspect ratio. We insert the exoplayer object we created in the previous step into the player parameter. Now we are all done and ready to start the video!
… but …
… if you go back to the previous screen, you can see that the video is still playing in the background, even though the screen is no longer part of the composition. This is because the player was not properly released and did not release the resources it was using. We can solve this problem using the DisposableEffect effect provided by the Compose API. For our use, all we need to know about this effect is that the body of the effect is executed whenever its key1 parameter changes, and that the callback method onDispose{} is executed whenever the composable leaves the composition. And this feature is key for us. It is in this part that we can call exoPlayer.release().
Now when we go back to the previous screen the video stops playing, however if we just put the app in the background the video will continue to play because it is still part of the composition and the onDispose{} callback hasn't been called. To solve this problem, we need to get an instance of the LocalLifecycleOwner class, which we need to listen for activity lifecycle changes.
Subsequently, we will create a LifecycleEventObserver implementation in DisposableEffect, which will either stop or start the player, depending on whether the application is in the foreground or in the background. We must bind this observer to the life cycle of the activity and we must also remove it when leaving the composition, again in the onDispose{} callback.
The whole code after editing is here 🙂
That is all. The implementation is not completely trivial, but I hope it will help you in your project 🙂