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

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

<?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
Source Code – YoutubePlayerView in RecyclerView
19 Comments
hello sir , can you guide me how to enable autoplay and hide time and seekbar
thank you
waiting for your reply
Sure, will tell you soon.
Landscape mode Not working Properly how can we do it for better.
I am using this code in existing project ut i can’t use with androidX it gives library compatobility error can you please help how we can use without androidX?
crash on api 22
android.view.InflateException: Binary XML file line #93: Error inflating class com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
at com.nanotricks.engaarea.adapter.FeedsAdapter.onCreateViewHolder(FeedsAdapter.java:93)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6794)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5975)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
at androidx.constraintlayou
It’s working fine on my side, can you inbox me on facebook?
Awesom android tutorials thanks for this tutorials…
Thank’s
Hi,
First of all thanks for the awesome library.
I’m using this library and working well in Debug mode, but not working in release mode, any idea about this?
Video playback started but a video is not displaying just black screen are there. Thank you:)
Hi , Have you got solutions , for me also same issue , only video is not displaying. Would you have any solutions @morris
During runtime i found this two error. It is related to @BindView(R.id.recyclerViewFeed). Can you please help me ?
error: package R does not exist.
error: java.lang.annotation.AnnotationTypeMismatchException: Incorrectly typed data found for annotation element public abstract int butterknife.BindView.value() (Found data of type R.id)
Here I have used butterknife to bind view, You can remove it or use just findViewById
Does this available for only youtube files? I wonder if this support other files such as outside m3u8 or mp4.
If it is possible, do I have to change which parts of the source?
where to place developers key
This is web embedded youtube lib, so no need of KEY,
where did you place a developer key?
Source code compiled, but app launch error:
com.androidwave.youtubeexoplayer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.androidwave.youtubeexoplayer, PID: 15174
java.lang.NullPointerException: Attempt to invoke virtual method ‘java.lang.String at.huber.youtubeExtractor.YtFile.getUrl()’ on a null object reference
at com.androidwave.youtubeexoplayer.MainActivity$1.onExtractionComplete(MainActivity.java:32)
at at.huber.youtubeExtractor.YouTubeExtractor.onPostExecute(YouTubeExtractor.java:155)
at at.huber.youtubeExtractor.YouTubeExtractor.onPostExecute(YouTubeExtractor.java:33)
Will look it