Tag

youtube-player-api

Browsing

In this article, I will tell you how to play youtube video in ExoPlayer in Android. In previous tutorials, We were learned video streaming from the server using ExoPlayer. If you wish to read the previous article Go Here. I assuming you have basic understanding of ExoPlayer.

How to play Youtube video inside the ExoPlayer in Android. I will demonstrate step by step

1. Let’s create a new project in Android Studio.

Add dependency in Project build.gradle
allprojects {
    repositories {
        google()
        jcenter()
        /**
         * Add dependency in Project build.gradle
         */
        maven { url "https://jitpack.io" }
    }
}
Add dependency in app build.gradle
   // For youtube Url Extractor
    implementation 'com.github.HaarigerHarald:android-youtubeExtractor:v1.7.0'
    // ExoPlayer
    implementation 'com.google.android.exoplayer:exoplayer:2.7.3'

2. Prepare ExoPlayerManager Singleton

In my previous tutorials wrote ExoPlayer instance inside each activity (not a good practice). In case if we need more than one ExoPlayerView in the app, we have to write code in each activity, as per programming standard it’s not a good practice.

Therefore, I’m going to write ExoPlayerManager utility class. In other words, I creating a singleton class for managing ExoPlayer instance.

2.1 Create a CallBacks for observing ExoPlayer state
package com.androidwave.youtubeexoplayer;

public interface CallBacks {

    void callbackObserver(Object obj);

    public interface playerCallBack {
        void onItemClickOnItem(Integer albumId);

        void onPlayingEnd();
    }
}
3. Furthermore, create a singleton class with ExoPlayerManager.java name

As per singleton design pattern constructor should be private

 /**
     * declare some usable variable
     */
    private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
    private static final String TAG = "ExoPlayerManager";
    private static ExoPlayerManager mInstance = null;
    PlayerView mPlayerView;
    DefaultDataSourceFactory dataSourceFactory;
    String uriString = "";
    ArrayList<String> mPlayList = null;
    Integer playlistIndex = 0;
    CallBacks.playerCallBack listner;
    private SimpleExoPlayer mPlayer;

 /**
     * Return ExoPlayerManager instance
     * @param mContext
     * @return
     */
    public static ExoPlayerManager getSharedInstance(Context mContext) {
        if (mInstance == null) {
            mInstance = new ExoPlayerManager(mContext);
        }
        return mInstance;
    }
 /**
     * private constructor
     * @param mContext
     */
    private ExoPlayerManager(Context mContext) {

        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
        mPlayer = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);

        mPlayerView = new PlayerView(mContext);
        mPlayerView.setUseController(true);
        mPlayerView.requestFocus();
        mPlayerView.setPlayer(mPlayer);

        Uri mp4VideoUri = Uri.parse(uriString);

        dataSourceFactory = new DefaultDataSourceFactory(mContext, Util.getUserAgent(mContext, "androidwave"), BANDWIDTH_METER);

        final MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                .createMediaSource(mp4VideoUri);

        mPlayer.prepare(videoSource);
        mPlayer.addListener(new Player.EventListener() {
            @Override
            public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
                Log.i(TAG, "onTimelineChanged: ");
            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                Log.i(TAG, "onTracksChanged: ");
            }

            @Override
            public void onLoadingChanged(boolean isLoading) {
                Log.i(TAG, "onLoadingChanged: ");
            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                Log.i(TAG, "onPlayerStateChanged: ");
                if (playbackState == 4 && mPlayList != null && playlistIndex + 1 < mPlayList.size()) {
                    Log.e(TAG, "Song Changed...");

                    playlistIndex++;
                    listner.onItemClickOnItem(playlistIndex);
                    playStream(mPlayList.get(playlistIndex));
                } else if (playbackState == 4 && mPlayList != null && playlistIndex + 1 == mPlayList.size()) {
                    mPlayer.setPlayWhenReady(false);
                }
                if (playbackState == 4 && listner != null) {
                    listner.onPlayingEnd();
                }
            }

            @Override
            public void onRepeatModeChanged(int repeatMode) {
                Log.i(TAG, "onRepeatModeChanged: ");
            }

            @Override
            public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
                Log.i(TAG, "onShuffleModeEnabledChanged: ");
            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Log.i(TAG, "onPlayerError: ");
            }

            @Override
            public void onPositionDiscontinuity(int reason) {
                Log.i(TAG, "onPositionDiscontinuity: ");
            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                Log.i(TAG, "onPlaybackParametersChanged: ");
            }

            @Override
            public void onSeekProcessed() {
                Log.i(TAG, "onSeekProcessed: ");
            }
        });
    }

After define some method complete code will seem like below class

package com.androidwave.youtubeexoplayer;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
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.extractor.DefaultExtractorsFactory;
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.source.hls.HlsMediaSource;
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.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;

public class ExoPlayerManager {

    /**
     * declare some usable variable
     */
    private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
    private static final String TAG = "ExoPlayerManager";
    private static ExoPlayerManager mInstance = null;
    PlayerView mPlayerView;
    DefaultDataSourceFactory dataSourceFactory;
    String uriString = "";
    ArrayList<String> mPlayList = null;
    Integer playlistIndex = 0;
    CallBacks.playerCallBack listner;
    private SimpleExoPlayer mPlayer;

    /**
     * private constructor
     * @param mContext
     */
    private ExoPlayerManager(Context mContext) {

        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
        mPlayer = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);

        mPlayerView = new PlayerView(mContext);
        mPlayerView.setUseController(true);
        mPlayerView.requestFocus();
        mPlayerView.setPlayer(mPlayer);

        Uri mp4VideoUri = Uri.parse(uriString);

        dataSourceFactory = new DefaultDataSourceFactory(mContext, Util.getUserAgent(mContext, "androidwave"), BANDWIDTH_METER);

        final MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                .createMediaSource(mp4VideoUri);

        mPlayer.prepare(videoSource);
        mPlayer.addListener(new Player.EventListener() {
            @Override
            public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
                Log.i(TAG, "onTimelineChanged: ");
            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                Log.i(TAG, "onTracksChanged: ");
            }

            @Override
            public void onLoadingChanged(boolean isLoading) {
                Log.i(TAG, "onLoadingChanged: ");
            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                Log.i(TAG, "onPlayerStateChanged: ");
                if (playbackState == 4 && mPlayList != null && playlistIndex + 1 < mPlayList.size()) {
                    Log.e(TAG, "Song Changed...");

                    playlistIndex++;
                    listner.onItemClickOnItem(playlistIndex);
                    playStream(mPlayList.get(playlistIndex));
                } else if (playbackState == 4 && mPlayList != null && playlistIndex + 1 == mPlayList.size()) {
                    mPlayer.setPlayWhenReady(false);
                }
                if (playbackState == 4 && listner != null) {
                    listner.onPlayingEnd();
                }
            }

            @Override
            public void onRepeatModeChanged(int repeatMode) {
                Log.i(TAG, "onRepeatModeChanged: ");
            }

            @Override
            public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
                Log.i(TAG, "onShuffleModeEnabledChanged: ");
            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Log.i(TAG, "onPlayerError: ");
            }

            @Override
            public void onPositionDiscontinuity(int reason) {
                Log.i(TAG, "onPositionDiscontinuity: ");
            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                Log.i(TAG, "onPlaybackParametersChanged: ");
            }

            @Override
            public void onSeekProcessed() {
                Log.i(TAG, "onSeekProcessed: ");
            }
        });
    }

    /**
     * Return ExoPlayerManager instance
     * @param mContext
     * @return
     */
    public static ExoPlayerManager getSharedInstance(Context mContext) {
        if (mInstance == null) {
            mInstance = new ExoPlayerManager(mContext);
        }
        return mInstance;
    }


    public void setPlayerListener(CallBacks.playerCallBack mPlayerCallBack) {
        listner = mPlayerCallBack;
    }

    public PlayerView getPlayerView() {
        return mPlayerView;
    }

    public void playStream(String urlToPlay) {
        uriString = urlToPlay;
        Uri mp4VideoUri = Uri.parse(uriString);
        MediaSource videoSource;
        String filenameArray[] = urlToPlay.split("\\.");
        if (uriString.toUpperCase().contains("M3U8")) {
            videoSource = new HlsMediaSource(mp4VideoUri, dataSourceFactory, null, null);
        } else {
            mp4VideoUri = Uri.parse(urlToPlay);
            videoSource = new ExtractorMediaSource(mp4VideoUri, dataSourceFactory, new DefaultExtractorsFactory(),
                    null, null);
        }


        // Prepare the player with the source.
        mPlayer.prepare(videoSource);
        mPlayer.setPlayWhenReady(true);

    }

    public void setPlayerVolume(float vol) {
        mPlayer.setVolume(vol);
    }

    public void setUriString(String uri) {
        uriString = uri;
    }

    public void setPlaylist(ArrayList<String> uriArrayList, Integer index, CallBacks.playerCallBack callBack) {
        mPlayList = uriArrayList;
        playlistIndex = index;
        listner = callBack;
        playStream(mPlayList.get(playlistIndex));
    }


    public void playerPlaySwitch() {
        if (uriString != "") {
            mPlayer.setPlayWhenReady(!mPlayer.getPlayWhenReady());
        }
    }

    public void stopPlayer(boolean state) {
        mPlayer.setPlayWhenReady(!state);
    }

    public void destroyPlayer() {
        mPlayer.stop();
    }

    public Boolean isPlayerPlaying() {
        return mPlayer.getPlayWhenReady();
    }

    public ArrayList<String> readURLs(String url) {
        if (url == null) return null;
        ArrayList<String> allURls = new ArrayList<String>();
        try {

            URL urls = new URL(url);
            BufferedReader in = new BufferedReader(new InputStreamReader(urls
                    .openStream()));
            String str;
            while ((str = in.readLine()) != null) {
                allURls.add(str);
            }
            in.close();
            return allURls;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

4. How to use ExoPlayerManager inside App?

Now we prepared ExoPlayer Manager, You are thinking about how will I use this manager in our app. don’t worry I’m here will explain with an example.

4.1 Let’s create a activity.xml
<?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=".MainActivity">

    <com.google.android.exoplayer2.ui.PlayerView
        android:id="@+id/mPlayerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#A6000000"
        app:controller_layout_id="@layout/exo_playback_control_view"
        app:player_layout_id="@layout/exo_simple_player_view"
        app:repeat_toggle_modes="none"
        app:show_timeout="45000"
        app:resize_mode="fixed_height"
        app:surface_type="texture_view" />

</android.support.constraint.ConstraintLayout>
4.2Create a exo_playback_control_view.xml for ExoPlayer playback controller
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="44dp"
    android:layout_gravity="bottom"
    android:background="#A6000000"
    android:layoutDirection="ltr"
    android:orientation="vertical">
    <! –    android:background="#11000000"-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin">

        <ImageButton
            android:id="@id/exo_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            app:srcCompat="@android:drawable/ic_media_play" />

        <ImageButton
            android:id="@id/exo_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            app:srcCompat="@android:drawable/ic_media_pause" />

        <TextView
            android:id="@id/exo_position"
            android:layout_width="45dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:gravity="center"
            android:includeFontPadding="false"
            android:letterSpacing="-0.02"
            android:textColor="#ffffff"
            android:textSize="12sp"
            tools:text="23:09" />


        <com.google.android.exoplayer2.ui.DefaultTimeBar
            android:id="@id/exo_progress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            app:bar_height="8dp"
            app:buffered_color="#4Dd8d8d8"
            app:played_color="@color/white"
            app:scrubber_color="@color/white"
            app:unplayed_color="#4Dd8d8d8" />

    </LinearLayout>


</LinearLayout>

5. Let’s extract video url from Youtube YouTubeExtractor

   private void extractYoutubeUrl() {
        @SuppressLint("StaticFieldLeak") YouTubeExtractor mExtractor = new YouTubeExtractor(this) {
            @Override
            protected void onExtractionComplete(SparseArray<YtFile> sparseArray, VideoMeta videoMeta) {
                if (sparseArray != null) {
                    playVideo(sparseArray.get(17).getUrl());
                }
            }
        };
        mExtractor.extract(mYoutubeLink, true, true);
    }

6. After that, set url with ExoPlayer for streaming

  private void playVideo(String downloadUrl) {
        PlayerView mPlayerView = findViewById(R.id.mPlayerView);
        mPlayerView.setPlayer(ExoPlayerManager.getSharedInstance(MainActivity.this).getPlayerView().getPlayer());
        ExoPlayerManager.getSharedInstance(MainActivity.this).playStream(downloadUrl);
    }

7. Finally, MainActivity.java code is

package com.androidwave.youtubeexoplayer;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.SparseArray;

import com.google.android.exoplayer2.ui.PlayerView;

import at.huber.youtubeExtractor.VideoMeta;
import at.huber.youtubeExtractor.YouTubeExtractor;
import at.huber.youtubeExtractor.YtFile;

public class MainActivity extends AppCompatActivity {
    // Replace video id with your video Id
    private String YOUTUBE_VIDEO_ID = "uZnWUZW1hQo";
    private String BASE_URL = "https://www.youtube.com";
    private String mYoutubeLink = BASE_URL + "/watch?v=" + YOUTUBE_VIDEO_ID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        extractYoutubeUrl();
    }

    private void extractYoutubeUrl() {
        @SuppressLint("StaticFieldLeak") YouTubeExtractor mExtractor = new YouTubeExtractor(this) {
            @Override
            protected void onExtractionComplete(SparseArray<YtFile> sparseArray, VideoMeta videoMeta) {
                if (sparseArray != null) {
                    playVideo(sparseArray.get(17).getUrl());
                }
            }
        };
        mExtractor.extract(mYoutubeLink, true, true);
    }

    private void playVideo(String downloadUrl) {
        PlayerView mPlayerView = findViewById(R.id.mPlayerView);
        mPlayerView.setPlayer(ExoPlayerManager.getSharedInstance(MainActivity.this).getPlayerView().getPlayer());
        ExoPlayerManager.getSharedInstance(MainActivity.this).playStream(downloadUrl);
    }

}

Conclusion

Now you are done, your project is ready to run, that way you can easily play youtube video in ExoPlayer

Download Project- Play Youtube Video in ExoPlayer

In this post, I will learn about playing YoutubePlayerView in ReyclerView Android. We implement Youtube Player in RecyclerView using WebView with the help of an external library.

Introduction

As usually youtube player API works well in Android in full-screen view. If you want to play a youtube video inside subview, it’s thrown illegal overlay exception for the reason that youtube API is not allowed any kind of overlay, padding, and margin inside the View. Same if you want to play a video in RecylerView similarly Twitter Player Card. In Twitter, Player Card video is played as WebView with some metadata. You no need to learn deep. We have on prebuilt lib for this.

If you facing illegal overlay issue in youtube player, You are in right place. Basically,
YouTube Android Player API is strictly prohibited overlay, So while you play in RecyclerView in then the video will be stopped after few second. Now I explain hows play YoutubePlayer in RecyclerView like Twitter. I’m using a library Android YouTube Player.

This is the fully open source library. The player is run on Webview within IFrame API, is easy to maintain and scalable. This library uses YouTube’s own web player to play videos, to interact with YouTube the library uses the IFrame Player API, inside of a WebView, therefore the YouTube app is not required on the user’s device and there are no issues with YouTube Terms of Service. Let’s learn the implementation step by step

YoutubePlayerView in ReyclerView Sample App

Implementation Steps

1. First of all, create a new project with the name Youtube Player Example.

Go to file menu => Create a new project => Enter a project name and packages name => Select template => Finish

2. Add dependency inside app/build.gradle

Now we need to add below dependency in build.gradle

  • AndroidX – Support lib
  • Glide – For image loading lib
  • ButterKnife – DI View Binding
  • IFrame Player API – Youtube lib
2.1 Define youtube player and butterknife dependency
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    // replace support with androidx
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    // Image loading lib
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    // Youtube lib
    implementation 'com.github.PierfrancescoSoffritti:AndroidYouTubePlayer:7.0.1'
    // bind view
    implementation 'com.jakewharton:butterknife:10.1.0'
    annotationProcessor "com.jakewharton:butterknife-compiler:10.1.0"

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
2.2 set compile option java sdk target 1.8 for using lambda expression.
compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

3. Add INTERNET uses permission in AndroidManifest.xml

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Full project structure look as below figure
how to play youtube player in recylerview

4. Let’s create a model class named YoutubeVideo.java

Define all model entities in POJO such as – id, title, videoId, and imageUrl etc.

package com.androidwave.youtuberecycler.model;

  public class YoutubeVideo {
    private String title;
    private Long id;
    private String videoId;
    private String imageUrl;

    public String getImageUrl() {
      return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
      this.imageUrl = imageUrl;
    }

    public String getTitle() {
      return title;
    }

    public void setTitle(String title) {
      this.title = title;
    }

    public Long getId() {
      return id;
    }

    public void setId(Long id) {
      this.id = id;
    }

    public String getVideoId() {
      return videoId;
    }

    public void setVideoId(String videoId) {
      this.videoId = videoId;
    }
  }

5. BaseViewHolder is helper class for RecyclerView.

Now I’m creating a generics file for BaseViewHolder which extends RecyclerView.ViewHolder. Which help a lot fetching current position of items in RecyclerView Adapter.

package com.androidwave.youtuberecycler.base;

import android.view.View;
import androidx.recyclerview.widget.RecyclerView;

public abstract class BaseViewHolder extends RecyclerView.ViewHolder {

  private int mCurrentPosition;

  public BaseViewHolder(View itemView) {
    super(itemView);
  }

  protected abstract void clear();

  public void onBind(int position) {
    mCurrentPosition = position;
    clear();
  }

  public int getCurrentPosition() {
    return mCurrentPosition;
  }
}

6. Prepare XML layout for list item.

Go to res = > layout folder and creates a layout file named item_youtube_list.xml and paste below code. Finally, the RecyclerView items look like below image

Youtube player in RecyclerView in Android
Youtube Player in RecyclerView tutorial
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    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="wrap_content"
    android:layout_margin="8dp"
    app:cardCornerRadius="6dp"
    app:cardElevation="6dp"
    >

  <androidx.constraintlayout.widget.ConstraintLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      >

    <TextView
        android:id="@+id/textViewTitle"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:letterSpacing="-0.02"
        android:lineSpacingExtra="5sp"
        android:text="TextView"
        android:textColor="@color/navy"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Was india better then south africa in current serise?"
        />

    <ImageView
        android:id="@+id/imageViewItem"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:scaleType="matrix"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textViewTitle"
        />

    <com.pierfrancescosoffritti.youtubeplayer.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textViewTitle"
        />

    <ImageView
        android:id="@+id/btnPlay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="@+id/imageViewItem"
        app:layout_constraintEnd_toEndOf="@+id/imageViewItem"
        app:layout_constraintStart_toStartOf="@+id/imageViewItem"
        app:layout_constraintTop_toTopOf="@+id/imageViewItem"
        app:srcCompat="@drawable/ic_play_button"
        />
  </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

7. Now create a new class named YoutubeRecyclerAdapter.java.

package com.androidwave.youtuberecycler.adapter;

import android.app.Activity;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.androidwave.youtuberecycler.R;
import com.androidwave.youtuberecycler.base.BaseViewHolder;
import com.androidwave.youtuberecycler.model.YoutubeVideo;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.pierfrancescosoffritti.youtubeplayer.player.AbstractYouTubePlayerListener;
import com.pierfrancescosoffritti.youtubeplayer.player.YouTubePlayerView;
import java.util.List;

public class YoutubeRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {

  public static final int VIEW_TYPE_NORMAL = 1;

  private List<YoutubeVideo> mYoutubeVideos;
  DisplayMetrics displayMetrics = new DisplayMetrics();

  public YoutubeRecyclerAdapter(List<YoutubeVideo> youtubeVideos) {
    mYoutubeVideos = youtubeVideos;
  }

  @NonNull
  @Override
  public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new ViewHolder(LayoutInflater.from(parent.getContext())
        .inflate(R.layout.item_youtube_list, parent, false));
  }

  @Override
  public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
    holder.onBind(position);
  }

  @Override
  public int getItemViewType(int position) {
    return VIEW_TYPE_NORMAL;
  }

  @Override
  public int getItemCount() {
    if (mYoutubeVideos != null && mYoutubeVideos.size() > 0) {
      return mYoutubeVideos.size();
    } else {
      return 1;
    }
  }

  public void setItems(List<YoutubeVideo> youtubeVideos) {
    mYoutubeVideos = youtubeVideos;
    notifyDataSetChanged();
  }

  public class ViewHolder extends BaseViewHolder {
    @BindView(R.id.textViewTitle)
    TextView textWaveTitle;
    @BindView(R.id.btnPlay)
    ImageView playButton;

    @BindView(R.id.imageViewItem)
    ImageView imageViewItems;
    @BindView(R.id.youtube_view)
    YouTubePlayerView youTubePlayerView;

    public ViewHolder(View itemView) {
      super(itemView);
      ButterKnife.bind(this, itemView);
    }

    protected void clear() {

    }

    public void onBind(int position) {
      super.onBind(position);
      final YoutubeVideo mYoutubeVideo = mYoutubeVideos.get(position);
      ((Activity) itemView.getContext()).getWindowManager()
          .getDefaultDisplay()
          .getMetrics(displayMetrics);
      int width = displayMetrics.widthPixels;
      if (mYoutubeVideo.getTitle() != null) {
        textWaveTitle.setText(mYoutubeVideo.getTitle());
      }

      if (mYoutubeVideo.getImageUrl() != null) {
        Glide.with(itemView.getContext())
            .load(mYoutubeVideo.getImageUrl()).
            apply(new RequestOptions().override(width - 36, 200))
            .into(imageViewItems);
      }
      imageViewItems.setVisibility(View.VISIBLE);
      playButton.setVisibility(View.VISIBLE);
      youTubePlayerView.setVisibility(View.GONE);

      playButton.setOnClickListener(view -> {
        imageViewItems.setVisibility(View.GONE);
        youTubePlayerView.setVisibility(View.VISIBLE);
        playButton.setVisibility(View.GONE);
        youTubePlayerView.initialize(
            initializedYouTubePlayer -> initializedYouTubePlayer.addListener(
                new AbstractYouTubePlayerListener() {
                  @Override
                  public void onReady() {
                    initializedYouTubePlayer.loadVideo(mYoutubeVideo.getVideoId(), 0);
                  }
                }), true);
      });
    }
  }
}

8. Open the Activity (MainActivity) and bind the views using @inject annotation using butter knife library.

@BindView(R.id.recyclerViewFeed)
RecyclerView recyclerViewFeed;
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }

9. Prepare demo content for list.

private List<YoutubeVideo> prepareList() {
    ArrayList<YoutubeVideo> videoArrayList=new ArrayList<>();

    // add first item
    YoutubeVideo video1 = new YoutubeVideo();
    video1.setId(1l);
    video1.setImageUrl("https://i.ytimg.com/vi/zI-Pux4uaqM/maxresdefault.jpg");
    video1.setTitle(
        "Thugs Of Hindostan - Official Trailer | Amitabh Bachchan | Aamir Khan");
    video1.setVideoId("zI-Pux4uaqM");
    videoArrayList.add(video1);

    // add second item
    YoutubeVideo video2 = new YoutubeVideo();
    video2.setId(2l);
    video2.setImageUrl("https://i.ytimg.com/vi/8ZK_S-46KwE/maxresdefault.jpg");
    video2.setTitle(
        "Colors for Children to Learning with Baby Fun Play with Color Balls Dolphin...");
    video2.setVideoId("8ZK_S-46KwE");

    // add third item
    YoutubeVideo video3 = new YoutubeVideo();
    video3.setId(3l);
    video3.setImageUrl("https://i.ytimg.com/vi/8czMWUH7vW4/hqdefault.jpg");
    video3.setTitle("Air Hostess Accepts Marriage Proposal Mid-Air, Airline Fires her.");
    video3.setVideoId("8czMWUH7vW4");

    // add four item
    YoutubeVideo video4 = new YoutubeVideo();
    video4.setId(4l);
    video4.setImageUrl("https://i.ytimg.com/vi/YrQVYEb6hcc/maxresdefault.jpg");
    video4.setTitle("EXPERIMENT Glowing 1000 degree METAL BALL vs Gunpowder (100 grams)");
    video4.setVideoId("YrQVYEb6hcc");

    // add four item
    YoutubeVideo video5 = new YoutubeVideo();
    video5.setId(5l);
    video5.setImageUrl("https://i.ytimg.com/vi/S84Fuo2rGoY/maxresdefault.jpg");
    video5.setTitle("What happened after Jauhar of Padmavati");
    video5.setVideoId("S84Fuo2rGoY");

    videoArrayList.add(video1);
    videoArrayList.add(video2);
    videoArrayList.add(video3);
    videoArrayList.add(video4);
    return videoArrayList;
  }

10. Set the adapter over RecyclerView.

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    // prepare data for list
    List<YoutubeVideo> youtubeVideos = prepareList();
    mRecyclerAdapter = new YoutubeRecyclerAdapter(youtubeVideos);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerViewFeed.setLayoutManager(mLayoutManager);
    recyclerViewFeed.setItemAnimator(new DefaultItemAnimator());
    recyclerViewFeed.setAdapter(mRecyclerAdapter);
  }

11. Finally, MainActivity.java source look like this

package com.androidwave.youtuberecycler;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.androidwave.youtuberecycler.adapter.YoutubeRecyclerAdapter;
import com.androidwave.youtuberecycler.model.YoutubeVideo;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

  @BindView(R.id.recyclerViewFeed)
  RecyclerView recyclerViewFeed;

  YoutubeRecyclerAdapter mRecyclerAdapter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    // prepare data for list
    List<YoutubeVideo> youtubeVideos = prepareList();
    mRecyclerAdapter = new YoutubeRecyclerAdapter(youtubeVideos);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerViewFeed.setLayoutManager(mLayoutManager);
    recyclerViewFeed.setItemAnimator(new DefaultItemAnimator());
    recyclerViewFeed.setAdapter(mRecyclerAdapter);
  }

  private List<YoutubeVideo> prepareList() {
    ArrayList<YoutubeVideo> videoArrayList=new ArrayList<>();

    // add first item
    YoutubeVideo video1 = new YoutubeVideo();
    video1.setId(1l);
    video1.setImageUrl("https://i.ytimg.com/vi/zI-Pux4uaqM/maxresdefault.jpg");
    video1.setTitle(
        "Thugs Of Hindostan - Official Trailer | Amitabh Bachchan | Aamir Khan");
    video1.setVideoId("zI-Pux4uaqM");
    videoArrayList.add(video1);

    // add second item
    YoutubeVideo video2 = new YoutubeVideo();
    video2.setId(2l);
    video2.setImageUrl("https://i.ytimg.com/vi/8ZK_S-46KwE/maxresdefault.jpg");
    video2.setTitle(
        "Colors for Children to Learning with Baby Fun Play with Color Balls Dolphin...");
    video2.setVideoId("8ZK_S-46KwE");

    // add third item
    YoutubeVideo video3 = new YoutubeVideo();
    video3.setId(3l);
    video3.setImageUrl("https://i.ytimg.com/vi/8czMWUH7vW4/hqdefault.jpg");
    video3.setTitle("Air Hostess Accepts Marriage Proposal Mid-Air, Airline Fires her.");
    video3.setVideoId("8czMWUH7vW4");

    // add four item
    YoutubeVideo video4 = new YoutubeVideo();
    video4.setId(4l);
    video4.setImageUrl("https://i.ytimg.com/vi/YrQVYEb6hcc/maxresdefault.jpg");
    video4.setTitle("EXPERIMENT Glowing 1000 degree METAL BALL vs Gunpowder (100 grams)");
    video4.setVideoId("YrQVYEb6hcc");

    // add four item
    YoutubeVideo video5 = new YoutubeVideo();
    video5.setId(5l);
    video5.setImageUrl("https://i.ytimg.com/vi/S84Fuo2rGoY/maxresdefault.jpg");
    video5.setTitle("What happened after Jauhar of Padmavati");
    video5.setVideoId("S84Fuo2rGoY");

    videoArrayList.add(video1);
    videoArrayList.add(video2);
    videoArrayList.add(video3);
    videoArrayList.add(video4);
    return videoArrayList;
  }
}

Finally, we have learned youtube player in RecyclerView with the help of this example. Thanks a lot

YoutubePlayerView in RecyclerView Source Code