В этой статье я хочу рассказать и показать, как можно реализовать 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):
<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:
<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:
<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 (вертикальная ориентация):
<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):
<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; 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(); } } 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; 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() { 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(); } }); } protected YouTubePlayer.Provider getYouTubePlayerProvider() { return youTubeView; } 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" />
Так выглядит результат проделанной работы в вертикальной и горизонтальной ориентации:
Я постарался в этой статье рассказать полезную вещь, которая надеюсь пригодится вам для создания интересных проектов и будет полезна. Если у вас остались вопросы, то попробую ответить на них.
Допустим, что вы делаете супер-мега крутой проект и у вас есть его промо-ролик. Наша цель показать это видео внутри вашего приложения, как ознакомительное и дать понять пользователю, что он сделал правильный выбор.
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):
<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:
<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:
<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 (вертикальная ориентация):
<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):
<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; 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(); } } 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; 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() { 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(); } }); } protected YouTubePlayer.Provider getYouTubePlayerProvider() { return youTubeView; } 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" />
Так выглядит результат проделанной работы в вертикальной и горизонтальной ориентации:
Комментарии
Отправить комментарий