Android Exoplayer - Play Audio/Video files in Android.

Now a days in every mobile app including the media. So playing the media is more popular in Android devices.
There are different ways to play media in Android.
In this post we are going to learn about Exoplayer.

     

                                                                           FullScreen


What is Exoplayer?
Exoplayer is a media playback library, which is alternative for the default android MediaPlayer API.
It will support play both offline and online videos.

Before going to Exoplayer let's check other Media players in android.


Youtube Player API:
Before YouTubePlayer  API, play youtube videos we called an intent to call default YouTube player to play the videos.
After that when YouTubePlayer API came, we can embedded to play the YouTube video inside the application.
Mostly we can use YouTube API for playing YouTube videos.

MediaPlayer :
Android default Multimedia framework provided classes to play the multimedia in the applications.
Media Player is primary class for playing the audio and video. It supports all types of audio and video.
But it is very less customization to extend.

So most of the People will go with Exoplayer when required to play different type of Media.
It supports different media which is not supported by Android default Media Player

Let's start Integrate Exoplayer

  • Create a Project in Android studio
  • Add Exoplayer dependency in the build.gradle file
  • Create exoplayer instance
  • Prepare the player with MediaSource to play
  • Handle the Player instance 

Create a Project in Android studio
Open Android studio and Create new Project.

Add Exoplayer dependency
In the Project level gradle file add Google and JCenter repositories 

repositories {
    google()
    jcenter()
}

Next add Exoplayer depency in App level gradle file

implementation 'com.google.android.exoplayer:exoplayer:2.X.X'

replace x.x with latest exoplayer version number.

This decency will add all modules of exoplayer, we can also add individual modules like

implementation 'com.google.android.exoplayer:exoplayer-core:2.X.X'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.X.X'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X'

 

The Modules available in exoplayer API are

  • exoplayer-core: Core functionality (required).
  • exoplayer-dash: Support for DASH content.
  • exoplayer-hls: Support for HLS content.
  • exoplayer-smoothstreaming: Support for SmoothStreaming content.
  • exoplayer-ui: UI components and resources for use with ExoPlayer

Add Java8  support
If not enable java8 support enable it by adding

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

 

Create Exoplayer instance
Create an Exoplayer instance by using Exoplayerfactory

DefaultTrackSelector trackselector;
    DefaultLoadControl loadControl;
    DefaultRenderersFactory defaultRenderersFactory;
    SimpleExoPlayer exoPlayer;
trackselector = new DefaultTrackSelector();
        loadControl = new DefaultLoadControl();
        defaultRenderersFactory = new DefaultRenderersFactory(getApplicationContext());

        exoPlayer =  ExoPlayerFactory.newSimpleInstance(getApplicationContext(),
                defaultRenderersFactory, trackselector, loadControl);

 

 

Now set the player to view

Prepare the DataSource and set it to player
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
    Util.getUserAgent(context, "USER AGENT NAME"));

MediaSource videoSource = MediaSource(mp4VideoUri);

player.prepare(videoSource);

 

Create MediaSource

private MediaSource buildMediaSource(Uri uri) {
        return buildMediaSource(uri, null);
    }

    private MediaSource buildMediaSource(Uri uri, @Nullable String overrideExtension) {

        @C.ContentType int type = Util.inferContentType(uri, overrideExtension);
        switch (type) {
            case C.TYPE_DASH:
                return new DashMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
            case C.TYPE_SS:
                return new SsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
            case C.TYPE_HLS:
                return new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
            case C.TYPE_OTHER:
                return new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
            default:
                throw new IllegalStateException("Unsupported type: " + type);
        }
    }

 

That's it, Now run your application you will able to play the videos.

Custom Playback Controllers

If we want to handle the Playback controllers we need to add belwo xml files in our application.

exo_simple_player_view.xml

            android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center">

       

                    android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/grey"/>

                    android:layout_width="match_parent"
            android:layout_height="match_parent"
            />

                    android:layout_width="match_parent"
            android:layout_height="match_parent"/>

                    android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:layout_gravity="center"/>

                    android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:gravity="center"
            android:background="@color/exo_error_message_background_color"
            android:padding="@dimen/_16dp"/>

   

            android:layout_width="match_parent"
        android:layout_height="match_parent"/>
            android:id="@id/exo_controller"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
            android:layout_width="match_parent"
        android:layout_height="match_parent"/>

 

 

exo_playback_control_view.xml



    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_gravity="bottom"
    android:layoutDirection="ltr"
    android:background="#BB000000"
    android:orientation="vertical">

            android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:paddingTop="4dp"
        android:orientation="horizontal">

                    style="@style/ExoMediaButton.Previous"/>

                    style="@style/ExoMediaButton.Rewind"/>

                    style="@style/ExoMediaButton"/>

                    style="@style/ExoMediaButton.Play"/>

                    style="@style/ExoMediaButton.Pause"/>

                    style="@style/ExoMediaButton.FastForward"/>

                    style="@style/ExoMediaButton.Next"/>

   

            android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/_4dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

                    android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/_14sp"
            android:textStyle="bold"
            android:paddingLeft="@dimen/_4dp"
            android:paddingRight="@dimen/_4dp"
            android:includeFontPadding="false"
            android:textColor="#AABEBEBE"/>

                    android:id="@id/exo_progress"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="@dimen/_26dp"/>

                    android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/_14sp"
            android:textStyle="bold"
            android:paddingLeft="@dimen/_4dp"
            android:paddingRight="@dimen/_4dp"
            android:includeFontPadding="false"
            android:textColor="#AABEBEBE"/>


                    android:id="@+id/exo_full"
            android:layout_width="28dp"
            android:layout_height="@dimen/_28dp"
            android:layout_gravity="center"
            android:adjustViewBounds="true"
            android:padding="@dimen/_4dp"

            app:srcCompat="@drawable/ic_expand"/>

   

 

 

To Hanlde events we need to write below code in our Activity

private void handlePlayBackControlls()
    {
        playerview.requestFocus();
        playerview.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
        PlaybackControlView controlView = playerview.findViewById(R.id.exo_controller);
        ImageView exo_full = controlView.findViewById(R.id.exo_full);
        exo_full.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int orientation = getResources().getConfiguration().orientation;

                switch (orientation) {

                    case Configuration.ORIENTATION_LANDSCAPE:

                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

                        break;

                    case Configuration.ORIENTATION_PORTRAIT:

                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

                        break;
                }
            }
        });
    }

Here i have handle full screen event of player. we can also handle other events like above.

 

Complete Activity Code

MainActivity.java

package com.rrtutors.androidexoplayer;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;

import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    PlayerView playerview;
    DefaultTrackSelector trackselector;
    DefaultLoadControl loadControl;
    DefaultRenderersFactory defaultRenderersFactory;
    SimpleExoPlayer exoPlayer;
    DataSource.Factory dataSourceFactory;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        playerview=findViewById(R.id.playerview);
        initializePlayer();
    }

    private void initializePlayer() {

        trackselector = new DefaultTrackSelector();
        loadControl = new DefaultLoadControl();
        defaultRenderersFactory = new DefaultRenderersFactory(getApplicationContext());

        exoPlayer =  ExoPlayerFactory.newSimpleInstance(getApplicationContext(),
                defaultRenderersFactory, trackselector, loadControl);
        playerview.setPlayer(exoPlayer);
        handlePlayBackControlls();
        prepareMedia();
    }

    private void prepareMedia()
    {
     dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(),
                Util.getUserAgent(getApplicationContext(), "Android Exoplayer"));

// Prepare the player with the source.
        exoPlayer.prepare(buildMediaSource(
Uri.parse("ASS_HERE_URL")));
        exoPlayer.setPlayWhenReady(true);

    }

    private void releasePlayer()
    {
        exoPlayer.stop();
        exoPlayer.release();
    }

    @Override
    protected void onPause() {
        super.onPause();
        releasePlayer();
    }

    @Override
    protected void onStop() {
        super.onStop();
        releasePlayer();
    }


    private MediaSource buildMediaSource(Uri uri) {
        return buildMediaSource(uri, null);
    }

    private MediaSource buildMediaSource(Uri uri, @Nullable String overrideExtension) {

        @C.ContentType int type = Util.inferContentType(uri, overrideExtension);
        switch (type) {
            case C.TYPE_DASH:
                return new DashMediaSource.Factory(dataSourceFactory).
createMediaSource(uri);
            case C.TYPE_SS:
                return new SsMediaSource.Factory(dataSourceFactory).
createMediaSource(uri);
            case C.TYPE_HLS:
                return new HlsMediaSource.Factory(dataSourceFactory).
createMediaSource(uri);
            case C.TYPE_OTHER:
                return new ProgressiveMediaSource.Factory(dataSourceFactory).
createMediaSource(uri);
            default:
                throw new IllegalStateException("Unsupported type: " + type);
        }
    }

    private void handlePlayBackControlls()
    {
        playerview.requestFocus();
        playerview.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 
RelativeLayout.LayoutParams.MATCH_PARENT));
        PlaybackControlView controlView = playerview.findViewById(R.id.exo_controller);
        ImageView exo_full = controlView.findViewById(R.id.exo_full);
        exo_full.setOnClickListener(
new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int orientation = getResources().
getConfiguration().orientation;

                switch (orientation) {

                    case Configuration.ORIENTATION_LANDSCAPE:

                        setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

                        break;

                    case Configuration.ORIENTATION_PORTRAIT:

                        setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

                        break;
                }
            }
        });
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);


        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            playerview.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, 
RelativeLayout.LayoutParams.MATCH_PARENT));


        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {

            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            final DisplayMetrics displayMetrics = 
new DisplayMetrics();
            Objects.requireNonNull(wm).getDefaultDisplay().
getMetrics(displayMetrics);
            int  screenHeight = displayMetrics.heightPixels;
            playerview.setLayoutParams(
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
/*(int) convertDpToPixel(200f,getApplicationContext()*/screenHeight / 3));
        }
    }
}