App Intro c использованием видео из YouTube

В этой статье я хочу рассказать и показать, как можно реализовать App Intro c помощью видео из YouTube. 
Допустим, что вы делаете супер-мега крутой проект и у вас есть его промо-ролик. Наша цель показать это видео внутри вашего приложения, как ознакомительное и дать понять пользователю, что он сделал правильный выбор.


Intro (вводное информационное активити, запускающее при первом старте приложения на девайсе) на базе видео с YouTube может быть весьма полезно, чтобы показать юзеру все фичи в реальном видео. Или это может быть рекламный ролик — не столько фичи, сколько реклама того какой апп интересный, полезный, прикольный и т.п. 

Итак приступим к реалзации: 

1) Для начала нам нужно создать проект и получить API Key в Google Developer Console:

a) создаем проект и активируем YouTube Data API:


b) Создаем API Key для Android приложения: даем название (произвольное), пакет своего проекта и генерируем SHA-1


После этих шагов вы получите API Key, такого плана: AIzaSyCKQSxрJFAHFHj9r2wfwfqkagkhFFa

Сохраните его, мы будем его использовать.

2) Создаем новый проект в Android Studio:

a) добавляем в strings.xml:

<string name="intro_header">Introduction</string> <string name="skip_intro">Skip Intro</string> <string name="error_player">Error initializing Youtube player: %1$s</string>

b) в colors.xml:

<!-- Intro Youtube video --> <color name="intro_skip_normal">#9e9e9e</color> <color name="intro_skip_active">#616161</color>

c) в dimens.xml:

<!-- Additional margins including ones for Intro Youtube video --> <dimen name="middle_margin">8dp</dimen> <dimen name="bottom_text_margin">40dp</dimen>

d) создадим директорию color и в ней файл intro_text_link.xml (будем применять этот стиль в layouts):

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="@color/intro_skip_active" /> <item android:state_focused="true" android:color="@color/intro_skip_active" /> <item android:color="@color/intro_skip_normal" /> <!-- default --> </selector>

На данном этапе нам нужно подключить библиотеку для просмотра видео-роликов. 
Скачиваем архив библиотеки YouTube по этой ссылке.


Далее, нужно скопировать и вставить файл YouTubeAndroidPlayerApi.jar в app/libs (в студии переключиться на Project), и нажать кнопку Sync на панеле инструментов (или в меню: Tools > Android > Sync Project with Gradle Files)

3) Теперь создадим Java класс Config, в котором будем хранить Google API Key и id для видео, которое мы будем использовать в нашем Intro (в URL следует после "?v=", например, для видео www.youtube.com/watch?v=aScEqSidNf8 id будет aScEqSidNf8):


public class Config { //Google API Key static final String API_KEY = "AIzaSyCKQSxрJFAHFHj9r2wfwfqkagkhFFa"; //YouTube video id for intro static final String YOUTUBE_INTRO_ID = "aScEqSidNf8"; }

4) Создадим теперь xml файлы внутри папке drawable, которые будут отвечать за background нашего Intro и за скругление углов:

a) intro_gradient.xml:

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:startColor="@color/colorPrimaryDark" android:centerColor="@color/colorPrimary" android:endColor="@color/colorPrimary" android:angle="270" /> </shape>

b) intro_rounded_corners.xml:

<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="rectangle" > <solid android:color="@android:color/white" /> <corners android:radius="8dp" /> </shape> </item> </layer-list>

5) Теперь создадим layout файл activity_intro.xml для нашего Intro (вертикальная ориентация):

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/intro_gradient"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center_horizontal" android:layout_marginStart="@dimen/activity_horizontal_margin" android:layout_marginEnd="@dimen/activity_horizontal_margin" android:orientation="vertical" android:background="@drawable/intro_rounded_corner"> <TextView android:text="@string/intro_header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textAppearance="@style/TextAppearance.AppCompat.Headline" /> <com.google.android.youtube.player.YouTubePlayerView android:id="@+id/youtube_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/middle_margin" /> <ImageView android:src="@mipmap/ic_launcher" android:contentDescription="@string/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/middle_margin" /> <TextView android:text="@string/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/bottom_text_margin" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:id="@+id/skip_intro" android:text="@string/skip_intro" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/activity_vertical_margin" android:textColor="@color/intro_text_link" /> </LinearLayout> </LinearLayout>

И для горизонтальной ориентации (создаем директорию layout-land, в которую помещаем идентичный файл activity_intro.xml):

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/intro_gradient"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@drawable/intro_rounded_corner" android:layout_gravity="center" android:gravity="center_vertical" android:baselineAligned="false" android:layout_marginStart="@dimen/activity_horizontal_margin" android:layout_marginEnd="@dimen/activity_horizontal_margin"> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:layout_marginTop="@dimen/activity_vertical_margin"> <ImageView android:src="@mipmap/ic_launcher" android:contentDescription="@string/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/middle_margin" /> <TextView android:text="@string/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/bottom_text_margin" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:id="@+id/skip_intro" android:text="@string/skip_intro" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/activity_vertical_margin" android:textColor="@color/intro_text_link" /> </LinearLayout> <com.google.android.youtube.player.YouTubePlayerView android:id="@+id/youtube_view" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" /> </LinearLayout> </LinearLayout>

6) Создаем класс YouTubeFailureRecoveryActivity. Выносим его в отдельный класс, поскольку в случае наличия YouTube-функционала в других частях приложение, используется этот же класс: 

public abstract class YouTubeFailureRecoveryActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener { private static final int RECOVERY_DIALOG_REQUEST = 1; @Override public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult errorReason) { if (errorReason.isUserRecoverableError()) { errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST).show(); } else { String errorMessage = String.format(getString(R.string.error_player), errorReason.toString()); Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RECOVERY_DIALOG_REQUEST) { // Retry initialization if user performed a recovery action getYouTubePlayerProvider().initialize(Config.API_KEY, this); } } protected abstract YouTubePlayer.Provider getYouTubePlayerProvider(); }

7) Создаем IntroActivity.java:

public class IntroActivity extends YouTubeFailureRecoveryActivity { YouTubePlayerView youTubeView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_intro); youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view); youTubeView.initialize(Config.API_KEY, this); // Закрываем Intro при клике на ссылку Skip Intro TextView skipIntro = (TextView) findViewById(R.id.skip_intro); skipIntro.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { /* Чтобы Intro можно было посмотреть позже, например, из главного активити * и чтобы это активити не открывалось повторно при закрытии Intro, добавим * экстра к интенту вызывающего активити: intent.putExtra(EXTRA_TEXT, "MainActivity"). * А здесь проверяем: если есть экстра - значит Intro было запущено из * активити - тогда при клике на Skip Intro просто закрываем Intro. * А если нет экстра - значит Intro было запущено при первом открытии аппа - * сначала открываем главное активити, и затем закрываем Intro. */ Intent intent = getIntent(); String extra = intent.getStringExtra(MainActivity.EXTRA_TEXT); if (extra == null) { intent.setClass(getApplicationContext(), MainActivity.class); startActivity(intent); } finish(); } }); } @Override protected YouTubePlayer.Provider getYouTubePlayerProvider() { return youTubeView; } @Override public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) { if (!b) { youTubePlayer.cueVideo(Config.YOUTUBE_INTRO_ID); } } }

Последним шагом в реализации данного функционала остается добавление permissions в Manifest и декларация IntroActivity:

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

Так выглядит результат проделанной работы в вертикальной и горизонтальной ориентации:


Я постарался в этой статье рассказать полезную вещь, которая надеюсь пригодится вам для создания интересных проектов и будет полезна. Если у вас остались вопросы, то попробую ответить на них.