Libraries

ExoPlayer Video Streaming in Android

We demonstrate video streaming from the server using the ExoPlayer. In fact, youtube player also used ExoPlayer for streaming video. This ExoPlayer android example I will explain how to use ExoPlayer in own android application.

ExoPlayer is an open-source project. This is not a part of Android SDK. In Android, ExoPlayer is application level media player. It’s standard audio and video components are built on Android’s MediaCodec API, which was released in Android.

ExoPlayer is easy to use, maintainable and fully customize.

ExoPlayer Android Tutorial Sample App

1. Create a new project.

Go to File Menu and Create a New Project, fill information like project and package name after that click Next and select target SDK and Finish

2. After that add below dependency in build.gradle.

    // add exo player dependency here
    implementation 'com.google.android.exoplayer:exoplayer:2.7.3'
    implementation 'org.jsoup:jsoup:1.10.3'

    // code generator for view
    implementation "com.jakewharton:butterknife:8.8.1"
    annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"

In the gradle.xml file, We have 2 major dependencies. One for ExoPlayer and second as know about ButterKnife already. Basically, the butterknife is injected of view in the java file.

3. Open activity_main.xml and add two Button like below code.

While creating project Android Studio is provide default template like EmptyActivity. So MainActivity.java and activity_main.xml is automatically created. So open activity_main.xml and add to button

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:background="@drawable/bg_design"
    tools:context=".MainActivity"
    >

  <Button
      android:id="@+id/buttonPlayUrlVideo"
      android:layout_width="200dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginTop="16dp"
      android:layout_marginEnd="8dp"
      android:layout_marginBottom="8dp"
      android:background="@color/colorAccent"
      android:text="@string/title_play_url"
      android:textColor="@color/white"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="0.5"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/buttonPlayDefaultVideo"
      />

  <Button
      android:id="@+id/buttonPlayDefaultVideo"
      android:layout_width="200dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      android:background="@color/colorAccent"
      android:text="@string/title_play_default_url"
      android:textColor="@color/white"
      app:layout_constraintBottom_toTopOf="@+id/buttonPlayUrlVideo"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="0.5"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintVertical_chainStyle="packed"
      />
</android.support.constraint.ConstraintLayout>

As per design, we have created two buttons one for play default video. The second user can put own URL in dialog prompt.

4.1 Now connect this layout with MainActivity.java

Open the main activity, we generate view inject code by using ButterKnief injection and set on click listeners.

  @BindView(R.id.buttonPlayUrlVideo)
  Button buttonPlayUrlVideo;
  @BindView(R.id.buttonPlayDefaultVideo)
  Button buttonPlayDefaultVideo;

  @OnClick({ R.id.buttonPlayUrlVideo, R.id.buttonPlayDefaultVideo })
  public void onViewClicked(View view) {
    switch (view.getId()) {
      case R.id.buttonPlayUrlVideo:
        showDialogPrompt();
        break;
      case R.id.buttonPlayDefaultVideo:
        Intent mIntent =
            ExoPlayerActivity.getStartIntent(this, VideoPlayerConfig.DEFAULT_VIDEO_URL);
        startActivity(mIntent);
        break;
    }
  }
4.2. Let’s bind butter knife in onCreate Activity
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getSupportActionBar().hide();
    ButterKnife.bind(this);
  }

4.3. -As per above, We are using two buttons. So If you want to play a default video then we call intent with default URL of ExoPlayer activity.
like Below

  // End Activity Here
  Intent mIntent = ExoPlayerActivity.getStartIntent(this, VideoPlayerConfig.DEFAULT_VIDEO_URL);

  startActivity(mIntent);


4.3. – Button for playing its own video by entering video URL. So taking user URL we have created alert dialog with edit text.

Just create a layout file for dialog view. In res, folder create file named dialog_prompts.xml and add few components

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/default_item_padding"
    >

  <TextView
      android:id="@+id/textView1"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      android:text="Type Your Url"
      android:textAppearance="?android:attr/textAppearanceLarge"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      />

  <EditText
      android:id="@+id/editTextDialogUrlInput"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/textView1"
      >

    <requestFocus />

  </EditText>

</android.support.constraint.ConstraintLayout>

Open again MainActivity.java and put this code for creating dialog

  private void showDialogPrompt() {
    // get dialog_prompts.xml view
    LayoutInflater li = LayoutInflater.from(this);
    View promptsView = li.inflate(R.layout.dialog_prompts, null);
    AlertDialog.Builder mBuilder = new AlertDialog.Builder( this);
    // set dialog_prompts.xml to dialog
    mBuilder.setView(promptsView);
    final EditText userInputURL = (EditText) promptsView
        .findViewById(R.id.editTextDialogUrlInput);
    // set dialog message here
    mBuilder.setCancelable(false)
        .setPositiveButton("OK",
            new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
                boolean isURL = Patterns.WEB_URL.matcher(userInputURL.getText().toString().trim()).matches();
                if (isURL) {
                  Intent mIntent = ExoPlayerActivity.getStartIntent(MainActivity.this, userInputURL.getText().toString().trim());
                  startActivity(mIntent);
                } else {
                  Toast.makeText(MainActivity.this, getString(R.string.error_message_url_not_valid), Toast.LENGTH_SHORT).show();
                }
              }
            })
        .setNegativeButton("Cancel",
            new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
              }
            }).create().show();
  }

5. Now MainActivity.java full code seems like below

package com.androidwave.exoplayer;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

  public class MainActivity extends AppCompatActivity {

    @BindView(R.id.buttonPlayUrlVideo)
    Button buttonPlayUrlVideo;
    @BindView(R.id.buttonPlayDefaultVideo)
    Button buttonPlayDefaultVideo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      getSupportActionBar().hide();
      ButterKnife.bind(this);
    }

    @OnClick({ R.id.buttonPlayUrlVideo, R.id.buttonPlayDefaultVideo })
    public void onViewClicked(View view) {
      switch (view.getId()) {
        case R.id.buttonPlayUrlVideo:
          showDialogPrompt();
          break;
        case R.id.buttonPlayDefaultVideo:
          Intent mIntent =
              ExoPlayerActivity.getStartIntent(this, VideoPlayerConfig.DEFAULT_VIDEO_URL);
          startActivity(mIntent);
          break;
      }
    }

    private void showDialogPrompt() {
      // get dialog_prompts.xml view
      LayoutInflater li = LayoutInflater.from(this);
      View promptsView = li.inflate(R.layout.dialog_prompts, null);
      AlertDialog.Builder mBuilder = new AlertDialog.Builder(this);
      // set dialog_prompts.xml to dialog
      mBuilder.setView(promptsView);
      final EditText userInputURL = (EditText) promptsView
          .findViewById(R.id.editTextDialogUrlInput);
      // set dialog message here
      mBuilder.setCancelable(false)
          .setPositiveButton("OK",
              new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                  boolean isURL =
                      Patterns.WEB_URL.matcher(userInputURL.getText().toString().trim()).matches();
                  if (isURL) {
                    Intent mIntent = ExoPlayerActivity.getStartIntent(MainActivity.this,
                        userInputURL.getText().toString().trim());
                    startActivity(mIntent);
                  } else {
                    Toast.makeText(MainActivity.this,
                        getString(R.string.error_message_url_not_valid), Toast.LENGTH_SHORT).show();
                  }
                }
              })
          .setNegativeButton("Cancel",
              new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                  dialog.cancel();
                }
              }).create().show();
    }
  }

6. Configure ExoPlayer

Before going to Exo Player activity we define followings configuration of ExoPlayer.
MIN_BUFFER_DURATION – Minimum Video you want to buffer while Playing. for now, I have set 3 second
MAX_BUFFER_DURATION – You can set Max Video you want to buffer during PlayBack.
MIN_PLAYBACK_START_BUFFER – Set Min Video you want to buffer before start Playing it
MIN_PLAYBACK_RESUME_BUFFER – Set Min video You want to buffer when the user resumes video
DEFAULT_VIDEO_URL– Set Default video url for demo

package com.androidwave.exoplayer;

  public class VideoPlayerConfig {
    //Minimum Video you want to buffer while Playing
    public static final int MIN_BUFFER_DURATION = 3000;
    //Max Video you want to buffer during PlayBack
    public static final int MAX_BUFFER_DURATION = 5000;
    //Min Video you want to buffer before start Playing it
    public static final int MIN_PLAYBACK_START_BUFFER = 1500;
    //Min video You want to buffer when user resumes video
    public static final int MIN_PLAYBACK_RESUME_BUFFER = 5000;

    public static final String DEFAULT_VIDEO_URL =
        "https://androidwave.com/media/androidwave-video-exo-player.mp4";
  }

7. Create a layout file name with activity_exo_player.xml

Create layout file inside res-> layout-> activity_exo_player.xml. and some components Progressbar(buffering indicator) and ExoPlayerView

<?xml version="1.0" encoding="utf-8"?>
<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=".ExoPlayerActivity"
    >

  <com.google.android.exoplayer2.ui.PlayerView
      android:id="@+id/videoFullScreenPlayer"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:background="#A6000000"
      app:controller_layout_id="@layout/exo_playback_control_view"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="1.0"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintVertical_bias="1.0"
      app:player_layout_id="@layout/exo_simple_player_view"
      app:repeat_toggle_modes="none"
      app:show_timeout="45000"
      app:surface_type="texture_view"
      />

  <ProgressBar
      android:id="@+id/spinnerVideoDetails"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:layout_marginStart="8dp"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      android:layout_marginBottom="8dp"
      android:indeterminate="true"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      />

  <ImageView
      android:id="@+id/imageViewExit"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="16dp"
      android:layout_marginLeft="16dp"
      android:layout_marginTop="16dp"
      android:padding="@dimen/default_item_padding"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:srcCompat="@drawable/ic_cross_circular_button_outline"
      />
</android.support.constraint.ConstraintLayout>

8. Same as Create ExoPlayerActivity.java

Go to create an Activity with ExoPlayerActivity.java and set content layout is activity_exo_player.xml. Furthermore generates ButteKnief Injection by select set ContentView and right click and click generate. Now one popup appeared select view and set ids and click ok.

  @BindView(R.id.videoFullScreenPlayer)
  PlayerView videoFullScreenPlayer;
  @BindView(R.id.spinnerVideoDetails)
  ProgressBar spinnerVideoDetails;
  @BindView(R.id.imageViewExit)
  ImageView imageViewExit;
8.1. Define some variables and do some fullscreen configuration
  private static final String TAG = "ExoPlayerActivity";
  private static final String KEY_VIDEO_URI = "video_uri";
  String videoUri;
  SimpleExoPlayer player;
  Handler mHandler;
  Runnable mRunnable;
8.2. We are using vector icon so enable
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
8.3. Now initialise video player configuration
  private void initializePlayer() {
    if (player == null) {
      // 1. Create a default TrackSelector
      LoadControl loadControl = new DefaultLoadControl(
          new DefaultAllocator(true, 16),
          VideoPlayerConfig.MIN_BUFFER_DURATION,
          VideoPlayerConfig.MAX_BUFFER_DURATION,
          VideoPlayerConfig.MIN_PLAYBACK_START_BUFFER,
          VideoPlayerConfig.MIN_PLAYBACK_RESUME_BUFFER, -1, true);

      BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
      TrackSelection.Factory videoTrackSelectionFactory =
          new AdaptiveTrackSelection.Factory(bandwidthMeter);
      TrackSelector trackSelector =
          new DefaultTrackSelector(videoTrackSelectionFactory);
      // 2. Create the player
      player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), trackSelector,
          loadControl);
      videoFullScreenPlayer.setPlayer(player);
    }
  }
8.3. After inilizaing player create a media source using below methods
  private void buildMediaSource(Uri mUri) {
    // Measures bandwidth during playback. Can be null if not required.
    DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
    // Produces DataSource instances through which media data is loaded.
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
        Util.getUserAgent(this, getString(R.string.app_name)), bandwidthMeter);
    // This is the MediaSource representing the media to be played.
    MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mUri);
    // Prepare the player with the source.
    player.prepare(videoSource);
    player.setPlayWhenReady(true);
    player.addListener(this);
  }
8.4. Implement Player.EventListener and override unimplemented methods

Just implement Player.EventListener you have to implement override methods. onPlayerStateChanged() methods will return all player state.

  @Override
  public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
    switch (playbackState) {

      case Player.STATE_BUFFERING:
        spinnerVideoDetails.setVisibility(View.VISIBLE);
        break;
      case Player.STATE_ENDED:
        // Activate the force enable
        break;
      case Player.STATE_IDLE:

        break;
      case Player.STATE_READY:
        spinnerVideoDetails.setVisibility(View.GONE);

        break;
      default:
        // status = PlaybackStatus.IDLE;
        break;
    }
  }

9. Finally, The full activity (ExoPlayerActivity.java) code looks like this

Mainly we are doing below things in this activity

  • Initialize Player with configuration .
  • Prepare source files and settings on the player.
  • Add Player Event listener for listening to different player state
  • Manage player state with activity life cycler eg. pausePlayer(), resumePlayer(), releasePlayer()
package com.androidwave.exoplayer;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ProgressBar;

import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

  public class ExoPlayerActivity extends AppCompatActivity implements Player.EventListener {
    private static final String TAG = "ExoPlayerActivity";

    private static final String KEY_VIDEO_URI = "video_uri";

    @BindView(R.id.videoFullScreenPlayer)
    PlayerView videoFullScreenPlayer;
    @BindView(R.id.spinnerVideoDetails)
    ProgressBar spinnerVideoDetails;
    @BindView(R.id.imageViewExit)
    ImageView imageViewExit;

    String videoUri;
    SimpleExoPlayer player;
    Handler mHandler;
    Runnable mRunnable;

    public static Intent getStartIntent(Context context, String videoUri) {
      Intent intent = new Intent(context, ExoPlayerActivity.class);
      intent.putExtra(KEY_VIDEO_URI, videoUri);
      return intent;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      requestWindowFeature(Window.FEATURE_NO_TITLE);
      this.getWindow()
          .setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
              WindowManager.LayoutParams.FLAG_FULLSCREEN);
      setContentView(R.layout.activity_exo_player);
      ButterKnife.bind(this);
      AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
      getSupportActionBar().hide();

      if (getIntent().hasExtra(KEY_VIDEO_URI)) {
        videoUri = getIntent().getStringExtra(KEY_VIDEO_URI);
      }

      setUp();
    }

    private void setUp() {
      initializePlayer();
      if (videoUri == null) {
        return;
      }
      buildMediaSource(Uri.parse(videoUri));
    }

    @OnClick(R.id.imageViewExit)
    public void onViewClicked() {
      finish();
    }

    private void initializePlayer() {
      if (player == null) {
        // 1. Create a default TrackSelector
        LoadControl loadControl = new DefaultLoadControl(
            new DefaultAllocator(true, 16),
            VideoPlayerConfig.MIN_BUFFER_DURATION,
            VideoPlayerConfig.MAX_BUFFER_DURATION,
            VideoPlayerConfig.MIN_PLAYBACK_START_BUFFER,
            VideoPlayerConfig.MIN_PLAYBACK_RESUME_BUFFER, -1, true);

        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory =
            new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector =
            new DefaultTrackSelector(videoTrackSelectionFactory);
        // 2. Create the player
        player =
            ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), trackSelector,
                loadControl);
        videoFullScreenPlayer.setPlayer(player);
      }
    }

    private void buildMediaSource(Uri mUri) {
      // Measures bandwidth during playback. Can be null if not required.
      DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
      // Produces DataSource instances through which media data is loaded.
      DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
          Util.getUserAgent(this, getString(R.string.app_name)), bandwidthMeter);
      // This is the MediaSource representing the media to be played.
      MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
          .createMediaSource(mUri);
      // Prepare the player with the source.
      player.prepare(videoSource);
      player.setPlayWhenReady(true);
      player.addListener(this);
    }

    private void releasePlayer() {
      if (player != null) {
        player.release();
        player = null;
      }
    }

    private void pausePlayer() {
      if (player != null) {
        player.setPlayWhenReady(false);
        player.getPlaybackState();
      }
    }

    private void resumePlayer() {
      if (player != null) {
        player.setPlayWhenReady(true);
        player.getPlaybackState();
      }
    }

    @Override
    protected void onPause() {
      super.onPause();
      pausePlayer();
      if (mRunnable != null) {
        mHandler.removeCallbacks(mRunnable);
      }
    }

    @Override
    protected void onRestart() {
      super.onRestart();
      resumePlayer();
    }

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

    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {

    }

    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

    }

    @Override
    public void onLoadingChanged(boolean isLoading) {

    }

    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
      switch (playbackState) {

        case Player.STATE_BUFFERING:
          spinnerVideoDetails.setVisibility(View.VISIBLE);
          break;
        case Player.STATE_ENDED:
          // Activate the force enable
          break;
        case Player.STATE_IDLE:

          break;
        case Player.STATE_READY:
          spinnerVideoDetails.setVisibility(View.GONE);

          break;
        default:
          // status = PlaybackStatus.IDLE;
          break;
      }
    }

    @Override
    public void onRepeatModeChanged(int repeatMode) {

    }

    @Override
    public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {

    }

    @Override
    public void onPlayerError(ExoPlaybackException error) {

    }

    @Override
    public void onPositionDiscontinuity(int reason) {

    }

    @Override
    public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

    }

    @Override
    public void onSeekProcessed() {

    }
  }

After following all above just RUN the project and use app, If you have any queries, feel free to ask them in the comment section below. Happy Coding đŸ™‚

Conclusion

Wow! Great job! You just finished the ExoPlayer android example. You learned about integrating ExoPlayer in your application.

Download Sample Project- Video Streaming ExoPlayer in Android

If you have any queries, feel free to connect us.

14
Leave a Reply

  Subscribe  
Notify of
Flakron Saidi

import com.google.android.exoplayer2.ui.PlayerView; does not exist ?

Sherwin

Hi, I am beginner in using exoplayer, How to change Http method of exoplayer from GET to POST. Thank you!