ExoPlayer, a media player for Android, was developed and is being maintained by Google as an alternative for Android’s default MediaPlayer. Among ExoPlayer’s advantages over MediaPlayer are dynamic adaptive streaming over HTTP (DASH), smooth streaming, and common encryption. A major advantage, however, is ExoPlayer’s easy customization.
Given the mobile constraints for resources, such as videos, ExoPlayer is an excellent choice for playing videos in Android apps because of its video-buffering capability, which downloads videos ahead of time for a seamless experience. You can play videos with ExoPlayer from phone storage or from URLs, as described later in this tutorial.
Through an Android example app for ExoPlayer, this tutorial shows you how to leverage Cloudinary, a cloud-based service platform on which you can upload rich media for cloud storage as well as efficiently and effectively manage and transform them, in order to seamlessly display videos on ExoPlayer.
This is part of a series of articles about video optimization.
Here’s a handy reference guide: Media Playback on Android with ExoPlayer: Getting Started
With Cloudinary, you can transform videos by simply tweaking their URLs. Cloudinary then delivers the videos through fast Content Delivery Networks (CDNs) with advanced caching techniques.
Follow the steps below to upload and transform videos in Cloudinary.
-
Replace
CLOUDINARY_NAME
in theAndroidManifest.xml
file with your cloud name, which is displayed in the console of your Cloudinary account:<meta-data android:name="CLOUDINARY_URL" android:value="cloudinary://@CLOUDINARY_NAME"/>
Code language: HTML, XML (xml) -
Create an application class to initialize Cloudinary once for the app’s entire lifecycle. Given this one-time initialization, the global variables usually reside in this class.
import android.app.Application; import com.cloudinary.android.MediaManager; public class AppController extends Application { @Override public void onCreate() { super.onCreate(); // Initialize Cloudinary MediaManager.init(this); } }
Code language: JavaScript (javascript) -
Also in the
AndroidManifest.xml
file, specifyAppController
as the name of the application tag:<application android:name=".AppController" >
Code language: HTML, XML (xml)Note:Your uploads can be unsigned or signed. Signed uploads, which offer certain benefits, require an API key, which is not recommended for Android clients because it can be easily decompiled. Hence, opt for unsigned upload here.
-
Enable unsigned uploads in your console: click the Settings icon on your dashboard and then the Upload tab, scroll down to the Upload Presets section, and enable unsigned uploading. Cloudinary then generates a new preset with a random string as its name.
-
Upload to Cloudinary by calling this function:
MediaManager.get() .upload(videoUri) .unsigned("YOUR_PRESET") .option("resource_type", "video") .callback(new UploadCallback() { @Override public void onStart(String requestId) { } @Override public void onProgress(String requestId, long bytes, long totalBytes) { } @Override public void onSuccess(String requestId, Map resultData) { } @Override public void onError(String requestId, ErrorInfo error) { } @Override public void onReschedule(String requestId, ErrorInfo error) { } }).dispatch();
Code language: JavaScript (javascript)
videoUri
is of type Uri
, which represents the Uniform Resource Identifier (URI) of the video that resides in your phone, e.g., content://media/external/video/media/3495
.
Be sure to replace YOUR_PRESET
with the string generated by Cloudinary after you’ve enabled unsigned upload.
On a successful upload, Cloudinary calls the onSuccess
method, which contains the details of your upload, such as URL
(the URL) and public_url
(the public URL), which is the unique name of the video as stored in Cloudinary.
Next, transform the video in the method below by referring to public_url
:
String publicUrl = = (String) resultData.get("public_url");
String transformedUrl = MediaManager.get().url()
.transformation(new Transformation()
.effect("fade:2000").chain()
.effect("fade:-3000").chain()
.effect("saturation:-50")
.resourceType("video").generate(publicUrl+".mp4");
Code language: JavaScript (javascript)
You’ve now added three effects to the video:
- A two-second fade-in. Fade-ins usually have a positive value.
- A three-second fade-out. Fade-outs usually have a negative value.
- A drop in the saturation. A negative saturation value results in a faded look of the video.
A printout of transformedUrl
reads like this: https://res.cloudinary.com/{CLOUD_NAME}/video/upload/e_fade:2000/e_fade:-3000/e_saturation:-50/{publicUrl}.mp4
For details on Cloudinary’s many transformation capabilities, see this section in a Cloudinary post. To learn about video transformations on Cloudinary, see the related documentation.
It is assumed that you have developed an Android app, hence this section does not address that process. Follow the steps below to set up ExoPlayer for your app:
-
Add the Gradle dependency to your
build.gradle
file to make use of the ExoPlayer library:implementation 'com.google.android.exoplayer:exoplayer:2.6.0'
Code language: JavaScript (javascript){note} If your Gradle version is below 3.0, replace
implementation
in the above snippet withcompile
. {/note} -
Sync your
gradle
file to ensure a download of the dependency for the project. -
Add
SimpleExoPlayerView
to yourActivity
layout:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="180dp" android:layout_margin="16dp"> <com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/exoplayer" android:layout_width="match_parent" android:layout_height="wrap_content"/>
Code language: HTML, XML (xml) -
In the
onStart
method in the correspondingActivity
class, initializeSimpleExoPlayerView
and set upSimpleExoPlayer
by calling theinitializePlayer
method:@Override protected void onStart() { super.onStart(); initializePlayer(); }
Code language: CSS (css)initializePlayer
applies the default configurations for a seamless display of videos in ExoPlayer:private void initializePlayer(){ // Create a default TrackSelector BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); //Initialize the player player = ExoPlayerFactory.newSimpleInstance(this, trackSelector); //Initialize simpleExoPlayerView SimpleExoPlayerView simpleExoPlayerView = findViewById(R.id.exoplayer); simpleExoPlayerView.setPlayer(player); // Produces DataSource instances through which media data is loaded. DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "CloudinaryExoplayer")); // Produces Extractor instances for parsing the media data. ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); // This is the MediaSource representing the media to be played. Uri videoUri = Uri.parse("any Cloudinary URL"); MediaSource videoSource = new ExtractorMediaSource(videoUri, dataSourceFactory, extractorsFactory, null, null); // Prepare the player with the source. player.prepare(videoSource); }
Code language: JavaScript (javascript)
The above snippet performs these tasks:
- Initializes the
SimpleExoPlayer
instance with the default configurations. - Creates and initializes an instance of
SimpleExoPlayerView
and assigns your existing player instance to it. - Generates the media source with
videoUri
parsed from a video URL (URL
) from Cloudinary.
Now prepare the player with the video source, after which the video is ready for display. You now have a basic implementation of ExoPlayer.
The SimpleExoPlayer
instance is a class variable here, accessible to all the methods in the class.
5. To save resources, add the code below to release the player when it’s not in use:
```java
@Override
public void onPause() {
super.onPause();
if (player!=null) {
player.release();
player = null;
}
}
```
Finally, add the permissions for the app to access the internet in the AndroidManifest.xml
file :
<uses-permission android:name="android.permission.INTERNET"/>
Code language: HTML, XML (xml)
The app looks like this if you play the transformed URL with ExoPlayer.
You can integrate Cloudinary, which offers robust capabilities for video management, with libraries like ExoPlayer to display videos on Android apps. It’s an intuitive, easy process. For details on optimizing videos with Cloudinary, see this post. Also see the Cloudinary documentation for other media-management features.
- Optimizing Video with Cloudinary and the HTML5 Video Player
- ExoPlayer Android Tutorial: Easy Video Delivery and Editing
- How to Generate Waveform Images From Audio Files
- Auto Generate Subtitles Based on Video Transcript
- Automated Generation of Intelligent Video Previews on Cloudinary’s Dynamic Video Platform
- Converting Android Videos to Animated GIF Images With Cloudinary: A Tutorial
- Tips for Retaining Audience Through Engaging Videos
- Product Videos 101: What Makes Them Great?