Mobile
Article
By Joyce Echessa

Using the YouTube API to Embed Video in an Android App

By Joyce Echessa
Help us help you! You'll get a... FREE 6-Month Subscription to SitePoint Premium Plus you'll go in the draw to WIN a new Macbook SitePoint 2017 Survey Yes, let's Do this It only takes 5 min

This post was updated in January 2017.

The YouTube Android Player API enables you to incorporate video playback functionality into your Android applications. The API allows you to load and play YouTube videos (and playlists) and to customize and control the video playback experience.

You can load or cue videos into a player view embedded in your application’s UI. You can then control playback programmatically. For example play, pause, or seek to a specific point in the loaded video. You can register event listeners to get callbacks for certain events, such as the player loading a video or the player state changing. The API also has helper functionality to support orientation changes as well as transitions to fullscreen playback.

To get started, create a new project. I called mine VideoTube. On the next window of the Android Studio wizard you can leave the Minimum SDK version at the default API 15 (the YouTube API will only work on API 10 and above). Select the Empty Activity template on the next window and MainActivity as the activity name on the last one.

Before using the Android Youtube API, you need to register your application, including your digitally signed .apk file’s public certificate in the Google Developers Console. To register the application, follow these steps.

  1. Go to the Google Developers Console
  2. Create a new project. I named mine VideoTube.
  3. In the sidebar on the left, make sure that Library is selected. On the right panel, select the Youtube Data API and Enable it on the page that follows.
  4. In the sidebar on the left, select Credentials. For credentials, the API supports OAuth 2.0, the use of an API key and of a Service account. We’ll use the API key option.
  5. Select API key from the Create Credentials dropdown menu. A popup will appear with the value of your API key. Keep this window open, we’ll use the key in the next step.

Note:

The popup window that displays the API key has a Restrict Key button that you can use to restrict the key from unauthorised use. In this tutorial, we won’t restrict the key, but for an app that you plan to push to production, you should definitely restrict access to it. Key restriction lets you specify which websites, IP addresses or apps can use this key. This can help prevent unauthorised use and quota theft.

Back in the Android app, create a class named Config.java and paste in the following.

package com.echessa.videotube;

/**
 * Created by echessa on 1/13/17.
 */
public final class Config {

    private Config() {
    }

    public static final String YOUTUBE_API_KEY = "YOUR API KEY";

}

Paste in your API key.

Download the latest version of the YouTube Android Player API (1.2.2 at the time of writing). Unzip the downloaded file to find the library jar file and a sample application that you can use to see what the library offers. The jar file is located in the libs folder. Copy and paste it into your project’s libs folder. To access the libs folder, use the Project perspective on the Android Studio Project Explorer. Then expand VideoTube -> app -> libs.

Project Explorer

Change back to the Android perspective, select the build.gradle (Module: app) file and add the following to the dependencies.

compile files('libs/YouTubeAndroidPlayerApi.jar')

Sync the project’s gradle files.

Add the following permission for internet access to the AndroidManifest.xml file as a child of the manifest tag and a sibling to the application.

<uses-permission android:name="android.permission.INTERNET"/>

Edit the strings.xml file as shown. These are all the string resources we’ll require.

<resources>
    <string name="app_name">VideoTube</string>
    <string name="player_error">Error initializing YouTube player: %s</string>
    <string name="seek_to">Jump To</string>
    <string name="seek_to_hint">Seconds</string>
</resources>

Next we’ll add a YouTubePlayerView to the layout file. This view is used for displaying YouTube videos.

Modify activity_main.xml as shown.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>

We’ll be using the YouTubePlayerView directly in our activity as opposed to using the YouTubePlayerFragment. Because of this, the activity needs to extend the YouTubeBaseActivity class.

Modify MainActivity.java as shown.

package com.echessa.videotube;

import android.content.Intent;
import android.os.Bundle;
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.YouTubePlayer.Provider;
import com.google.android.youtube.player.YouTubePlayerView;

public class MainActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener {

    private static final int RECOVERY_REQUEST = 1;
    private YouTubePlayerView youTubeView;

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

        youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
        youTubeView.initialize(Config.YOUTUBE_API_KEY, this);
    }

    @Override
    public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) {
        if (!wasRestored) {
            player.cueVideo("fhWaJi1Hsfo"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
        }
    }

    @Override
    public void onInitializationFailure(Provider provider, YouTubeInitializationResult errorReason) {
        if (errorReason.isUserRecoverableError()) {
            errorReason.getErrorDialog(this, RECOVERY_REQUEST).show();
        } else {
            String error = String.format(getString(R.string.player_error), errorReason.toString());
            Toast.makeText(this, error, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == RECOVERY_REQUEST) {
            // Retry initialization if user performed a recovery action
            getYouTubePlayerProvider().initialize(Config.YOUTUBE_API_KEY, this);
        }
    }

    protected Provider getYouTubePlayerProvider() {
        return youTubeView;
    }
}

In the above code, we created a class that is a subclass of YouTubeBaseActivity. This is required to make use of YouTubePlayerView. We implemented YouTubePlayer.OnInitializedListener to listen for initialization success or failure. The interface has two methods, named onInitializationFailure() and onInitializationSuccess(). If initialization is successful, the cueVideo() method plays the YouTube video and incase of failure, checks to see whether the error is recoverable by user action.

If it’s not then a Toast of the error is shown to the user and if it’s user-recoverable, then the getErrorDialog() method shows a dialog that will enable the user to recover from the error.

For example, if the YouTube app isn’t installed on the user’s device or is out of date, the dialog will have a prompt that upon confirmation, will open the Google Play Store for the user to install or update it accordingly. If the YouTube app is disabled on the device, then the prompt will open System Settings for the user to enable it.

When the user returns from the error recovery dialog, onActivityResult() is called checks to see if the user performed a recovery action. If so, we retry initialization.

Run the app and you should be able to play the video specified in the code.

Note:

You need the YouTube app on your device for the video to play. The API client library interacts with a service that is distributed as part of the YouTube app for the Android platform. Users need to run version 4.2.16 of the mobile YouTube app (or higher) to use the API. Generally, devices running Android 2.2 (Froyo) or later that have the Google Play Store app should be able to run the up-to-date version of the YouTube app.

YouTube Player

Responding to Playback Events and State Changes

In the app, you might need to take some action depending on the YouTube player’s events such as buffering, play, pause, seek and stop. You might want to show the user a message or overlay the player view with another view once video playback stops or ends.

The YouTubePlayer has the following interface definitions to listen to such events:
YouTubePlayer.PlayerStateChangeListener – Interface definition for callbacks which invoked when the high level player state changes.
YouTubePlayer.PlaybackEventListener – Interface definition for callbacks which invoked when video playback events occur.
YouTubePlayer.OnFullscreenListener – Interface definition for callbacks which invoked when the player toggles between fullscreen on or off, either due to the user clicking the fullscreen button or a call to setFullscreen(boolean).
YouTubePlayer.PlaylistEventListener – Interface definition for callbacks which invoked when events related to playlists occur.

We’ll look at the first two for this app.

Add the following method to the MainActivity class.

private void showMessage(String message) {
    Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}

This will create a Toast with the message passed into the function. This will save us from writing similar lines of code.

Next add the following two subclasses to the MainActivity class.

private final class MyPlaybackEventListener implements YouTubePlayer.PlaybackEventListener {

    @Override
    public void onPlaying() {
        // Called when playback starts, either due to user action or call to play().
        showMessage("Playing");
    }

    @Override
    public void onPaused() {
        // Called when playback is paused, either due to user action or call to pause().
        showMessage("Paused");
    }

    @Override
    public void onStopped() {
        // Called when playback stops for a reason other than being paused.
        showMessage("Stopped");
    }

    @Override
    public void onBuffering(boolean b) {
        // Called when buffering starts or ends.
    }

    @Override
    public void onSeekTo(int i) {
        // Called when a jump in playback position occurs, either
        // due to user scrubbing or call to seekRelativeMillis() or seekToMillis()
    }
}

private final class MyPlayerStateChangeListener implements YouTubePlayer.PlayerStateChangeListener {

    @Override
    public void onLoading() {
        // Called when the player is loading a video
        // At this point, it's not ready to accept commands affecting playback such as play() or pause()
    }

    @Override
    public void onLoaded(String s) {
        // Called when a video is done loading.
        // Playback methods such as play(), pause() or seekToMillis(int) may be called after this callback.
    }

    @Override
    public void onAdStarted() {
        // Called when playback of an advertisement starts.
    }

    @Override
    public void onVideoStarted() {
        // Called when playback of the video starts.
    }

    @Override
    public void onVideoEnded() {
        // Called when the video reaches its end.
    }

    @Override
    public void onError(YouTubePlayer.ErrorReason errorReason) {
        // Called when an error occurs.
    }
}

The above creates classes that implement the YouTubePlayer.PlaybackEventListener and YouTubePlayer.PlayerStateChangeListener interfaces. For each class, I have implemented the interface methods and included a comment of when the callback is invoked. You can take whatever action you want in each callback. For our example, I have included a Toast output for the onPlaying(), onPaused() and onStopped() methods that will output a message when the event happens.

Add the following class variables to the MainActivity file.

private MyPlayerStateChangeListener playerStateChangeListener;
private MyPlaybackEventListener playbackEventListener;

Add the following to the bottom of onCreate() to initialize the above objects.

playerStateChangeListener = new MyPlayerStateChangeListener();
playbackEventListener = new MyPlaybackEventListener();

Modify onInitializationSuccess() as shown. This sets the listeners on the YouTubePlayer object.

@Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) {
    player.setPlayerStateChangeListener(playerStateChangeListener);
    player.setPlaybackEventListener(playbackEventListener);

    if (!wasRestored) {
        player.cueVideo("fhWaJi1Hsfo"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
    }
}

Run the app and you should see different Toast messages appear when you start playing the video, when you pause it and when it stops (for a reason other than being paused, e.g. the video ending or a playback error).

--ADVERTISEMENT--

Custom Player Controls

The YouTube library does a good job of creating an out-of-the-box user friendly interface to play YouTube videos. As a developer, you might want to take this further and provide custom controls that will give the user more control over playback. For example, enable them to jump back and forth in the video, or enable them to play the next or previous video in a playlist.

We’ll create a control in our app that will enable the user to jump to a specific time in the video.

The API provides two methods to jump playback:
seekToMillis() – Seeks to the specified time in the video.
seekRelativeMillis() – Seeks forward or backwards by the specified number of seconds.

We’ll use the first to jump to a specified time in the video.

Modify activity_main.xml as shown.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context=".MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/seek_to_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:hint="@string/seek_to_hint"/>

        <Button
            android:id="@+id/seek_to_button"
            android:text="@string/seek_to"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>
</LinearLayout>

In MainActivity add the following class variable.

private YouTubePlayer player;

At the beginning of onInitializationSuccess() set this variable.

this.player = player;

Add the following to the bottom of onCreate().

final EditText seekToText = (EditText) findViewById(R.id.seek_to_text);
Button seekToButton = (Button) findViewById(R.id.seek_to_button);
seekToButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        int skipToSecs = Integer.valueOf(seekToText.getText().toString());
        player.seekToMillis(skipToSecs * 1000);
    }
});

Run the app and you should be able to enter a number (in seconds) and have the video skip to that point. If you input a number that is larger than the duration of the video, then the video will skip to the end.

YouTube Player

Conclusion

In this tutorial, we have looked at how to embed a YouTube player in your app. This is handy if you want your app users to be able to play YouTube videos while remaining in your app, instead of the YouTube app opening to play the video and then the user returning to your app after playback.

The YouTube Android library provides a great API that enables you to customise this experience and we’ve only touched on its capabilities. To find out more about the library, be sure to read through the documentation and the sample app that comes with the library download.

You can download the completed project here. Remember to place your key in the Config.java file.

I’d be keen to hear if you try the tutorial and your experiences and any questions you may have.

More:
Login or Create Account to Comment
Login Create Account
Recommended
Sponsors