Media Playback on Android with ExoPlayer: Getting Started
- Media Playback on the Android Framework
- Audio and Video
- Playing Media on Android
- Getting Started
- Project Structure
- Adding a Media Player to the Application
- Adding the Dependency
- Creating the View
- Creating the Player
- Attaching the Player to a View
- Customizing ExoPlayer
- Changing the Appearance
- Pros and Cons of ExoPlayer
- Where to Go From Here?
Playing music or videos is a very popular activity on Android devices. There are several ways of providing media playback in your Android app and, in this tutorial, you’ll learn how to use ExoPlayer to do this.
In this tutorial, you’ll build an Android app that allows you to watch videos from Cloudinary‘s free cloud-based video management solution. In the process, you’ll learn:
- How to add a media player to your app.
- How to customize the media player to fit your specific needs.
- The best practices for media player architecture.
- Additional capabilities ExoPlayer provides beyond the built in APIs.
Note: This tutorial assumes that you are familiar with the basics of Android development. If you are completely new to Android development, read through our Beginning Android Development tutorials first.
Media Playback on the Android Framework
Audio and Video
First, you’ll do a little experiment. Take out your mobile device and count the number of apps you interact with on a regular basis. How many of them have the ability to play some kind of media? In fact, count how many of them don’t have that possibility. You may find that the number is zero — it seems every single app a user interacts with on a daily basis can play some kind of media. This demonstrates just how important and popular media playback is on mobile devices.
But no matter the media type, they all have one thing in common: They have to get the media from somewhere to play it on your device.
Media used in an app can be stored on the local device’s storage. That same app can also allow you to stream the media from the Internet; in that case, some remote web server is a media source. Media can also be available through many other streaming technologies, but that’s beyond the scope of this tutorial.
So how do you play the media from any source? Before the hands-on part of this tutorial, you’ll first cover the different ways media can be played on the Android framework.
Playing Media on Android
The Android framework provides several options for media playback, covered below.
Sending Implicit Intent
Intent represents an app’s “intent to do something.” As with all implicit
Intents, you have to specify a general action that you want to perform.
For media playback, you must specify the
ACTION_VIEW. You also have to include a
URI of the media sample that you want to play. If there’s an app on the device that can handle that media type, the Android system launches it. This is useful for very simple use cases, the downside is you don’t play the media within your app — you use another app on the device that was built to handle the
YouTube Player API
To play a YouTube video, you can send an implicit
Intent to launch the YouTube app, which will then play a video. But you don’t have to do that. The YouTube Android Player API provides an embedded player to play YouTube videos directly in your app, and it gives you the possibility to customize the playback experience. This is useful if your use case is to play videos specifically from YouTube.
The Android multimedia framework includes support for playing a variety of common media types so that you can easily integrate audio, video and images into your apps. The MediaPlayer class is the primary entry point for playing sound and video. It supports the most common audio and video formats and data sources and because of that is good enough for many simple use cases. MediaPlayer is also very straightforward to use, but the downside is that it supports very little customization.
ExoPlayer is an open-source library that provides an alternative to Android’s MediaPlayer API for playing audio and video. ExoPlayer supports features not supported by Android’s MediaPlayer API, which you’ll see later, and it’s also easy to customize and extend.
Because of that, ExoPlayer is recommended for media player apps of any complexity on Android. ExoPlayer’s standard audio and video components are built on Android’s MediaCodec API, which was released in Android 4.1 (API level 16), which means ExoPlayer can only be used on devices running Android 4.1 or greater. This is also what you’ll use in this tutorial.
It is also possible to create a custom media player from low-level media APIs. The downside of this is that it’s very complicated and, in most cases unnecessary, other media-playing possibilities are good enough for almost every use case. Don’t reinvent the wheel. :]
To show you how to implement ExoPlayer in an app, you’ll create a simple app called FunTime that allows you to play videos from Cloudinary directly from the app.
You’ll use sample videos from Cloudinary as your media source. You’re not required to create an account for this library.
Download the materials for this tutorial using the Download Materials button at the top or bottom of the page. Open the starter project in Android Studio 3.0 or greater.
Now, build and run your app to make sure everything works as expected.
It’s helpful to go through the project structure briefly, so you’ll do that now.
The package names are pretty self-explanatory, but there are a few things that you need to notice, here.
The app is written using the Model-View-Presenter (MVP) architectural pattern. MVP is great way of organizing your code in Android. Some important advantages of using MVP are:
- It provides a clear separation of responsibilities between components which allows for easier understanding and maintenance of the code base.
- MVP provides a modular approach which allows you to switch to a different implementation of a view component in order to completely change the application’s UI, while all other components remain intact.
- Easier testing. Since there are well defined boundaries between components, it becomes much easier to test each component in isolation (e.g. by mocking other components).