ExoPlayer — медиаплеер прикладного уровня для Android. В этом руководстве показано, как можно использовать расширение ExoPlayer IMA , которое является оболочкой IMA DAI SDK, для запроса и воспроизведения медиапотока с рекламой и контентом.
Вот некоторые преимущества расширения:
- Упрощает код, необходимый для интеграции IMA с функциями.
- Сокращает время разработки, необходимое для обновления до новых версий IMA.
Расширение ExoPlayer IMA поддерживает протоколы потоковой передачи HLS и DASH. Вот краткое изложение:
Поддержка потока расширения ExoPlayer-IMA | ||
---|---|---|
Прямая трансляция | VOD-потоки | |
ЗОЖ | ![]() | ![]() |
БРОСАТЬСЯ | ![]() | ![]() |
Прямые трансляции DASH поддерживаются в ExoPlayer-IMA версии 1.1.0+.
Это руководство основано на руководстве ExoPlayer и показывает, как создать полноценное приложение и интегрировать расширение. См. пример ExoPlayerExample
на GitHub с полным примером приложения.
Предварительные условия
- Android-студия
- AndroidX Media3 ExoPlayer версии 1.0.0 или выше для поддержки DAI.
Создайте новый проект Android Studio.
Чтобы создать проект Android Studio, выполните следующие шаги:
- Запустите Android-студию.
- Выберите «Начать новый проект Android Studio» .
- На странице «Выберите проект» выберите шаблон «Нет активности» .
- Нажмите Далее .
На странице «Настройка проекта» укажите имя своего проекта и выберите Java в качестве языка.
Нажмите «Готово» .
Добавьте расширение ExoPlayer IMA в свой проект.
Добавьте импорт для расширения в файл build.gradle уровня приложения в разделе dependencies
.
Настройте свое приложение и включите multidex . Это необходимо из-за размера расширения и требуется для приложений, для которых minSdkVersion
установлено значение Android 4,4W (уровень API 20) или ниже.
Вот пример:
приложение/build.gradle
android { ... defaultConfig { applicationId "com.google.ads.interactivemedia.v3.samples.videoplayerapp" minSdkVersion 21 targetSdkVersion 34 multiDexEnabled true versionCode 1 versionName "1.0" } ... } dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.media3:media3-ui:1.1.1' implementation 'androidx.media3:media3-exoplayer:1.1.1' implementation 'androidx.media3:media3-exoplayer-hls:1.1.1' implementation 'androidx.media3:media3-exoplayer-dash:1.1.1' // Adding the ExoPlayer IMA extension for ads will also include the IMA // SDK as a dependency. implementation 'androidx.media3:media3-exoplayer-ima:1.1.1' }
Добавьте разрешения пользователя, необходимые IMA DAI SDK для запроса рекламы:
приложение/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name "> <!-- Required permissions for the IMA DAI SDK --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ... </manifest>
Добавить декларации о намерениях
Если ваше приложение предназначено для Android 11 (уровень API 30) или выше, текущая и последняя версии IMA DAI SDK требуют явного заявления о намерении для открытия веб-ссылок. Добавьте следующий фрагмент в файл манифеста вашего приложения, чтобы включить переходы по объявлениям (пользователи нажимают кнопку «Подробнее» ).
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name "> ... </application> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="https" /> </intent> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http" /> </intent> </queries> </manifest>
Настройте пользовательский интерфейс ExoPlayer
Создайте объект PlayerView
, который будет использоваться ExoPlayer.
Измените androidx.constraintlayout.widget.ConstraintLayout
на LinearLayout
, который рекомендуется для расширения ExoPlayer IMA.
Вот пример:
приложение/src/main/res/layout/activity_my.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:background="@android:color/black" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MyActivity" tools:ignore="MergeRootFrame"> <androidx.media3.ui.PlayerView android:id="@+id/player_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Добавьте параметры вашего потока
См. страницу примера потока IMA , где можно найти примеры ресурсов потока для тестирования вашего проекта. Также посетите раздел Менеджера рекламы на DAI, чтобы получить информацию о настройке собственных потоков.
На этом этапе демонстрируется настройка прямой трансляции, но расширение ExoPlayer IMA также поддерживает потоки DAI VOD. См. шаг для потоков видео по запросу (VOD), чтобы узнать, какие изменения необходимо внести в ваше приложение для обработки потоков VOD.
Импортируйте расширение ExoPlayer IMA.
Добавьте инструкции импорта для расширения ExoPlayer.
Добавьте следующие частные переменные в MyActivity.java
:
-
PlayerView
-
ExoPlayer
-
ImaServerSideAdInsertionMediaSource.AdsLoader
-
ImaServerSideAdInsertionMediaSource.AdsLoader.State
Добавьте ключ ресурса потока HLS Big Buck Bunny (Live) для тестирования с этим потоком. Дополнительные потоки доступны для тестирования на странице образцов потоков IMA .
Создайте константу KEY_ADS_LOADER_STATE
для сохранения и получения состояния AdsLoader
.
Вот пример:
app/src/main/java/com/example/ project name /MyActivity.java
import static androidx.media3.common.C.CONTENT_TYPE_HLS; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.annotation.OptIn; import androidx.media3.common.MediaItem; import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource; import androidx.media3.exoplayer.ima.ImaServerSideAdInsertionUriBuilder; import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import androidx.media3.exoplayer.util.EventLogger; import androidx.media3.ui.PlayerView; import androidx.multidex.MultiDex; ... public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private PlayerView playerView; private ExoPlayer player; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; }
Создайте adsLoader
Перезапишите метод onCreate
, чтобы найти PlayerView
и проверить наличие сохраненного AdsLoader.State
, который можно использовать при инициализации adsLoader
.
Кроме того, включите multidex, если этого требуют количество методов вашего приложения и minSdkVersion
(как описано в шаге 2 ).
Вот пример:
app/src/main/java/com/example/ project name /MyActivity.java
... public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private PlayerView playerView; private ExoPlayer player; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); MultiDex.install(this); playerView = findViewById(R.id.player_view); // Checks if there is a saved AdsLoader state to be used later when // initiating the AdsLoader. if (savedInstanceState != null) { Bundle adsLoaderStateBundle = savedInstanceState.getBundle(KEY_ADS_LOADER_STATE); if (adsLoaderStateBundle != null) { adsLoaderState = ImaServerSideAdInsertionMediaSource.AdsLoader.State.fromBundle( adsLoaderStateBundle); } } } }
Добавьте методы для инициализации плеера
Добавьте метод для инициализации плеера и выполните следующие действия:
- Создайте экземпляр
AdsLoader
. - Создайте
ExoPlayer
. - Создайте
MediaItem
с ключом ресурса прямой трансляции. - Установите
MediaItem
для вашего проигрывателя.
Вот пример:
app/src/main/java/com/example/ project name /MyActivity.java
public class MyActivity extends Activity { ... // Create a server side ad insertion (SSAI) AdsLoader. private ImaServerSideAdInsertionMediaSource.AdsLoader createAdsLoader() { ImaServerSideAdInsertionMediaSource.AdsLoader.Builder adsLoaderBuilder = new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(this, playerView); // Attempt to set the AdsLoader state if available from a previous session. if (adsLoaderState != null) { adsLoaderBuilder.setAdsLoaderState(adsLoaderState); } return adsLoaderBuilder.build(); } private void initializePlayer() { adsLoader = createAdsLoader(); // Set up the factory for media sources, passing the ads loader. DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(this); DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(dataSourceFactory); // MediaSource.Factory to create the ad sources for the current player. ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory = new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, mediaSourceFactory); // 'mediaSourceFactory' is an ExoPlayer component for the DefaultMediaSourceFactory. // 'adsMediaSourceFactory' is an ExoPlayer component for a MediaSource factory for IMA server // side inserted ad streams. mediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory); // Create an ExoPlayer and set it as the player for content and ads. player = new ExoPlayer.Builder(this).setMediaSourceFactory(mediaSourceFactory).build(); playerView.setPlayer(player); adsLoader.setPlayer(player); // Build an IMA SSAI media item to prepare the player with. Uri ssaiLiveUri = new ImaServerSideAdInsertionUriBuilder() .setAssetKey(SAMPLE_ASSET_KEY) .setFormat(CONTENT_TYPE_HLS) // Use CONTENT_TYPE_DASH for dash streams. .build(); // Create the MediaItem to play, specifying the stream URI. MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiLiveUri); // Prepare the content and ad to be played with the ExoPlayer. player.setMediaItem(ssaiMediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); } }
Добавить метод освобождения игрока
Добавьте метод освобождения игрока в следующей последовательности:
- Установите для ссылок игрока значение null и освободите ресурсы игрока.
- Освободите
adsLoader
.
app/src/main/java/com/example/ project name /MyActivity.java
public class MyActivity extends Activity { ... private void releasePlayer() { // Set the player references to null and release the player's resources. playerView.setPlayer(null); player.release(); player = null; // Release the adsLoader state so that it can be initiated again. adsLoaderState = adsLoader.release(); }
Обработка событий игрока
Наконец, создайте обратные вызовы для событий жизненного цикла действия для управления воспроизведением потока.
Для поддержки Android SDK версии 24+:
Для поддержки версий Android SDK ниже 24: - onResume()
- onPause()
onStart()
и onResume()
сопоставляются с playerView.onResume()
, а onStop()
и onPause()
сопоставляются с playerView.onPause()
.
На этом шаге также используется событие onSaveInstanceState()
, чтобы попытаться adsLoaderState
.
app/src/main/java/com/example/ project name /MyActivity.java
public class MyActivity extends Activity { ... @Override public void onStart() { super.onStart(); if (Util.SDK_INT > 23) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onResume() { super.onResume(); if (Util.SDK_INT <= 23 || player == null) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onPause() { super.onPause(); if (Util.SDK_INT <= 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onStop() { super.onStop(); if (Util.SDK_INT > 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onSaveInstanceState(Bundle outState) { // Attempts to save the AdsLoader state to handle app backgrounding. if (adsLoaderState != null) { outState.putBundle(KEY_ADS_LOADER_STATE, adsLoaderState.toBundle()); } } ... }
Настройка потока VOD (необязательно)
Если вашему приложению требуется воспроизведение VOD-контента с рекламой, вам необходимо сделать следующее:
- Добавьте
CMS ID
иVideo ID
для тестового потока VOD. - Создайте URI VOD SSAI с помощью
ImaServerSideAdInsertionUriBuilder()
. - Используйте этот новый URI в качестве медиа-элемента вашего проигрывателя.
app/src/main/java/com/example/ project name /MyActivity.java
public class MyActivity extends Activity { private static final String KEY_ADS_LOADER_STATE = "ads_loader_state"; private static final String SAMPLE_ASSET_KEY = "c-rArva4ShKVIAkNfy6HUQ"; private static final String SAMPLE_CMS_ID = "2548831"; private static final String SAMPLE_VIDEO_ID = "tears-of-steel"; ... private void initializePlayer() { ... Uri ssaiVodUri = new ImaServerSideAdInsertionUriBuilder() .setContentSourceId(SAMPLE_CMS_ID) .setVideoId(SAMPLE_VIDEO_ID) .setFormat(CONTENT_TYPE_HLS) .build(); // Create the MediaItem to play, specifying the stream URI. MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiVodUri); // Prepare the content and ad to be played with the ExoPlayer. player.setMediaItem(ssaiMediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); }
Вот и все! Теперь вы запрашиваете и воспроизводите медиапоток с расширением ExoPlayer IMA. Полный код можно найти в примерах Android DAI на GitHub .