Code Example

Android YouTube Video Search Snippets

In this tutorial you will learn how to search youtube videos based on keywords via simple step by step example.

1. Android YouTube API - Search and List Videos

Learn how to search videos from youtube via API and list them in a recyclerview and play the videos.

An Android App which provides the basic functionality of searching videos from youtube, displaying the results and playing them.

This example will help you learn the following concepts:

  1. How to search YouTube for videos based on a keyword.
  2. Search youtube via API
  3. How to play YouTube Videos.
  4. How to fetch youtube videos via API and list them on a recyclerview.

Here are the demo screenshots of what is created:

Android YouTube API - Search and List Videos
Android YouTube API - Search and List Videos
Android YouTube API - Search and List Videos
Android YouTube API - Search and List Videos

This example will comprise the following files:

  • MainActivity.java
  • PlayerActivity.java
  • VideoItem.java
  • YoutubeAdapter.java
  • YoutubeConnector.java

Step 1: Create Project

  1. Open your AndroidStudio IDE.
  2. Go to File-->New-->Project to create a new project.

Step 2: Dependencies

In your app/build.gradle add dependencies as shown below:

apply plugin: 'com.android.application'

android {

    //Compiled for this SDK version
    compileSdkVersion 25

    //buildTools to be used for compiling
    buildToolsVersion "25.0.1"

    defaultConfig {

        //app unique ID
        applicationId "com.test.abhishek.searchyoutube"

        //minimum SDK version on which the app  can be installed and run
        //sdk 21 : Android 5.0(Lollipop)
        minSdkVersion 21

        //Target SDK for which the app is compiled
        //sdk 25 : Android 7.1(Nougat)
        targetSdkVersion 25

        //App's build version
        versionCode 1

        //App's version shown to user
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
    }
}

dependencies {

    //dependency for backward compatibility
    implementation 'com.android.support:appcompat-v7:25.3.1'

    //dependency for RecyclerView
    implementation 'com.android.support:recyclerview-v7:25.3.1'

    //dependency for CardView
    implementation 'com.android.support:cardview-v7:25.3.1'

    //Picasso library dependency
    implementation 'com.squareup.picasso:picasso:2.5.2'

    //google client for android api dependency
    //excluding org.apache.httpcomponents so as to resolve anonymity
    implementation('com.google.api-client:google-api-client-android:1.23.0') {
        exclude group: 'org.apache.httpcomponents'
    }

    //youtube data api v3 dependency
    //excluding org.apache.httpcomponents so as to resolve anonymity
    implementation('com.google.apis:google-api-services-youtube:v3-rev192-1.23.0') {
        exclude group: 'org.apache.httpcomponents'
    }

    //dependency for JSON support
    implementation files('libs/gson-2.1.jar')

    //dependency for finding bugs
    implementation files('libs/jsr305-1.3.9.jar')

    //YouTubeAndroidPlayerApi for playing youtube videos
    implementation files('libs/YouTubeAndroidPlayerApi.jar')
}

Step 3: Design Layouts

*(a). activity_main.xml

Create a file named activity_main.xml and design it as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- This layout defines how the activity should look when the app is opened as this is the layout which is loaded at first -->
<!-- LinearLayout stacks the views one after the other which in this case is vertical orientation -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- A input text type view to enter the search keyword(s)
    and setting the keyboard action to actionSearch so that it shows a search icon 
    for clicking after a text has been entered -->
    <EditText
        android:id="@+id/search_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/search"
        android:imeOptions="actionSearch"
        android:inputType="text"
        android:maxLines="1" />

    <!-- RecyclerView will show the result in a ordered manner
    by infalting the video_item.xml which has the CardView set to show 
    Thumbnail, Video title, id and short description -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/videos_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:dividerHeight="5dp"
        />

</LinearLayout>

*(b). activity_player.xml

Create a file named activity_player.xml and design it as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- This layout defines how the activity should look when a video is clicked and it is played in this activity -->

<!-- LinearLayout stacks the views one after the other which in this case is vertical orientation -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- The YouTubePlayerView view helps to load the video from the id 
    set to it from its cuevideo() method which just loads the video -->
    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <!-- This TextView displays the title of video -->
    <!-- This view has has the following properrties:
            -maxLines for the maximum no of lines that the view can use
            -fonts for special look
            -layout_margin for margin from all sides
     -->
    <TextView
        android:id="@+id/player_title"
        android:text="Title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="4"
        android:typeface="normal"
        android:textAppearance="@style/TextAppearance.AppCompat"
        android:textSize="24sp"
        android:layout_margin="10dp" />

    <!-- This TextView displays the ID of video -->
    <TextView
        android:id="@+id/player_id"
        android:text="Video ID : NA"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
        android:textSize="18sp" />

    <!-- This TextView displays the description of video -->
    <!-- This view has has the following properties:
            -maxLines set to 15 so whole of description can be seen
     -->
    <TextView
        android:id="@+id/player_description"
        android:text="Description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="15"
        android:layout_margin="10dp" />

</LinearLayout>

*(c). video_item.xml

Create a file named video_item.xml and design it as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- This layout defines how a single card or view of the list(RecyclerView) should look -->

<!-- CardView helps design a mini layout in the form of cards -->
<!-- Cards provide an easy way to contain a group of views while providing a consistent style for the container -->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="10dp"
    android:layout_margin="5dp">

    <!-- RelativeLayout places views with respect to each other -->
    <RelativeLayout
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        >

        <!-- ImageView is a view which can show images based on a source -->
        <!-- Size and various properties can be set with the view -->
        <!-- Here image or the thumbnail of the video will be shown -->
        <ImageView
            android:id="@+id/video_thumbnail"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:src="@mipmap/ic_launcher"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true"
            card_view:srcCompat="@color/colorPrimary" />

        <!-- TextView used to show title of the searched video -->
        <TextView
            android:id="@+id/video_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:text="Video Title"
            android:textAppearance="@style/TextAppearance.AppCompat"
            android:textSize="18sp"
            android:textStyle="normal|bold"
            android:maxLines="2"
            android:layout_below="@+id/video_thumbnail" />

        <!-- TextView used to show id of the searched video -->
        <TextView
            android:id="@+id/video_id"
            android:text="Video ID : N/A"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/video_title"
            android:textAppearance="@style/TextAppearance.AppCompat"
            android:fontFamily="sans-serif-condensed"
            android:textStyle="normal|italic"
            android:textSize="14sp" />

        <!-- TextView used to show short description of the searched video -->
        <TextView
            android:id="@+id/video_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/video_id"
            android:text="Video Description"
            android:textAppearance="@style/TextAppearance.AppCompat"
            android:textSize="10sp"
            android:maxLines="2" />

    </RelativeLayout>

</android.support.v7.widget.CardView>

Step 4: Write Code

Write Code as follows:

(a). MainActivity.java

Create a file named MainActivity.java

Extend the AppCompatActivity. This is our launcher activity.

public class MainActivity extends AppCompatActivity {

EditText for input search keywords

private EditText searchInput;

YoutubeAdapter class that serves as a adapter for filling the. RecyclerView by the CardView (video_item.xml) that is created in layout folder

private YoutubeAdapter youtubeAdapter;

RecyclerView manages a long list by recycling the portion of view that is currently visible on screen:

private RecyclerView mRecyclerView;

ProgressDialog can be shown while downloading data from the internet which indicates that the query is being processed

private ProgressDialog mProgressDialog;

Handler to run a thread which could fill the list after downloading data from the internet and inflating the images, title and description

private Handler handler;

Results list of type VideoItem to store the results so that each item int the array list has id, title, description and thumbnail url

private List<VideoItem> searchResults;

Overriding onCreate method(first method to be called) to create the activity and initialise all the variable to their respective views in layout file and adding listeners to required views

@Override
protected void onCreate(Bundle savedInstanceState) {

Calling parent class to recall the app's last state:

super.onCreate(savedInstanceState);

Method to fill the activity that is launched with the activity_main.xml layout file:

setContentView(R.layout.activity_main);

Initailising the objects with their respective view in activity_main.xml file:

mProgressDialog = new ProgressDialog(this);
searchInput = (EditText)findViewById(R.id.search_input);
mRecyclerView = (RecyclerView) findViewById(R.id.videos_recycler_view);

Setting title and and style for progress dialog so that users can understand what is happening currently

mProgressDialog.setTitle("Searching...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

Fixing the size of recycler view which means that the size of the view should not change if adapter or children size changes

mRecyclerView.setHasFixedSize(true);

Give RecyclerView a layout manager to set its orientation to vertical by default it is vertical:

mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

Add listener to the EditText view which listens to changes that occurs when users changes the text or deletes the text passing object of Textview's EditorActionListener to this method

searchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {

onEditorAction method called when user clicks ok button or any custom button set on the bottom right of keyboard

@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

actionId of the respective action is returned as integer which can be checked with our set custom search button in keyboard

if(actionId == EditorInfo.IME_ACTION_SEARCH){

Setting progress message so that users can understand what is happening:

mProgressDialog.setMessage("Finding videos for "+v.getText().toString());

Displaying the progress dialog on the top of activity for two reasons 1.user can see what is going on, 2.User cannot click anything on screen for time being

mProgressDialog.show();

Calling our search method created below with input keyword entered by user by getText method which returns Editable type, get string by toString method

searchOnYoutube(v.getText().toString());

Getting instance of the keyboard or any other input from which user types:

InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

Hiding the keyboard once search button is clicked

imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
InputMethodManager.RESULT_UNCHANGED_SHOWN);

This is a custom search method which takes argument as the keyword for which videos is to be searched:

private void searchOnYoutube(final String keywords){

Create a thread that will execute the searching and inflating the RecyclerView as and when results are found:

new Thread(){

Implementing run method:

public void run(){

Create our YoutubeConnector class's object with Activity context as argument:

YoutubeConnector yc = new YoutubeConnector(MainActivity.this);

Calling the YoutubeConnector's search method by entered keyword and saving the results in list of type VideoItem class

searchResults = yc.search(keywords);

Handler's method used for doing changes in the UI:

handler.post(new Runnable(){

Implementing run method of Runnable

public void run(){

Call method to create Adapter for RecyclerView and filling the list with thumbnail, title, id and description

fillYoutubeVideos();

after the above has been done hiding the ProgressDialog

mProgressDialog.dismiss();

starting the thread

}.start();

Method for creating adapter and setting it to recycler view

private void fillYoutubeVideos(){

object of YoutubeAdapter which will fill the RecyclerView

youtubeAdapter = new YoutubeAdapter(getApplicationContext(),searchResults);

setAdapter to RecyclerView

mRecyclerView.setAdapter(youtubeAdapter);

notify the Adapter that the data has been downloaded so that list can be updapted

youtubeAdapter.notifyDataSetChanged();

Here is the full code

package com.test.abhishek.searchyoutube;

import android.app.ProgressDialog;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;

import android.os.Handler;
import android.os.Bundle;

import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;

import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;
public class MainActivity extends AppCompatActivity {
//end
    private EditText searchInput;
    private YoutubeAdapter youtubeAdapter;

    private RecyclerView mRecyclerView;

    private ProgressDialog mProgressDialog;

    private Handler handler;

    private List<VideoItem> searchResults;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mProgressDialog = new ProgressDialog(this);
        searchInput = (EditText)findViewById(R.id.search_input);
        mRecyclerView = (RecyclerView) findViewById(R.id.videos_recycler_view);

        mProgressDialog.setTitle("Searching...");
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        handler = new Handler();

        searchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {

            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

                if(actionId == EditorInfo.IME_ACTION_SEARCH){

                    mProgressDialog.setMessage("Finding videos for "+v.getText().toString());

                    mProgressDialog.show();

                    searchOnYoutube(v.getText().toString());

                    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
                            InputMethodManager.RESULT_UNCHANGED_SHOWN);

                    return false;
                }
                return true;
            }
        });

    }
    private void searchOnYoutube(final String keywords){

        new Thread(){

            public void run(){

                YoutubeConnector yc = new YoutubeConnector(MainActivity.this);

                searchResults = yc.search(keywords);

                handler.post(new Runnable(){

                    public void run(){

                        fillYoutubeVideos();

                        mProgressDialog.dismiss();
                    }
                });
            }
        }.start();
    }
    private void fillYoutubeVideos(){

        youtubeAdapter = new YoutubeAdapter(getApplicationContext(),searchResults);

        mRecyclerView.setAdapter(youtubeAdapter);

        youtubeAdapter.notifyDataSetChanged();
    }
}

(b). PlayerActivity.java

Create a file named PlayerActivity.java

The activity which plays has YouTubePlayerView inside layout must extend YouTubeBaseActivity. Them implement OnInitializedListener to get the state of the player whether it has succeed or failed to load

public class PlayerActivity extends YouTubeBaseActivity implements OnInitializedListener {
private YouTubePlayerView playerView;

Overriding onCreate method(first method to be called) to create the activity and initialise all the variable to their respective views in layout file and adding listeners to required views

@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);

method to fill the activity that is launched with the activity_player.xml layout file

setContentView(R.layout.activity_player);

getting youtube player view object

playerView = (YouTubePlayerView)findViewById(R.id.player_view);

Iitialize method of YouTubePlayerView used to play videos and control video playback arguments are a valid API key that is enabled to use the YouTube Data API v3 service and YouTubePlayer.OnInitializedListener object or the callbacks that will be invoked when the initialization succeeds or fails as in this case the activity implements OnInitializedListener

playerView.initialize(YoutubeConnector.KEY, this);

Initialising various descriptive data in the UI and player

TextView video_title = (TextView)findViewById(R.id.player_title);
TextView video_desc = (TextView)findViewById(R.id.player_description);
TextView video_id = (TextView)findViewById(R.id.player_id);

Setting text of each View form UI: setText method used to change the text shown in the view, getIntent method returns the object of current Intent of which getStringExtra returns the string which was passed while calling the intent by using the name that was associated during call

video_title.setText(getIntent().getStringExtra("VIDEO_TITLE"));
video_id.setText("Video ID : "+(getIntent().getStringExtra("VIDEO_ID")));
video_desc.setText(getIntent().getStringExtra("VIDEO_DESC"));

The method called if the YouTubePlayerView fails to initialize

@Override
public void onInitializationFailure(Provider provider,
YouTubeInitializationResult result) {
Toast.makeText(this, getString(R.string.failed), Toast.LENGTH_LONG).show();
}

The method called if the YouTubePlayerView succeeds to load the video

@Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player,
boolean restored) {

Initialise the video player only if it is not restored or is not yet set

if(!restored){

cueVideo takes video ID as argument and initialise the player with that video this method just prepares the player to play the video but does not download any of the video stream until play() is called

player.cueVideo(getIntent().getStringExtra("VIDEO_ID"));

Here is the full code

package com.test.abhishek.searchyoutube;

import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.youtube.player.YouTubeBaseActivity;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerView;
import com.google.android.youtube.player.YouTubePlayer.OnInitializedListener;
import com.google.android.youtube.player.YouTubePlayer.Provider;

public class PlayerActivity extends YouTubeBaseActivity implements OnInitializedListener {
    private YouTubePlayerView playerView;

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        setContentView(R.layout.activity_player);
        playerView = (YouTubePlayerView)findViewById(R.id.player_view);

        playerView.initialize(YoutubeConnector.KEY, this);
        TextView video_title = (TextView)findViewById(R.id.player_title);
        TextView video_desc = (TextView)findViewById(R.id.player_description);
        TextView video_id = (TextView)findViewById(R.id.player_id);
        video_title.setText(getIntent().getStringExtra("VIDEO_TITLE"));
        video_id.setText("Video ID : "+(getIntent().getStringExtra("VIDEO_ID")));
        video_desc.setText(getIntent().getStringExtra("VIDEO_DESC"));
    }

    @Override
    public void onInitializationFailure(Provider provider,
                                        YouTubeInitializationResult result) {
        Toast.makeText(this, getString(R.string.failed), Toast.LENGTH_LONG).show();
    }
    @Override
    public void onInitializationSuccess(Provider provider, YouTubePlayer player,
                                        boolean restored) {
        if(!restored){
            player.cueVideo(getIntent().getStringExtra("VIDEO_ID"));
        }
    }
}

(c). VideoItem.java

Create a file named VideoItem.java

Bean class for a single video item

public class VideoItem {

stores id of a video

private String id;

stores title of the video

private String title;

stores the description of video

private String description;

stores the url of thumbnail of video

private String thumbnailURL;

Here is the full code

package com.test.abhishek.searchyoutube;

public class VideoItem {
    private String id;
    private String title;
    private String description;
    private String thumbnailURL;

    //getter and setter methods for id
    public String getId() {
        return id;
    }

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

    //getter and setter methods for video Title
    public String getTitle() {
        return title;
    }

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

    //getter and setter methods for video description
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    //getter and setter methods for thumbnail url
    public String getThumbnailURL() {
        return thumbnailURL;
    }

    public void setThumbnailURL(String thumbnail) {
        this.thumbnailURL = thumbnail;
    }

}

(d). YoutubeAdapter.java

Create a file named YoutubeAdapter.java

The Adapter class for RecyclerView of videos

public class YoutubeAdapter extends RecyclerView.Adapter<YoutubeAdapter.MyViewHolder> {

private Context mContext;
private List<VideoItem> mVideoList;

Provide a reference to the views for each data item Complex data items may need more than one view per item, and you provide access to all the views for a data item in a view holder

public class MyViewHolder extends RecyclerView.ViewHolder{

public ImageView thumbnail;
public TextView video_title, video_id, video_description;
public RelativeLayout video_view;

The video_item.xml file is now associated as view object so the view can be called from view's object

thumbnail = (ImageView) view.findViewById(R.id.video_thumbnail);
video_title = (TextView) view.findViewById(R.id.video_title);
video_id = (TextView) view.findViewById(R.id.video_id);
video_description = (TextView) view.findViewById(R.id.video_description);
video_view = (RelativeLayout) view.findViewById(R.id.video_view);

Parameterised Constructor to save the Activity context and video list helps in initializing a oject for this class

public YoutubeAdapter(Context mContext, List<VideoItem> mVideoList) {
this.mContext = mContext;
this.mVideoList = mVideoList;
}

Create new views (invoked by the layout manager)

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

create a new view

View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.video_item, parent, false);

Replace the contents of a view (invoked by the layout manager) filling every item of view with respective text and image

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {

get element from your dataset at this position, replace the contents of the view with that element

final VideoItem singleVideo = mVideoList.get(position);

Replace the default text with id, title and description with setText method

holder.video_id.setText("Video ID : "+singleVideo.getId()+" ");
holder.video_title.setText(singleVideo.getTitle());
holder.video_description.setText(singleVideo.getDescription());

Handling ImageView recycling and download cancelation in an adapter

Complex image transformations with minimal memory use

```java
Automatic memory and disk caching

```java

//placing the thumbnail with picasso library
//by resizing it to the size of thumbnail

//with method gives access to the global default Picasso instance
//load method starts an image request using the specified path may be a remote URL, file resource, etc.
//resize method resizes the image to the specified size in pixels wrt width and height
//centerCrop crops an image inside of the bounds specified by resize(int, int) rather than distorting the aspect ratio
//into method asynchronously fulfills the request into the specified Target
Load Video thumbnail via Picasso

```java
Picasso.with(mContext)
.load(singleVideo.getThumbnailURL())
.resize(480,270)
.centerCrop()
.into(holder.thumbnail);

setting on click listener for each video_item to launch clicked video in new activity

holder.video_view.setOnClickListener(new View.OnClickListener() {

onClick method called when the view is clicked

@Override
public void onClick(View view) {

Creating a intent for PlayerActivity class from this Activity arguments needed are package context and the new Activity class

Intent intent = new Intent(mContext, PlayerActivity.class);

putExtra method helps to add extra/extended data to the intent which can then be used by the new activity to get initial data from older activity arguments is a name used to identify the data and other is the data itself

intent.putExtra("VIDEO_ID", singleVideo.getId());
intent.putExtra("VIDEO_TITLE",singleVideo.getTitle());
intent.putExtra("VIDEO_DESC",singleVideo.getDescription());

Flags define hot the activity should behave when launched FLAG_ACTIVITY_NEW_TASK flag if set, the activity will become the start of a new task on this history stack. adding flag as it is required for YoutubePlayerView Activity

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Launching the activity by startActivity method use mContext as this class is not the original context

mContext.startActivity(intent);

Return the size of your dataset (invoked by the layout manager) here the dataset is mVideoList

@Override
public int getItemCount() {
return mVideoList.size();
}

Here is the full code

package com.test.abhishek.searchyoutube;

import android.content.Context;
import android.content.Intent;

import android.support.v7.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.List;

public class YoutubeAdapter extends RecyclerView.Adapter<YoutubeAdapter.MyViewHolder> {

    private Context mContext;
    private List<VideoItem> mVideoList;

    public class MyViewHolder extends RecyclerView.ViewHolder{

        public ImageView thumbnail;
        public TextView video_title, video_id, video_description;
        public RelativeLayout video_view;
        public MyViewHolder(View view) {

            super(view);

            thumbnail = (ImageView) view.findViewById(R.id.video_thumbnail);
            video_title = (TextView) view.findViewById(R.id.video_title);
            video_id = (TextView) view.findViewById(R.id.video_id);
            video_description = (TextView) view.findViewById(R.id.video_description);
            video_view = (RelativeLayout) view.findViewById(R.id.video_view);
        }
    }

    public YoutubeAdapter(Context mContext, List<VideoItem> mVideoList) {
        this.mContext = mContext;
        this.mVideoList = mVideoList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.video_item, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

        final VideoItem singleVideo = mVideoList.get(position);

        holder.video_id.setText("Video ID : "+singleVideo.getId()+" ");
        holder.video_title.setText(singleVideo.getTitle());
        holder.video_description.setText(singleVideo.getDescription());

        //Picasso library allows for hassle-free image loading
        // in your application—often in one line of code!
        //Features :

        //placing the thumbnail with picasso library 
        //by resizing it to the size of thumbnail

        //with method gives access to the global default Picasso instance
        //load method starts an image request using the specified path may be a remote URL, file resource, etc.
        //resize method resizes the image to the specified size in pixels wrt width and height
        //centerCrop crops an image inside of the bounds specified by resize(int, int) rather than distorting the aspect ratio
        //into method asynchronously fulfills the request into the specified Target
        Picasso.with(mContext)
                .load(singleVideo.getThumbnailURL())
                .resize(480,270)
                .centerCrop()
                .into(holder.thumbnail);

        holder.video_view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent intent = new Intent(mContext, PlayerActivity.class);

                intent.putExtra("VIDEO_ID", singleVideo.getId());
                intent.putExtra("VIDEO_TITLE",singleVideo.getTitle());
                intent.putExtra("VIDEO_DESC",singleVideo.getDescription());

                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mContext.startActivity(intent);
            }
        });
    }

    @Override
    public int getItemCount() {
        return mVideoList.size();
    }
}

(e). YoutubeConnector.java

Create a file named YoutubeConnector.java

Our YouTube connector class

public class YoutubeConnector {

Youtube object for executing api related queries through Youtube Data API

private YouTube youtube;

Custom list of youtube which gets returned when searched for keyword. Returns a collection of search results that match the query parameters specified in the API request. By default, a search result set identifies matching video, channel, and playlist resources, but you can also configure queries to only retrieve a specific type of resource

private YouTube.Search.List query;

Developer API key a developer can obtain after creating a new project in google developer console. Developer has to enable YouTube Data API v3 in the project. Add credentials and then provide the Application's package name and SHA fingerprint

public static final String KEY = "API_KEY_FROM_GOOGLE_CLOUD_CONSOLE";

Package name of the app that will call the YouTube Data API

public static final String PACKAGENAME = "com.test.abhishek.searchyoutube";

SHA1 fingerprint of APP can be found by double clicking on the app signing report on right tab called gradle

public static final String SHA1 = "SHA1_FINGERPRINT_STRING";

maximum results that should be downloaded via the YouTube data API at a time

private static final long MAXRESULTS = 25;

Constructor to properly initialize Youtube's object

public YoutubeConnector(Context context) {

Youtube.Builder returns an instance of a new builder. Parameters: transport - HTTP transport, jsonFactory - JSON factory, httpRequestInitializer - HTTP request initializer or null for none. This object is used to make YouTube Data API requests. The last argument is required, but since we don't need anything initialized when the HttpRequest is initialized, we override the interface and provide a no-op function.

youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), new HttpRequestInitializer() {

Initialize method helps to add any extra details that may be required to process the query

@Override
public void initialize(HttpRequest request) throws IOException {

Setting package name and sha1 certificate to identify request by server

request.getHeaders().set("X-Android-Package", PACKAGENAME);
request.getHeaders().set("X-Android-Cert",SHA1);

Define the API request for retrieving search results.

query = youtube.search().list("id,snippet");

Setting API key to query. Set your developer key from the {{ Google Cloud Console }} for non-authenticated requests. See: {{ https://cloud.google.com/console }}

query.setKey(KEY);

Restrict the search results to only include videos. See: https://developers.google.com/youtube/v3/docs/search/list#type

query.setType("video");

Setting fields which should be returned, setting only those fields which are required for maximum efficiency here we are retreiving fiels: kind of video, video ID, title of video, description of video, high quality thumbnail url of the video

query.setFields("items(id/kind,id/videoId,snippet/title,snippet/description,snippet/thumbnails/high/url)");

The method to search for our video based on keyword and return a VideoItem object

public List<VideoItem> search(String keywords) {

setting keyword to query

query.setQ(keywords);

max results that should be returned

query.setMaxResults(MAXRESULTS);

executing prepared query and calling Youtube API

SearchListResponse response = query.execute();

Retrieving list from response received. getItems method returns a list from the response which is originally in the form of JSON

List<SearchResult> results = response.getItems();

List of type VideoItem for saving all data individually

List<VideoItem> items = new ArrayList<VideoItem>();

check if result is found and call our setItemsList method

if (results != null) {

//iterator method returns a Iterator instance which can be used to iterate through all values in list
items = setItemsList(results.iterator());
}

The method for filling our array list

private static List<VideoItem> setItemsList(Iterator<SearchResult> iteratorSearchResults) {

temporary list to store the raw data from the returned results

List<VideoItem> tempSetItems = new ArrayList<>();

if no result then printing appropriate output

if (!iteratorSearchResults.hasNext()) {
System.out.println(" There aren't any results for your query.");
}

iterating through all search results, hasNext() method returns true until it has no elements left to iterate

while (iteratorSearchResults.hasNext()) {

next() method returns single instance of current video item and returns next item everytime it is called. SearchResult is Youtube's custom result type which can be used to retrieve data of each video item

SearchResult singleVideo = iteratorSearchResults.next();

getId() method returns the resource ID of one video in the result obtained

ResourceId rId = singleVideo.getId();

Confirm that the result represents a video. Otherwise, the item will not contain a video ID. getKind() returns which type of resource it is which can be video, playlist or channel

if (rId.getKind().equals("youtube#video")) {

object of VideoItem class that can be added to array list

VideoItem item = new VideoItem();

getting High quality thumbnail object URL of thumbnail is in the heirarchy snippet/thumbnails/high/url

Thumbnail thumbnail = singleVideo.getSnippet().getThumbnails().getHigh();

Retrieving title,description,thumbnail url, id from the heirarchy of each resource, Video ID - id/videoId, Title - snippet/title, Description - snippet/description, Thumbnail - snippet/thumbnails/high/url

item.setId(singleVideo.getId().getVideoId());
item.setTitle(singleVideo.getSnippet().getTitle());
item.setDescription(singleVideo.getSnippet().getDescription());
item.setThumbnailURL(thumbnail.getUrl());

adding one Video item to temporary array list

tempSetItems.add(item);

For debug purpose printing one by one details of each Video that was found

System.out.println(" Video Id" + rId.getVideoId());
System.out.println(" Title: " + singleVideo.getSnippet().getTitle());
System.out.println(" Thumbnail: " + thumbnail.getUrl());
System.out.println(" Description: "+ singleVideo.getSnippet().getDescription());
System.out.println("n-------------------------------------------------------------n");

Here is the full code

    package com.test.abhishek.searchyoutube;

    import android.content.Context;
    import android.util.Log;
    import android.widget.Toast;

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    import com.google.api.client.http.HttpRequest;
    import com.google.api.client.http.HttpRequestInitializer;
    import com.google.api.client.http.javanet.NetHttpTransport;
    import com.google.api.client.json.jackson2.JacksonFactory;

    import com.google.api.services.youtube.YouTube;
    import com.google.api.services.youtube.model.ResourceId;
    import com.google.api.services.youtube.model.SearchListResponse;
    import com.google.api.services.youtube.model.SearchResult;
    import com.google.api.services.youtube.model.Thumbnail;

    public class YoutubeConnector {
        private YouTube youtube;
        private YouTube.Search.List query;

        public static final String KEY = "API_KEY_FROM_GOOGLE_CLOUD_CONSOLE";
        public static final String PACKAGENAME = "com.test.abhishek.searchyoutube";
        public static final String SHA1 = "SHA1_FINGERPRINT_STRING";
        private static final long MAXRESULTS = 25;
        public YoutubeConnector(Context context) {
            youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), new HttpRequestInitializer() {
                @Override
                public void initialize(HttpRequest request) throws IOException {

                    request.getHeaders().set("X-Android-Package", PACKAGENAME);
                    request.getHeaders().set("X-Android-Cert",SHA1);
                }
            }).setApplicationName("SearchYoutube").build();

            try {

                query = youtube.search().list("id,snippet");

                query.setKey(KEY);

                query.setType("video");
                query.setFields("items(id/kind,id/videoId,snippet/title,snippet/description,snippet/thumbnails/high/url)");
            } catch (IOException e) {

                //printing stack trace if error occurs
                Log.d("YC", "Could not initialize: " + e);
            }
        }
        public List<VideoItem> search(String keywords) {
            query.setQ(keywords);
            query.setMaxResults(MAXRESULTS);
            try {

                SearchListResponse response = query.execute();
                List<SearchResult> results = response.getItems();
                List<VideoItem> items = new ArrayList<VideoItem>();
                if (results != null) {

                    //iterator method returns a Iterator instance which can be used to iterate through all values in list
                    items = setItemsList(results.iterator());
                }
                return items;

            } catch (IOException e) {

                //catch exception and print on console
                Log.d("YC", "Could not search: " + e);
                return null;
            }
        }

        private static List<VideoItem> setItemsList(Iterator<SearchResult> iteratorSearchResults) {
            List<VideoItem> tempSetItems = new ArrayList<>();
            if (!iteratorSearchResults.hasNext()) {
                System.out.println(" There aren't any results for your query.");
            }

            while (iteratorSearchResults.hasNext()) {

                SearchResult singleVideo = iteratorSearchResults.next();

                ResourceId rId = singleVideo.getId();
                if (rId.getKind().equals("youtube#video")) {

                    VideoItem item = new VideoItem();
                    Thumbnail thumbnail = singleVideo.getSnippet().getThumbnails().getHigh();

                    item.setId(singleVideo.getId().getVideoId());
                    item.setTitle(singleVideo.getSnippet().getTitle());
                    item.setDescription(singleVideo.getSnippet().getDescription());
                    item.setThumbnailURL(thumbnail.getUrl());

                    tempSetItems.add(item);

                    System.out.println(" Video Id" + rId.getVideoId());
                    System.out.println(" Title: " + singleVideo.getSnippet().getTitle());
                    System.out.println(" Thumbnail: " + thumbnail.getUrl());
                    System.out.println(" Description: "+ singleVideo.getSnippet().getDescription());
                    System.out.println("n-------------------------------------------------------------n");
                }
            }
            return tempSetItems;
        }
    }

Run

Simply copy the source code into your Android Project,Build and Run.

Reference

  1. Download code or Browse here.
  2. Follow code author.

Read More.