ExoPlayer 是一款适用于 Android 的应用级媒体播放器。本指南介绍了如何使用封装了 IMA DAI SDK 的 ExoPlayer IMA 扩展程序请求和播放包含广告和内容的媒体流。
以下是该扩展程序的一些优势:
- 简化了将 IMA 与功能集成所需的代码。
- 缩短更新到新版 IMA 所需的开发时间。
ExoPlayer IMA 扩展支持 HLS 和 DASH 流式传输协议。下面是摘要:
ExoPlayer-IMA 扩展流支持 | ||
---|---|---|
直播 | VOD 串流 | |
HLS | ||
DASH |
ExoPlayer-IMA 版本 1.1.0 及更高版本支持 DASH 直播。
本指南基于 ExoPlayer 指南,介绍了如何创建完整应用并集成扩展程序。如需查看包含完整示例应用的示例,请参阅 GitHub 上的 ExoPlayerExample
。
前提条件
- Android Studio
- AndroidX Media3 ExoPlayer 1.0.0 版或更高版本,以支持 DAI。
创建一个新的 Android Studio 项目
如需创建 Android Studio 项目,请完成以下步骤:
- 启动 Android Studio。
- 选择 Start a new Android Studio project。
- 在 Choose your project 页面中,选择 No Activity 模板。
- 点击下一步。
在 Configure your project 页面中,为项目命名,然后选择 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 要求明确声明打开网页链接的 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>
设置 ExoPlayer 的界面
创建要供 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 扩展程序的 import 语句。
将以下私有变量添加到 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); } }
添加用于释放播放器的方法
添加一个方法以按以下顺序释放玩家:
- 将播放器引用设为 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(); }
处理播放器事件
最后,为 activity 的生命周期事件创建回调,以处理流式播放。
如需支持 Android SDK 24 及更高版本,请执行以下操作:
如需支持低于 24 的 Android SDK 版本,请执行以下操作:
- 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 示例。