Exoplayer IMA 扩展程序使用入门

借助 IMA SDK,您可以轻松将多媒体广告集成到您的网站和应用中。IMA SDK 可以从任何 与 VAST 兼容的广告服务器请求广告,并管理应用中的广告播放。借助 IMA 客户端 SDK,您可以控制内容视频播放,而 SDK 则负责处理广告播放。广告在应用内容视频播放器上方的一个单独视频播放器中播放。

本指南演示了如何使用 ExoPlayer IMA 扩展程序将 IMA SDK 集成到空的 Android Studio 项目中。如果您想查看或跟随完整的示例集成,请从 GitHub 下载 BasicExample

IMA 客户端概览

实现 IMA 客户端涉及四个主要 SDK 组件,本指南将对此进行演示:

  • AdDisplayContainer:一个容器对象,用于指定 IMA 在何处呈现广告界面元素并衡量可见度,包括 Active ViewOpen Measurement
  • AdsLoader:用于请求广告并处理广告请求响应中的事件的对象。您应仅实例化一个广告加载器,该加载器可在应用的整个生命周期内重复使用。
  • AdsRequest:用于定义广告请求的对象。广告请求会指定 VAST 广告代码的网址,以及其他参数(例如广告尺寸)。
  • AdsManager:一个对象,包含对广告请求的响应,控制广告播放,并监听 SDK 触发的广告事件。

前提条件

开始前,您需要安装 Android Studio 3.0 或更高版本

1. 创建一个新的 Android Studio 项目

如需创建 Android Studio 项目,请完成以下步骤:

  1. 启动 Android Studio。
  2. 选择 Start a new Android Studio project
  3. Choose your project 页面中,选择 Empty Activity 模板。
  4. 点击下一步
  5. Configure your project 页面中,为项目命名,然后选择 Java 作为语言。
  6. 点击完成

2. 将 ExoPlayer IMA 扩展程序添加到您的项目中

首先,在应用级 build.gradle 文件中,将扩展程序的导入添加到依赖项部分。由于 ExoPlayer IMA 扩展程序的大小,请在此处实现并启用 MultiDex。对于将 minSdkVersion 设置为 20 或更低数值的应用,此操作是必需的。此外,添加了新的 compileOptions 来指定 Java 版本兼容性信息。

app/build.gradle
android {
    namespace 'com.google.ads.interactivemedia.v3.samples.exoplayerexample'
    compileSdkVersion 34

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
  }

  defaultConfig {
      applicationId "com.google.ads.interactivemedia.v3.samples.exoplayerexample"
      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.3.1'
    implementation 'androidx.media3:media3-exoplayer:1.3.1'
    implementation 'androidx.media3:media3-exoplayer-ima:1.3.1'

    ...
}

添加 IMA SDK 请求广告时所需的用户权限。

app/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 SDK -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    ...

</manifest>

添加 intent 声明

如果您的应用以 Android 11(API 级别 30)或更高版本为目标平台,当前和较新版本的 IMA SDK 需要明确声明 intent 才能打开网页链接。将以下代码段添加到应用的清单文件中,以启用广告点击(用户点击了解详情按钮)。
  <?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>

3. 创建广告界面容器

创建一个具有适当 ID 的 StyledPlayerView 对象,以便创建要用作 ExoPlayer PlayerView 的视图。此外,将 androidx.constraintlayout.widget.ConstraintLayout 更改为 LinearLayout

app/src/main/res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.media3.ui.PlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

4. 为广告请求添加内容网址和广告代码网址

strings.xml 添加条目以存储内容网址和 VAST 广告代码网址。

app/src/main/res/values/strings.xml
<resources>
    <string name="app_name">Your_Project_Name</string>
    <string name="content_url"><![CDATA[https://storage.googleapis.com/gvabox/media/samples/stock.mp4]]></string>
    <string name="ad_tag_url"><![CDATA[https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=]]></string>

</resources>

5. 导入 ExoPlayer IMA 扩展程序

添加 ExoPlayer 扩展程序的 import 语句。然后,更新 MainActivity 类,为 PlayerViewSimpleExoPlayerImaAdsLoader 添加私有变量,以扩展 Activity

app/src/main/java/com/example/project name/MainActivity.java

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
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.ImaAdsLoader;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.ui.PlayerView;
import androidx.multidex.MultiDex;

...

public class MainActivity extends Activity {

  private PlayerView playerView;
  private ExoPlayer player;
  private ImaAdsLoader adsLoader;

}

6. 创建 adsLoader 实例

覆盖 onCreate 方法并添加所需的变量赋值,以创建包含广告代码网址的新 adsLoader 对象。

app/src/main/java/com/example/project name/MainActivity.java
...

public class MainActivity extends Activity {

  private PlayerView playerView;
  private ExoPlayer player;
  private ImaAdsLoader adsLoader;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MultiDex.install(this);

    playerView = findViewById(R.id.player_view);

    // Create an AdsLoader.
      adsLoader =
        new ImaAdsLoader.Builder(/* context= */ this)
            .setAdEventListener(buildAdEventListener())
            .build();
  }

  public AdEvent.AdEventListener buildAdEventListener() {

    AdEvent.AdEventListener imaAdEventListener = event -> {
      AdEvent.AdEventType eventType = event.getType();
      // Log IMA events for debugging.
      // The ExoPlayer IMA extension already handles IMA events and does not need anything
      // additional here to function.
    };

    return imaAdEventListener;
  }

}

7. 初始化和释放播放器

添加了用于初始化和释放播放器的方法。在初始化方法中,创建 SimpleExoPlayer。然后,创建 AdsMediaSource 并将其设置为玩家。

app/src/main/java/com/example/project name/MainActivity.java
public class MainActivity extends Activity {

  ...

  private void releasePlayer() {
    adsLoader.setPlayer(null);
    playerView.setPlayer(null);
    player.release();
    player = null;
  }

  private void initializePlayer() {
    // Set up the factory for media sources, passing the ads loader and ad view providers.
    DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(this);

    MediaSource.Factory mediaSourceFactory =
        new DefaultMediaSourceFactory(dataSourceFactory)
            .setLocalAdInsertionComponents(unusedAdTagUri -> adsLoader, playerView);

    // 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);

    // Create the MediaItem to play, specifying the content URI and ad tag URI.
    Uri contentUri = Uri.parse(getString(R.string.content_url));
    Uri adTagUri = Uri.parse(getString(R.string.ad_tag_url));
    MediaItem mediaItem =
        new MediaItem.Builder()
            .setUri(contentUri)
            .setAdsConfiguration(new MediaItem.AdsConfiguration.Builder(adTagUri).build())
            .build();

    // Prepare the content and ad to be played with the SimpleExoPlayer.
    player.setMediaItem(mediaItem);
    player.prepare();

    // Set PlayWhenReady. If true, content and ads will autoplay.
    player.setPlayWhenReady(false);
  }
}

8. 处理播放器事件

最后,为玩家的生命周期事件创建回调:

  • onStart
  • onResume
  • onStop
  • onPause
  • onDestroy
app/src/main/java/com/example/project name/MainActivity.java
public class MainActivity extends Activity {

  private PlayerView playerView;
  private SimpleExoPlayer player;
  private ImaAdsLoader adsLoader;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_my);

      playerView = findViewById(R.id.player_view);

      // Create an AdsLoader.
      adsLoader =
        new ImaAdsLoader.Builder(/* context= */ this)
            .setAdEventListener(buildAdEventListener())
            .build();
  }

  @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
  protected void onDestroy() {
    super.onDestroy();
    adsLoader.release();
  }

  ...

}

大功告成!现在,您可以使用 IMA SDK 请求和展示广告了。如需了解其他 SDK 功能,请参阅其他指南或 GitHub 上的示例