開始使用 Exoplayer IMA 擴充功能

使用 IMA SDK,您就能輕鬆地將多媒體廣告整合至網站和應用程式。IMA SDK 可以 向任何 符合 VAST 規定的廣告伺服器請求廣告,並管理應用程式中的廣告播放情形。使用 IMA 用戶端 SDK,您可以控制內容影片播放,而 SDK 會處理廣告播放。廣告會在應用程式內容影片播放器上方的獨立影片播放器中播放。

本指南說明如何使用 ExoPlayer IMA 擴充功能,將 IMA SDK 整合到空白的 Android Studio 專案中。如果您要查看或執行已完成的範例整合,請下載 GitHub 中的 BasicExample

IMA 用戶端總覽

導入 IMA 用戶端時,牽涉到四個主要的 SDK 元件,詳細方式如下:

  • AdDisplayContainer:顯示廣告的容器物件。
  • 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. 按一下「Finish」

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>

新增意圖宣告

如果您的應用程式指定 Android 11 (API 級別 30) 或以上版本,則現行和最新版本的 IMA 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>

3. 建立廣告 UI 容器

使用適當 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 擴充功能的匯入陳述式。接著,更新 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 範例