Implementing Exoplayer for Beginners in Kotlin
Hi Developers!! This post is based on implementing Exoplayer Library to play media files on Android.
Android framework provides classes such as MediaPlayer
and AudioManager
to play media files. Exoplayer is an open source library by Google to play media files. This blog will guide you through process of implementing a SimpleExoPlayer
to play audio files.
Which media player to use??
There are different ways to play media files on android devices. From using the default APIs provided the android framework to external libraries, there are whole lot of options. You can even create your own media player using the Codec classes included in the android framework.
- MediaPlayer : It is provided by the Android Framework and provides the basic implementation of the media player. It is useful to play media in a player with little/no customization options.
- ExoPlayer : It is an open source library maintained by Google. It provides many customization options and supports a wide range of media files including DASH and HLS streaming which is not supported by the MediaPlayer. **Important : It works on Android 4.1 and above.**
- Custom Player : You can build custom media player using the
MediaCodec
,AudioTrack
andMediaDrm
classes.
How does it work?
Media player contains 2 main components i.e. MediaController and MediaSession. MediaController is used to decode the media and play it. Usually both are tied with a predefined set of callbacks (play, pause, stop, etc).
Media Session
It is used to decode and play the media. It is also used for communication with the player from the app’s UI or the external clients such as Android Wear and Android Auto. You can call it the public face of your player which stores the information about the state of the player and the meta data about the media being played.
It is made up of 2 components i.e. PlaybackStateCompact
and MediaMetaDataCompact
. PlaybackStateCompact
contains the state of the app. It can also be used to change the state of the app. The MediaMetaDataCompact
class contains the metadata about the media, For Example: Name of the media, album art etc.
MediaController
It isolates the UI from the player. The UI components do not directly communicate with the player but with the controller which converts the actions to callbacks for the media session. The controller can also receive callbacks from the media session about the changes in state and accordingly update the UI. It can connect to only one media session at a time.
Where to Implement?
The main components of an music app, i.e. MediaSession and MediaController can both be defined in 2 ways :
- Both are defined in the Activity.
- MediaPlayer is defined in activity and MediaSession in service.
The implementation depends on the type of player you are building. If you are making a video player, the MediaSession and Controller should be implemented in the activity as the user leaves the activity, it is expected that the playback is stopped. In case of an audio app, it is expected that even if the user leaves the activity, the playback continues in the background so the controller can be setup in the activity whereas the session can be in a service.
This blog is based on implementing an audio app without the service component.
Lets get started!!
Step 1 : Adding the Dependencies.
Add the dependency of Exoplayer by adding the below line in your build.gradle
file. Before adding the dependency, make sure to add the JCenter and Google repository.
repositories {
jcenter()
google()
}
The next step is to add the exoplayer dependency to the app module. The below dependency is used to add full library.
compile 'com.google.android.exoplayer:exoplayer:2.X.X'
Where 2.X.X
is the preferred version.
If you want to add particular feature of the exoplayer such as DASH streaming or core features, add the below lines.
compile 'com.google.android.exoplayer:exoplayer-core:2.X.X'
compile 'com.google.android.exoplayer:exoplayer-dash:2.X.X'
compile 'com.google.android.exoplayer:exoplayer-ui:2.X.X'
Step 2 : Adding view
After you have added the dependencies, the next step is to add a container view that will display the media. Exoplayer library provides SimpleExoPlayerView
to display video, subtitles, album art during playback and displays playback controls using PlaybackControlView
.
In your xml
file, add the following line of code to add a SimpleExoPlayerView
.
Step 3 : Initializing the ExoPlayer
After adding the container view, it is time to initialize the player with a media file. SimpleExoPlayer
can be initialized by calling newSimpleInstance()
method that takes in 2 arguments, i.e. context and a TrackSelector.
TrackSelector class is responsible for selecting the tracks that the Renderers will consume.
val trackSelector = DefaultTrackSelector()val exoPlayer = SimpleExoPlayer.newSimpleInstance(baseContext,trackSelector)exoPlayerView?.player = exoPlayer
After the exoPlayer
is initialized, a MediaSession is to be created to control the playback state and store the media metadata. To create a media session, call the MediaSessionCompact
constructor. The constructor expects arguments such as the context, tagName (short name for debugging purposes), componentName and a Pending Intent (for your receiver component that handle the media callbacks).
val componentName = ComponentName(baseContext, "MainActivity")val mediaSession = MediaSessionCompact(baseContext, "MainActivity", componentName, null)
Even after the media session is created, it will not be published to the system until the setActive()
method is called.
Currently, our media session is missing 1 main component i.e. PlaybackStateCompact. You can create an instance by using the PlaybackStateCompact.Builder()
and calling build()
method. Before calling the build method, it has to be configured to set the current capabilities of the session. After the playbackStateCompactBuilder
is configured, connect it to the media session using the setPlaybackState()
method.
val playbackStateCompactBuilder = PlaybackStateCompact.Builder()playbackStateCompactBuilder.setActions(
PlaybackStateCompact.ACTION_PLAY,
PlaybackStateCompact.ACTION_PAUSE,
PlaybackStateCompact.ACTION_FAST_FORWARD)mediaSession.setPlaybackState(playbackStateCompactBuilder.build())mediaSession.isActive = true
Its almost done!! Our Exoplayer is initialized and media session has been created. Now is time to add a media file that our player will play.
Create an assets
folder and add the mp3
file in it. Next, get the Uri of the file and create a MediaSource
. MediaSource class is used to define and provide the media to be played by the player.
val mediaUri = Uri.parse("asset:///heart_attack.mp3")val userAgent = Util.getUserAgent(baseContext, "ExoPlayer")val mediaSource = ExtractorMediaSource(mediaUri,
DefaultDataSourceFactory(baseContext, userAgent),
DefaultExtractorsFactory(), null, null)exoplayer?.prepare(mediaSource)
That’s it! You can find this project on Github here
This post completes the implementation of the Exoplayer for local file.. Hope it helps you to be comfortable with setting up an database for your app
If you liked it, show some love 👏🏻and share more! Keep practicing and happy coding!