Libraries

Youtube player in RecyclerView in Android

Google+ Pinterest LinkedIn Tumblr

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 a video 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.

Prerequisite

1. First of all, create a new project with the name YoutubePlayer.

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

2. Add below dependency in build.gradle also

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    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'
    implementation 'com.android.support:cardview-v7:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    // Image loading lib
    implementation('com.github.bumptech.glide:glide:[email protected]') {
        transitive = true
    }
    // Youtube lib
    implementation 'com.github.PierfrancescoSoffritti:AndroidYouTubePlayer:7.0.1'
    // code generator for view
    implementation 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
}
2.1 set compile option java sdk target 1.8 for using lambda expression.
  compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

3. Furthermore add uses permission in AndroidMenifest.xml

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
how to play youtube player in recylerview

The complete folder structure look like

4. Now create a Model class name with YoutubeVideo.java

Create a POJO with the following entity like – id, title, videoId, and imageUrl

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. Create a Base RecyclerView.ViewHolder

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.support.v7.widget.RecyclerView;
import android.view.View;

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. Let’s create an item view for recycler adapter item_youtube_list.xml

The item view design seem like below

How to play YouTube player in RecyclerView
Playing RecyclerView in android

Let’s prepare item_youtube_list.xml RecylerView item layout. It seems like above image

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

    <android.support.constraint.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" />
    </android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>

7. Create a new class YoutubeRecyclerAdapter.java for RecyclerView Adapter set data on item views

package com.androidwave.youtuberecycler.adapter;

import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
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 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;

import butterknife.BindView;
import butterknife.ButterKnife;

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 &amp;&amp; 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. Comes in main activity and inject view using ButterKnief

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

9. Now prepare demo item list

 private List<YoutubeVideo> prepareList() {
        ArrayList mYoutubeVideo = 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 | Katrina Kaif | Fatima");
        video1.setVideoId("zI-Pux4uaqM");
        mYoutubeVideo.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 Slider Toy Set Kids Edu");
        video2.setVideoId("8ZK_S-46KwE");
        mYoutubeVideo.add(video2);

        // 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");
        mYoutubeVideo.add(video3);

        // 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");
        mYoutubeVideo.add(video4);

        // 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");
        mYoutubeVideo.add(video5);

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

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. The finally MainActivity.java source seems like below

package com.androidwave.youtuberecycler;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.androidwave.youtuberecycler.adapter.YoutubeRecyclerAdapter;
import com.androidwave.youtuberecycler.model.YoutubeVideo;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

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 mYoutubeVideo = 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 | Katrina Kaif | Fatima");
        video1.setVideoId("zI-Pux4uaqM");
        mYoutubeVideo.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 Slider Toy Set Kids Edu");
        video2.setVideoId("8ZK_S-46KwE");
        mYoutubeVideo.add(video2);

        // 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");
        mYoutubeVideo.add(video3);

        // 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");
        mYoutubeVideo.add(video4);

        // 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");
        mYoutubeVideo.add(video5);

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

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 🙂

Download Sample Project- Youtube player in RecyclerView in Android
Author

11 Comments

  1. Karan Khurana Reply

    Hi,

    I’ve been trying to implement your below dependency and facing some issue. I’m also posting error occuring due to this dependency and please help me resolve it.

    implementation ‘com.pierfrancescosoffritti.androidyoutubeplayer:core:9.0.1’

    Manifest merger failed with multiple errors, see logs

    org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: Execution failed for task ‘:app:processDebugManifest’.
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:139)
    at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:109)
    at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:78)
    at org.gradle.internal.invocation.GradleBuildController$1.call(GradleBuildController.java:75)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:152)
    at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:100)
    at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:75)
    at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:53)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at

    • admin Reply

      I think this issue is related to a different version of two same or dependent lib. Please look at your build.gradle and verify once

  2. Why it is showing double view for every single video please help….

  3. Why it is showing double view for every single video?? plzz help…….

    • admin Reply

      You are doing something wrong, can you share screenshot over the facebook page

      • i just download the source code and when i run it is doubling every video view even in your youtube video which you show in your tutorial .
        You have added 4 videos and it is showing 8 or 9 videos that is it is doubling the list. Please check your youtube video…

        • admin Reply

          Anmol in demo app I’m adding 2 times same URL in array list that by showing two times. If you add in list only one times shows one time only and every things will fine

  4. Its not working man…Okay i am sending your the screenshot on Facebook please check it out….

  5. Waqas Khan Reply

    Source code compiled, but app launch error:

    2019-03-04 16:15:37.183 15174-15174/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)
    at android.os.AsyncTask.finish(AsyncTask.java:695)
    at android.os.AsyncTask.access$600(AsyncTask.java:180)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6718)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Write A Comment