Начните работу с расширением ExoPlayer IMA

ExoPlayer — это медиаплеер уровня приложения для Android. В этом руководстве показано, как можно использовать расширение ExoPlayer IMA , которое оборачивает IMA DAI SDK, для запроса и воспроизведения медиапотока с рекламой и контентом.

Вот некоторые из преимуществ расширения:

  • Упрощает код, необходимый для интеграции IMA с функциями.
  • Сокращает время разработки, необходимое для обновления до новых версий IMA.

Расширение ExoPlayer IMA поддерживает протоколы потоковой передачи HLS и DASH. Вот краткое изложение:

Поддержка потоковой передачи расширения ExoPlayer-IMA
Прямая трансляция VOD-потоки
ЗОЖ CheckmarkCheckmark
БРОСАТЬСЯ CheckmarkCheckmark

Прямые трансляции DASH поддерживаются на ExoPlayer-IMA версии 1.1.0+.

Это руководство основано на руководстве ExoPlayer и показывает, как создать полное приложение и интегрировать расширение. См. ExoPlayerExample из GitHub для примера с полным образцом приложения.

Предпосылки

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

Чтобы создать свой проект Android Studio, выполните следующие шаги:

  • Запустите Android Studio.
  • Выберите Начать новый проект Android Studio .
  • На странице «Выберите проект» выберите шаблон «Нет активности» .
  • Нажмите Далее .
  • На странице «Настройка проекта» дайте проекту имя и выберите Java в качестве языка.

  • Нажмите «Готово» .

Добавьте расширение ExoPlayer IMA в свой проект

Добавьте импорты для расширения в файл build.gradle уровня приложения в разделе dependencies .

Настройте свое приложение и включите multidex . Это необходимо из-за размера расширения и требуется для приложений с minSdkVersion , установленным на Android 4.4W (API level 20) или ниже.

Вот пример:

приложение/сборка.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.7.1'
    implementation 'androidx.media3:media3-exoplayer:1.7.1'
    implementation 'androidx.media3:media3-exoplayer-hls:1.7.1'
    implementation 'androidx.media3:media3-exoplayer-dash:1.7.1'

    // Adding the ExoPlayer IMA extension for ads will also include the IMA
    // SDK as a dependency.
    implementation 'androidx.media3:media3-exoplayer-ima:1.7.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 для образцов потоков для тестирования вашего проекта. Также см. раздел Ad Manager на DAI для информации о настройке собственных потоков.

Этот шаг демонстрирует настройку прямой трансляции, но расширение ExoPlayer IMA также поддерживает потоки DAI VOD. См. шаг для потоков видео по запросу (VOD), чтобы узнать, какие изменения необходимо внести в ваше приложение для обработки потоков VOD.

Импортируйте расширение ExoPlayer IMA

Добавьте операторы импорта для расширения ExoPlayer.

Добавьте следующие частные переменные в MyActivity.java :

Добавьте ключ ресурса потока Big Buck Bunny (Live) HLS для тестирования с этим потоком. Больше потоков доступны для тестирования на странице образцов потоков 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;
import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;
import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;

...

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 ImaSdkSettings imaSdkSettings;
  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 ImaSdkSettings imaSdkSettings;
  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);

    // 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 для вашего проигрывателя.

Вот пример:

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
        .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 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:

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-контент с рекламой, вам необходимо сделать следующее:

  1. Добавьте CMS ID и Video ID для тестового потока VOD.
  2. Создайте SSAI VOD URI с помощью ImaServerSideAdInsertionUriBuilder() .
  3. Используйте этот новый 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 для полного кода.