เริ่มต้นใช้งานส่วนขยาย IMA ของ ExoPlayer

ExoPlayer เป็นมีเดียเพลเยอร์ระดับแอปพลิเคชันสำหรับ Android คู่มือนี้แสดงวิธีใช้ ส่วนขยาย ExoPlayer IMA ซึ่งรวม IMA DAI SDK ไว้ด้วย เพื่อขอและเล่นสตรีมสื่อกับทั้งโฆษณาและเนื้อหา

ต่อไปนี้เป็นประโยชน์บางส่วนของส่วนขยาย:

  • ลดความซับซ้อนของโค้ดที่จำเป็นในการผสานรวม IMA กับฟีเจอร์ต่างๆ
  • ลดเวลาในการพัฒนาที่จำเป็นในการอัปเดตเป็น IMA เวอร์ชันใหม่

ส่วนขยาย ExoPlayer IMA รองรับโปรโตคอลสตรีมมิง HLS และ DASH สรุปได้มีดังนี้

การรองรับสตรีมส่วนขยาย ExoPlayer-IMA
ไลฟ์สด สตรีม VOD
HLS เครื่องหมายถูก เครื่องหมายถูก
แดชบอร์ด เครื่องหมายถูก เครื่องหมายถูก

ExoPlayer-IMA เวอร์ชัน 1.1.0 ขึ้นไปรองรับสตรีมแบบสด DASH ได้

คู่มือนี้อิงจากคู่มือ ExoPlayer และแสดงวิธีสร้างแอปเต็มรูปแบบและผสานรวมส่วนขยาย ดูตัวอย่าง ExoPlayerExample จาก GitHub พร้อมแอปตัวอย่างที่สมบูรณ์

สิ่งที่ต้องดำเนินการก่อน

สร้างโปรเจ็กต์ Android Studio ใหม่

หากต้องการสร้างโปรเจ็กต์ Android Studio ให้ทำตามขั้นตอนต่อไปนี้

  • เริ่ม Android Studio
  • เลือกเริ่มโปรเจ็กต์ Android Studio ใหม่
  • ในหน้าเลือกโครงการ ให้เลือกเทมเพลตไม่มีกิจกรรม
  • คลิกถัดไป
  • ในหน้ากำหนดค่าโปรเจ็กต์ ให้ตั้งชื่อโปรเจ็กต์และเลือก Java สำหรับภาษา

  • คลิกเสร็จสิ้น

เพิ่มส่วนขยาย ExoPlayer IMA ในโปรเจ็กต์

เพิ่มการนำเข้าสำหรับส่วนขยายลงในไฟล์ build.gradle ระดับแอปพลิเคชันในส่วน dependencies

กำหนดค่าแอปและเปิดใช้ multidex ขั้นตอนนี้จำเป็นเนื่องจากขนาดของส่วนขยาย ซึ่งจำเป็นสำหรับแอปที่ตั้งค่า minSdkVersion เป็น Android 4.4W (API ระดับ 20) หรือต่ำกว่า

ตัวอย่าง

app/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 กำหนดไว้สำหรับการส่งคำขอโฆษณา

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

    ...

</manifest>

เพิ่มการประกาศ Intent

หากแอปกำหนดเป้าหมายเป็น Android 11 (API ระดับ 30) ขึ้นไป IMA DAI SDK เวอร์ชันปัจจุบันและเวอร์ชันล่าสุดของต้องมีการประกาศความตั้งใจที่จะเปิดเว็บลิงก์อย่างชัดเจน เพิ่มข้อมูลโค้ดต่อไปนี้ลงในไฟล์ Manifest ของแอปเพื่อเปิดใช้การคลิกผ่านของโฆษณา (ผู้ใช้คลิกปุ่มดูข้อมูลเพิ่มเติม)

  <?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>

ตั้งค่า UI ของ ExoPlayer

สร้างออบเจ็กต์ PlayerView ที่ ExoPlayer จะใช้งาน

เปลี่ยน androidx.constraintlayout.widget.ConstraintLayout เป็น LinearLayout ซึ่งแนะนำสำหรับส่วนขยาย ExoPlayer IMA

ตัวอย่าง

app/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:

เพิ่มคีย์เนื้อหา 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();
  }

จัดการเหตุการณ์ของผู้เล่น

สุดท้าย ให้สร้าง Callback สำหรับเหตุการณ์ในวงจรของกิจกรรมเพื่อจัดการการเล่นสตรีม

หากต้องการรองรับ 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 ที่มีโฆษณา คุณจะต้องดำเนินการต่อไปนี้

  1. เพิ่ม CMS ID และ Video ID สำหรับสตรีมทดสอบ VOD
  2. สร้าง URI ของ SSAI VOD โดยใช้ 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 เพื่อดูโค้ดทั้งหมด