ExoPlayer – это медиапроигрыватель для Android. В этом руководстве рассказывается, как использовать расширение IMA для ExoPlayer. Это расширение использует IMA DAI SDK для запроса и воспроизведения медиапотоков с рекламой и контентом.
Преимущества расширения:
- Упрощает код, необходимый для интеграции функций IMA.
- Сокращает время, необходимое для перехода на новые версии IMA.
Расширение IMA для ExoPlayer поддерживает протоколы потоковой передачи HLS и DASH. Вот краткое описание:
| Поддержка потоков в расширении ExoPlayer-IMA | ||
|---|---|---|
| Прямая трансляция | Трансляции видео по запросу | |
| HLS; | ![]() |
![]() |
| DASH | ![]() |
![]() |
Версия 1.1.0 и более поздние версии ExoPlayer-IMA поддерживают трансляции DASH.
В этом руководстве мы будем использовать руководство по ExoPlayer, чтобы создать полноценное приложение и интегрировать расширение. Полный пример приложения можно найти в ExoPlayerExample на GitHub.
Требования
- Android Studio
- AndroidX Media3 ExoPlayer версии 1.0.0 или более поздней для поддержки динамической вставки объявлений.
Как создать проект Android Studio
Чтобы создать проект Android Studio, выполните следующие действия:
- Запустите Android Studio.
- Выберите Начать новый проект Android Studio.
- На странице Выберите проект выберите шаблон Нет действий.
- Нажмите Далее.
- На странице Настройте проект укажите название проекта и выберите язык Java. Примечание. IMA DAI SDK работает с Kotlin, но в этом руководстве используются примеры на Java.
- Нажмите Готово.
Как добавить в проект расширение ExoPlayer IMA
Чтобы добавить расширение IMA для ExoPlayer, выполните следующие действия:
Включите следующие импорты в раздел
dependenciesфайлаbuild.gradleвашего приложения:dependencies { def media3_version = "1.11.0" coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5") implementation(platform("org.jetbrains.kotlin:kotlin-bom:2.3.21")) implementation("androidx.appcompat:appcompat:1.8.0") implementation("androidx.media3:media3-ui:$media3_version") implementation("androidx.media3:media3-exoplayer:$media3_version") implementation("androidx.media3:media3-exoplayer-hls:$media3_version") implementation("androidx.media3:media3-exoplayer-dash:$media3_version") // The library adds the IMA ExoPlayer integration for ads. implementation("androidx.media3:media3-exoplayer-ima:$media3_version") }Добавьте разрешения пользователя, необходимые IMA DAI SDK для запроса объявлений:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Настройка интерфейса ExoPlayer
Чтобы настроить интерфейс ExoPlayer, выполните следующие действия:
Создайте объект
PlayerViewдля ExoPlayer.Измените представление
androidx.constraintlayout.widget.ConstraintLayoutна представлениеLinearLayout, как рекомендовано в расширении IMA для ExoPlayer:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" 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:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!-- UI element for viewing SDK event log --> <TextView android:id="@+id/logText" android:gravity="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="100" android:scrollbars="vertical" android:textSize="@dimen/font_size"> </TextView> </LinearLayout>
Как добавить параметры трансляции
На странице с примерами потоков IMA можно найти объекты потоков, которые помогут вам протестировать проект. Чтобы настроить собственные потоки, ознакомьтесь с разделом о динамической вставке объявлений в Менеджере рекламы.
На этом этапе настраивается трансляция. Расширение ExoPlayer IMA также поддерживает потоки VOD с динамической вставкой объявлений. Чтобы узнать, какие изменения нужно внести в приложение для трансляций видео по запросу, ознакомьтесь с инструкциями для этого типа контента.
Как импортировать расширение ExoPlayer IMA
Добавьте следующие операторы импорта для расширения ExoPlayer:
import static androidx.media3.common.C.CONTENT_TYPE_HLS; import android.annotation.SuppressLint; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.widget.TextView; import androidx.media3.common.MediaItem; 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.ui.PlayerView; import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; import java.util.HashMap; import java.util.Map;В
MyActivity.javaдобавьте следующие частные переменные:PlayerViewExoPlayerImaServerSideAdInsertionMediaSource.AdsLoaderImaServerSideAdInsertionMediaSource.AdsLoader.State
Чтобы протестировать поток HLS Большой кролик Банни (трансляция), добавьте его ключ объекта. Другие потоки для тестирования можно найти на странице с примерами потоков IMA.
Создайте константу
KEY_ADS_LOADER_STATE, чтобы сохранять и получать состояниеAdsLoader:/** Main Activity. */ @SuppressLint("UnsafeOptInUsageError") /* @SuppressLint is needed for new media3 APIs. */ 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 LOG_TAG = "ImaExoPlayerExample"; private static final String NETWORK_CODE = "21775744923"; private PlayerView playerView; private TextView logText; private ExoPlayer player; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; private ImaSdkSettings imaSdkSettings;
Как создать экземпляр adsLoader
Переопределите метод onCreate. Найдите в нем PlayerView и проверьте, есть ли сохраненный AdsLoader.State.
Этот статус можно использовать при инициализации объекта adsLoader.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// Initialize the IMA SDK as early as possible when the app starts. If your app already
// overrides Application.onCreate(), call this method inside the onCreate() method.
// https://developer.android.com/topic/performance/vitals/launch-time#app-creation
ImaSdkFactory.getInstance().initialize(this, getImaSdkSettings());
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);
}
}
}
private ImaSdkSettings getImaSdkSettings() {
if (imaSdkSettings == null) {
imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings();
// Set any IMA SDK settings here.
}
return imaSdkSettings;
}
Добавьте методы для инициализации проигрывателя
Добавьте метод для инициализации проигрывателя. Этот метод должен выполнять следующие действия:
- Создайте экземпляр
AdsLoader. - Создайте
ExoPlayer. - Создайте
MediaItem, используя ключ объекта трансляции. - Задайте
MediaItemдля проигрывателя.
// Create a server side ad insertion (SSAI) AdsLoader.
private ImaServerSideAdInsertionMediaSource.AdsLoader createAdsLoader() {
ImaServerSideAdInsertionMediaSource.AdsLoader.Builder adsLoaderBuilder =
new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(this, playerView);
// Attempts to set the AdsLoader state if available from a previous session.
if (adsLoaderState != null) {
adsLoaderBuilder.setAdsLoaderState(adsLoaderState);
}
return adsLoaderBuilder
.setAdEventListener(buildAdEventListener())
.setImaSdkSettings(getImaSdkSettings())
.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 a SimpleExoPlayer and set it as the player for content and ads.
player = new ExoPlayer.Builder(this).setMediaSourceFactory(mediaSourceFactory).build();
playerView.setPlayer(player);
adsLoader.setPlayer(player);
// Create the MediaItem to play, specifying the stream URI.
Uri ssaiUri = buildLiveStreamUri(SAMPLE_ASSET_KEY, CONTENT_TYPE_HLS);
MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiUri);
// 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);
}
/**
* Builds an IMA SSAI live stream URI for the given asset key and format.
*
* @param assetKey The asset key of the live stream.
* @param format The format of the live stream request, either {@code CONTENT_TYPE_HLS} or {@code
* CONTENT_TYPE_DASH}.
* @return The URI of the live stream.
*/
public Uri buildLiveStreamUri(String assetKey, int format) {
Map<String, String> adTagParams = new HashMap<String, String>();
// Update the adTagParams map with any parameters.
// For more information, see https://support.google.com/admanager/answer/7320899
return new ImaServerSideAdInsertionUriBuilder()
.setAssetKey(assetKey)
.setFormat(format)
.setNetworkCode(NETWORK_CODE)
.setAdTagParameters(adTagParams)
.build();
}
Добавьте метод для освобождения проигрывателя
Добавьте метод для освобождения проигрывателя. Этот метод должен выполнять следующие действия в указанном порядке:
- Установите для ссылок на проигрыватель значение null и освободите ресурсы проигрывателя.
- Отмените состояние
adsLoader.
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 API уровня 24 и более поздних версий используйте следующие методы:
Для уровней API Android ниже 24 используйте следующие методы:
Методы onStart() и onResume() соответствуют методу playerView.onResume(), а методы onStop() и onPause() – методу playerView.onPause().
На этом шаге также используется событие onSaveInstanceState() для сохранения adsLoaderState.
@Override
public void onStart() {
super.onStart();
initializePlayer();
if (playerView != null) {
playerView.onResume();
}
}
@Override
public void onResume() {
super.onResume();
if (player == null) {
initializePlayer();
if (playerView != null) {
playerView.onResume();
}
}
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onStop() {
super.onStop();
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());
}
}
Настройка трансляции видео по запросу (необязательно)
Если в вашем приложении нужно воспроизводить видео по запросу с рекламой, выполните следующие действия:
- Добавьте теги
CMS IDиVideo IDдля потока видео по запросу. Для тестирования используйте следующие параметры потока:- Идентификатор CMS:
"2548831" - Идентификатор видео:
"tears-of-steel"
- Идентификатор CMS:
Создайте URI SSAI VOD с помощью метода
ImaServerSideAdInsertionUriBuilder():/** * Builds an IMA SSAI VOD stream URI for the given CMS ID, video ID, and format. * * @param cmsId The CMS ID of the VOD stream. * @param videoId The video ID of the VOD stream. * @param format The format of the VOD stream request, either {@code CONTENT_TYPE_HLS} or {@code * CONTENT_TYPE_DASH}. * @return The URI of the VOD stream. */ public Uri buildVodStreamUri(String cmsId, String videoId, int format) { Map<String, String> adTagParams = new HashMap<String, String>(); // Update the adTagParams map with any parameters. // For more information, see https://support.google.com/admanager/answer/7320899 return new ImaServerSideAdInsertionUriBuilder() .setContentSourceId(cmsId) .setVideoId(videoId) .setFormat(format) .setNetworkCode(NETWORK_CODE) .setAdTagParameters(adTagParams) .build(); }Установите новый URI потока VOD в качестве мультимедийного объекта проигрывателя, используя метод
MediaItem.fromUri().
Если все пройдет успешно, вы сможете запросить и воспроизвести медиапоток с помощью расширения ExoPlayer IMA. Полный пример можно найти в образцах DAI для Android на GitHub.
