How Can Play Again Video in Exoplayer
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, yous'll larn how to employ ExoPlayer to practise this.
ExoPlayer is a media playback library for Android which provides an alternative to Android'south MediaPlayer API. ExoPlayer is used past YouTube and Play Movies for video playback.
In this tutorial, you lot'll build an Android app that allows you to lookout man videos from Cloudinary'south complimentary cloud-based video direction solution. In the procedure, you lot'll acquire:
- 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.
Notation: This tutorial assumes that you are familiar with the basics of Android development. If you are completely new to Android development, read through our Start Android Development tutorials first.
Media Playback on the Android Framework
Audio and Video
First, you'll practice a little experiment. Have out your mobile device and count the number of apps you interact with on a regular footing. How many of them take the ability to play some kind of media? In fact, count how many of them don't accept that possibility. Y'all may detect 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.
Only no matter the media type, they all take one matter in common: They have to become 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 tin likewise allow you to stream the media from the Internet; in that instance, some remote spider web server is a media source. Media can as well be bachelor through many other streaming technologies, merely that's beyond the telescopic of this tutorial.
And then how do you play the media from any source? Earlier the hands-on function of this tutorial, you'll get-go cover the dissimilar ways media can exist played on the Android framework.
Playing Media on Android
The Android framework provides several options for media playback, covered beneath.
Sending Implicit Intent
An Intent
represents an app's "intent to do something." Every bit with all implicit Intent
due south, you take to specify a full general activeness that you want to perform.
For media playback, yous 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 tin can handle that media blazon, the Android organisation launches it. This is useful for very unproblematic utilize cases, the downside is you don't play the media within your app — yous use another app on the device that was built to handle the Intent
.
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 straight 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.
MediaPlayer
The Android multimedia framework includes support for playing a variety of mutual media types so that you tin easily integrate audio, video and images into your apps. The MediaPlayer class is the primary entry point for playing audio and video. Information technology supports the virtually mutual audio and video formats and data sources and because of that is good enough for many simple employ cases. MediaPlayer is besides very straightforward to use, but the downside is that it supports very petty customization.
ExoPlayer
ExoPlayer is an open-source library that provides an culling to Android's MediaPlayer API for playing audio and video. ExoPlayer supports features non supported past Android's MediaPlayer API, which yous'll come across later, and information technology's too piece of cake to customize and extend.
Because of that, ExoPlayer is recommended for media player apps of any complexity on Android. ExoPlayer'due south standard sound and video components are built on Android's MediaCodec API, which was released in Android 4.1 (API level sixteen), which means ExoPlayer tin can simply exist used on devices running Android four.1 or greater. This is also what you lot'll apply in this tutorial.
Custom Thespian
Information technology is also possible to create a custom media thespian from low-level media APIs. The downside of this is that it'southward very complicated and, in most cases unnecessary, other media-playing possibilities are adept plenty for almost every use case. Don't reinvent the bike. :]
Getting Started
To show you how to implement ExoPlayer in an app, yous'll create a simple app called FunTime that allows you to play videos from Cloudinary straight from the app.
You'll use sample videos from Cloudinary as your media source. Yous're not required to create an account for this library.
Download the materials for this tutorial using the Download Materials push at the acme 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.
You should get a screen like this:
Project Construction
It'southward helpful to go through the project construction briefly, so you'll exercise that now.
The bundle names are pretty self-explanatory, but in that location are a few things that yous need to notice, hither.
The app is written using the Model-View-Presenter (MVP) architectural pattern. MVP is great manner of organizing your lawmaking in Android. Some of import advantages of using MVP are:
- It provides a clear separation of responsibilities betwixt components which allows for easier understanding and maintenance of the lawmaking base.
- MVP provides a modular approach which allows you to switch to a different implementation of a view component in order to completely alter the application's UI, while all other components remain intact.
- Easier testing. Since there are well divers boundaries between components, it becomes much easier to exam each component in isolation (due east.thou. by mocking other components).
Calculation a Media Histrion to the Application
The main screen shows you a listing of sample video names that are fetched from Cloudinary.
When you lot click on a list particular VideoViewActivity
launches, merely shows nothing in the starter project. This is where your video is going to be displayed.
Calculation the Dependency
Recall that ExoPlayer is a library, in order to apply it y'all have to add it to the projection first. The ExoPlayer library is split into modules to permit developers to import only a subset of the functionality provided by the total library. The benefits of depending on only the modules you need are that you become a smaller APK size and you don't include the features in your app that you aren't going to utilize.
These are the available modules and their purpose:
-
exoplayer-core
: Core functionality (required). -
exoplayer-dash
: Support for Nuance content. -
exoplayer-hls
: Back up for HLS content. -
exoplayer-smoothstreaming
: Support for SmoothStreaming content. -
exoplayer-ui
: UI components and resources for use with ExoPlayer.
It's yet possible to depend on the full library if you prefer which is equivalent to depending on all of the modules individually.
For the sake of simplicity we'll add the full library.
Open up your app module level build.gradle
file and add the post-obit dependency to the dependencies
block:
implementation 'com.google.android.exoplayer:exoplayer:' + projection.ext.exoPlayerVersion
The ExoPlayer version constant is already added to the project level build.gradle
file so you can only use that version.
Sync the project after adding the dependency.
Creating the View
Next, yous'll create the view. If yous were using Android's MediaPlayer API you would display videos in a SurfaceView
. The ExoPlayer library provides it's own high level view for media playback. It displays video, subtitles and album fine art, and besides displays playback controls.
To add it, open the activity_video_view.xml
layout file from res/layout
and replace the contents with the following:
<?xml version="ane.0" encoding="utf-eight"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.video.VideoViewActivity"> <com.google.android.exoplayer2.ui.PlayerView android:id="@+id/ep_video_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
Open the VideoViewActivity.kt file in the iu.video
package and add together a property for the PlayerView
:
private lateinit var videoView: PlayerView
Initialize the view in the init()
method:
videoView = findViewById(R.id.ep_video_view)
Creating the Player
Since you're using the MVP pattern in this projection, you will decouple the view from the player. Start by creating a new com.raywenderlich.funtime.device.player
package.
Inside this parcel, create a MediaPlayer
interface, which is going to describe the behavior for the media player, and a MediaPlayerImpl
class, which will contain the concrete implementation of your media histrion. Make the MediaPlayerImpl
class implement the MediaPlayer
interface.
Using the MediaPlayer
interface makes swapping thespian implementations a breeze. You might want to explore creating alternate implementations without using ExoPlayer to explore the Android Media APIs more than deeply.
Now, open the MediaPlayerImpl
grade. Offset, you need to initialize your player.
Add together a holding called exoPlayer
for the actor:
private lateinit var exoPlayer: ExoPlayer
Besides add a belongings for the context that you'll ready and use later on:
individual lateinit var context: Context
Side by side, add the initializePlayer()
method where you're going to create a new instance of ExoPlayer and assign it to the exoPlayer fellow member variable.
You can create an ExoPlayer
instance using ExoPlayerFactory
. The factory provides a range of methods for creating ExoPlayer
instances with varying levels of customization. Simply, for most use cases, y'all should utilise 1 of the ExoPlayerFactory.newSimpleInstance
methods.
Initialize exoPlayer
in the method like this:
private fun initializePlayer() { val trackSelector = DefaultTrackSelector() val loadControl = DefaultLoadControl() val renderersFactory = DefaultRenderersFactory(context) exoPlayer = ExoPlayerFactory.newSimpleInstance( renderersFactory, trackSelector, loadControl) }
ExoPlayerFactory.newSimpleInstance()
takes three parameters:
- A RenderersFactory that creates renderer instances for use by
ExoPlayer
; they render media from some stream. - A TrackSelector is responsible for selecting tracks to be consumed past each of the role player'south renderers.
- A LoadControl that controls the buffering of the media.
Don't worry about the specifics of these classes; using the default classes works perfectly in near use cases.
Crawly, you created an instance of the ExoPlayer
!
You desire your player to accept the power to play media, so describe that in the MediaPlayer
interface past calculation the post-obit method:
fun play(url: String)
Implement that method in the MediaPlayerImpl
class.
This is how you lot play the media with ExoPlayer
:
override fun play(url: String) { //1 val userAgent = Util.getUserAgent(context, context.getString(R.string.app_name)) //two val mediaSource = ExtractorMediaSource .Manufacturing plant(DefaultDataSourceFactory(context, userAgent)) .setExtractorsFactory(DefaultExtractorsFactory()) .createMediaSource(Uri.parse(url)) //three exoPlayer.prepare(mediaSource) //4 exoPlayer.playWhenReady = true }
Going through this stride by step:
- A
UserAgent
is just a cord that is generated for y'all based on the given awarding name and library version. You'll utilize information technology in next step. - In
ExoPlayer
, every slice of media is represented by aMediaSource
. To play a piece of media, you must get-go create a correspondingMediaSource
. Again, there's a factory for media source cosmos that takes a data source mill as a parameter. Data source is a component from which streams of data can be read. Yous accept to set theExtractorsFactory
, which just returns the assortment of extractors. An Extractor extracts media data from a container format. Don't worry about the specifics of these classes, since using the default classes works perfectly in most use cases. What'southward important here is thecreateMediaSource()
method which takes aUri
of the media that you want to play. In this instance yous'll play the media from a remote server. - You lot need to call the
prepare()
method on theExoPlayer
example. This method prepares the actor to play the provided media source. - Finally, by setting the
playWhenReady
variable totruthful
orimitation
, y'all actually tell the role player to play the media when it's ready. If the player is already in the fix state, and so this method tin can be used to pause and resume playback.
You have at present initialized the actor and yous accept the view. What's next?
Attaching the Thespian to a View
Attaching the player to the view is very straightforward. You only ready the ExoPlayer
instance on the thespian view that yous added to the xml by calling the setPlayer(...)
method.
Since you're using MVP and you're decoupling the concrete actor implementation from the view, you need a way to go the underlying player implementation.
Add together a method to the MediaPlayer
interface that will give yous access to the underlying implementation:
fun getPlayerImpl(context: Context): ExoPlayer
Implement that method in MediaPlayerImpl
class:
override fun getPlayerImpl(context: Context): ExoPlayer { this.context = context initializePlayer() return exoPlayer }
Now, you have access to the ExoPlayer
implementation. VideoViewActivity
volition get the ExoPlayer
case through VideoViewPresenter
.
Add a getPlayer()
method to the VideoViewContract.Presenter
interface in the ui.video
package, which returns a MediaPlayer
instance:
fun getPlayer(): MediaPlayer
Add together a media player property to the VideoViewPresenter
:
private val mediaPlayer = MediaPlayerImpl()
Implement the getPlayer()
method, which will just return the media thespian instance:
override fun getPlayer() = mediaPlayer
In VideoViewActivity
, set the histrion on the view inside the init()
method by calling:
videoView.player = presenter.getPlayer().getPlayerImpl(this)
To really play the video, add together a play()
method to the VideoViewContract.Presenter
interface and laissez passer in the media url:
fun play(url: String)
At present, implement that method in the VideoViewPresenter
. This method just delegates media playing to media player.
override fun play(url: String) = mediaPlayer.play(url)
Dandy, now you're ready to play the video.
At the end of VideoViewActivity
'southward init()
method, tell the presenter to play the video:
presenter.play(videoUrl)
It's important to release the player when it's no longer needed, in order to gratuitous up limited resources, such equally video decoders, for use by other apps. This can be done by calling ExoPlayer.release()
.
Add a releasePlayer()
method to the MediaPlayer
interface:
fun releasePlayer()
And implement it in the MediaPlayerImpl
class:
override fun releasePlayer() { exoPlayer.stop() exoPlayer.release() }
Add the releasePlayer()
method to the VideoViewContract.Presenter
, equally well, and implement information technology in the VideoViewPresenter
course:
override fun releasePlayer() = mediaPlayer.releasePlayer()
You demand to brand sure that VideoViewActivity
releases the player when information technology is no longer the active Activeness.
To exercise this, you release the player in onPause()
if on Android Marshmallow and below:
override fun onPause() { super.onPause() if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { presenter.releasePlayer() } }
Or release in onStop
if on Android Nougat and above because of the multi window support that was added in Android Due north:
override fun onStop() { super.onStop() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.North) { presenter.releasePlayer() } }
Build and run your app to encounter what happens.
Click on any item in the list and you will become a screen like this:
Now you tin can play video. Awesome. :]
Judge nosotros're washed here, right? Not still.
Customizing ExoPlayer
If you lot take a look at the UI of ExoPlayer
, it'due south minimalistic. Adjacent, you'll brand information technology nice and shiny.
The ExoPlayer
library is designed specifically with customization in mind. That's a huge advantage of ExoPlayer
: yous tin customize nigh anything. The ExoPlayer
library defines a number of interfaces and abstract base classes that make it possible for app developers to easily replace the default implementations provided by the library.
In your app, yous'll customize the user interface.
Changing the Appearance
Video is displayed in the PlayerView
in XML. PlayerView
is a loftier level UI component for media playback which displays the video and playback controls. Playback controls are displayed in a PlaybackControlView
. Those elements back up a diversity of XML attributes, which yous tin use to customize the wait of the UI.
Yous can besides override the default layout files. When these views are inflated, they use specific layout files that determine how the UI will look. Y'all'll change the appearance of the playback controls.
When PlaybackControlView
is inflated, it uses exo_playback_control_view.xml
. Create a new XML layout file in the res/layout
binder and name it exo_playback_control_view.xml
. This volition override the default file.
Update the file to the following:
<?xml version="i.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="lesser" android:background="#CC000000" android:layoutDirection="ltr" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="centre" android:orientation="horizontal" android:paddingTop="4dp"> <ImageButton android:id="@id/exo_rew" way="@way/ExoMediaButton.Rewind" /> <ImageButton android:id="@id/exo_play" style="@style/CustomExoMediaButton.Play" /> <ImageButton android:id="@id/exo_pause" style="@style/CustomExoMediaButton.Pause" /> <ImageButton android:id="@id/exo_ffwd" style="@fashion/ExoMediaButton.FastForward" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@id/exo_position" android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="simulated" android:paddingLeft="4dp" android:paddingRight="4dp" android:textColor="#FFBEBEBE" android:textSize="14sp" android:textStyle="assuming" /> <com.google.android.exoplayer2.ui.DefaultTimeBar android:id="@id/exo_progress" android:layout_width="0dp" android:layout_height="26dp" android:layout_weight="1" /> <TextView android:id="@id/exo_duration" android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:paddingLeft="4dp" android:paddingRight="4dp" android:textColor="#FFBEBEBE" android:textSize="14sp" android:textStyle="bold" /> </LinearLayout> </LinearLayout>
These changes customize how the Play and Pause buttons look. Open styles.xml
and view the custom styles for those buttons. The default styles change the drawable source that is displayed and brand the buttons a little chip bigger.
<fashion name="CustomExoMediaButton"> <item name="android:background">?android:attr/selectableItemBackground</detail> <particular name="android:scaleType">fitXY</detail> <item name="android:layout_width">@dimen/video_view_exo_player_play_pause_button_dimen</item> <item name="android:layout_height">@dimen/video_view_exo_player_play_pause_button_dimen</particular> </style> <way proper noun="CustomExoMediaButton.Play"> <item name="android:src">@drawable/ic_play_circle_filled</item> </fashion> <fashion name="CustomExoMediaButton.Pause"> <item proper noun="android:src">@drawable/ic_pause_circle_filled</item> </manner>
Build and run your app and play a video to see what it looks like.
OK, it's not as dainty and shiny as yous might have hoped, only experience free to change the styles if yous want to run into a more dramatic change. :]
There is a pocket-sized consequence with this approach. Since you lot overrode the default XML layout file, all instances of the PlaybackControlView
in your app will be customized like this. If you don't want this behavior, you can customize individual instances every bit well. You can use the controller_layout_id
attribute in the XML to specify a custom layout file for individual instances.
Pros and Cons of ExoPlayer
The biggest advantages of ExoPlayer
are its flexibility and rich feature stack, but that too makes it harder to work with it.
Since you can customize the thespian to suit well-nigh every use case, ExoPlayer
is the best choice for complex utilise cases. For simple use cases at that place really isn't a reason to apply ExoPlayer
, MediaPlayer
will suffice.
For audio-only playback on some devices, ExoPlayer
may swallow significantly more bombardment than MediaPlayer
.
Ane more advantage of MediaPlayer
over ExoPlayer
is that MediaPlayer
works all the style back to the first of Android, while ExoPlayer
is only available on Jelly Bean and above. Merely I wouldn't phone call this a problem since there's only nigh i% of active devices running earlier versions.
Where to Become From Here?
You lot covered a lot in this tutorial, only ExoPlayer
has many other possibilities and avant-garde features that aren't mentioned hither. In general, if at that place is something that yous tin can't do with Android's MediaPlayer
there'due south a high probability that you can do it with ExoPlayer
. Therefore, ExoPlayer
is often the best choice for media playback on Android.
Nevertheless, be conscientious of over-engineering science! You must be thinking at present: "ExoPlayer is crawly, I'll utilize it all the time!" Before y'all do that, ask yourself this: "Do I really need an ExoPlayer?" Say yous have a killer app thought. You want to brand an app that plays dizzy audio effects. Do yous really need ExoPlayer
here? ExoPlayer
has many cool features, simply in this instance you don't need it. You but demand a way to play a very unproblematic sound. Android's MediaPlayer
would be a ameliorate choice. Don't over-engineer things!
The FunTime app was just ane example of how you can play videos from a remote web server in your app. If you want to check out other features of ExoPlayer
and run into how to implement those, Google'southward codelab is a good place to showtime. You can check it out here.
We promise yous enjoyed this tutorial and learned something from information technology. If you have any question or comments, or y'all desire to share your experience with ExoPlayer
, please bring together in the give-and-take below.
Source: https://www.raywenderlich.com/5573-media-playback-on-android-with-exoplayer-getting-started
0 Response to "How Can Play Again Video in Exoplayer"
Post a Comment