Building a video player app in Android (Part 4 / 5)
With ExoPlayer, Playlists, MediaSession, Audio Focus, PIP
The goal of this series of articles is to get you started with using ExoPlayer to build a simple, but feature rich, video player app (that supports playlists, MediaSession, Audio Focus, and Picture in Picture).
This is the fourth part of a 5 part series that includes:
- ExoPlayer introduction
- ExoPlayer playlists, UI customization, and events
- MediaSession Connector extension for ExoPlayer
- Supporting Audio Focus (this article)
- Supporting PIP
The previous article in the series covered the steps needed to connect your ExoPlayer instance to a MediaSession. This article gets into the details of supporting Audio Focus in the app.
Audio Focus
Android allows many apps to play audio simultaneously by automatically mixing all the audio streams together. However, it is disruptive to the user if they hear multiple apps playing audio at the same time. It’s like many people trying to talk to a user at the same time, the result of which is that they can’t really hear or pay attention to any one person. To avoid this, Android provides an API that allows apps to share audio focus, where only one app can hold audio focus at any given time.
You can learn more about the details of audio focus and how to implement it from the following sources.
- Understanding Audio Focus articles on medium. This article is a deep dive on what audio focus is, what ducking is, what AudioAttributes are, and what important use cases that you should consider for your app.
- Android sample app that uses Audio Focus. There’s an
AudioFocusHelper
class that handles audio focus (that’s written in Java).
Kotlin implementation using ExoPlayer
It is easy to use the delegation pattern in Kotlin in order to create a subclass that uses an instance of the superclass to provide all the inherited behaviors. This way you can just focus on the differences in your subclass without writing any boilerplate code. The following code shows how the SimpleExoPlayer
class can extended with the ability to handle audio focus. You can use this class just as you would a SimpleExoPlayer
, by passing the type of audio focus that you require for your app (using AudioAttributes
).
Here’s the code snippet to create audio attributes for an app that plays music (audio track for our video files).
Here’s the code snippet for the AudioFocusWrapper
class that extends SimpleExoPlayer
.
PIP and Audio Focus
So far, our app doesn’t work in the background. As soon as any other app is launched, or the user switches to the home screen, playback stops. So there isn’t really much use for Audio Focus in this case. However, as soon as you add the ability for the app to minimize itself into a small window and play media while other apps are running, audio focus becomes hugely important.
Imagine this scenario, you launch the video player app and start playing a video, then minimize it into a PIP window, and then launch YouTube. At this point, both YouTube and the video player app are visible to the user.
- When you choose to play a video in YouTube app, this should pause playback in the sample app.
- When you choose to play a video in the sample app, this should pause playback in the video app.
We will explore this in the next (and final) article in this series 👍.
Source code on GitHub
By following these 5 articles, you should be able to create a video player app that is similar to this sample we have created (which you can get from Android Studio as well).
Resources for further learning
ExoPlayer
- IO17 ExoPlayer codelab
- IO14 ExoPlayer Introduction Video
- IO17 ExoPlayer Session Video
- Why ExoPlayer?
- Latest changes for ExoPlayer v2.6.1
MediaSession, Audio Focus
DASH, HLS
Picture in Picture