ExoPlayer 是 Android 的應用程式層級媒體播放器。本指南說明如何使用 ExoPlayer IMA 擴充功能 (包裝 IMA DAI SDK),請求及播放含有廣告和內容的媒體串流。
以下列舉擴充功能的幾項優點:
- 簡化整合 IMA 與功能所需的程式碼。
- 縮短更新至新版 IMA 所需的開發時間。
ExoPlayer IMA 擴充功能支援 HLS 和 DASH 串流通訊協定。以下是摘要:
ExoPlayer-IMA 擴充功能串流支援 | ||
---|---|---|
直播 | VOD 串流 | |
HLS | ||
DASH |
ExoPlayer-IMA 1.1.0 以上版本支援 DASH 直播。
本指南以 ExoPlayer 指南為基礎,說明如何建立完整應用程式並整合擴充功能。如需完整範例應用程式的範例,請參閱 GitHub 上的 ExoPlayerExample
。
必要條件
建立新的 Android Studio 專案
如要建立 Android Studio 專案,請完成下列步驟:
- 啟動 Android Studio。
- 選取「Start a new Android Studio project」。
- 在「Choose your project」頁面中,選取「No Activity」範本。
- 點選「下一步」。
在「Configure your project」頁面中為專案命名,並選取 Java 做為語言。
按一下「完成」。
在專案中新增 ExoPlayer IMA 擴充功能
在 dependencies
區段中,將擴充功能的匯入項目新增至應用程式層級的 build.gradle 檔案。
設定應用程式並啟用 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>
新增意圖宣告
如果應用程式指定 Android 11 (API 級別 30) 以上版本,則目前和近期版本的 IMA DAI SDK 需要明確宣告意圖,才能開啟網頁連結。將以下程式碼片段新增至應用程式的資訊清單檔案,即可啟用廣告點閱 (使用者點選「Learn more」按鈕)。
<?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 的 UI
建立 ExoPlayer 要使用的 PlayerView
物件。
將 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 示範串流頁面。如要瞭解如何設定自己的串流,請參閱 DAI 的 Ad Manager 專區。
本步驟將示範如何設定直播,但 ExoPlayer IMA 擴充功能也支援 DAI VOD 串流。請參閱隨選影片 (VOD) 串流步驟,瞭解應用程式需要進行哪些變更才能處理 VOD 串流。
匯入 ExoPlayer IMA 擴充功能
新增 ExoPlayer 擴充功能的匯入陳述式。
將下列私人變數新增至 MyActivity.java
:
PlayerView
ExoPlayer
ImaServerSideAdInsertionMediaSource.AdsLoader
ImaServerSideAdInsertionMediaSource.AdsLoader.State
新增 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; ... 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
物件時使用。
此外,如果應用程式的方法計數和 minSdkVersion
需要,請啟用 Multidex (如步驟 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); } }
新增釋放播放器的方法
新增方法,以便在這個序列中釋放玩家:
- 將播放器參照設為空值,並釋放播放器的資源。
- 釋出
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 以下版本:
- 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 內容,您必須執行下列操作:
- 為 VOD 測試串流新增
CMS ID
和Video ID
。 - 使用
ImaServerSideAdInsertionUriBuilder()
建立 SSAI VOD URI。 - 將這個新 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 擴充功能,要求及播放媒體串流。如需完整程式碼,請參閱 GitHub 上的 Android DAI 範例。