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 .