ExoPlayer là một trình phát nội dung nghe nhìn trên Android. Hướng dẫn này sẽ cho bạn biết cách sử dụng phần mở rộng ExoPlayer IMA. Tiện ích này sử dụng IMA DAI SDK để yêu cầu và phát các luồng truyền phát nội dung nghe nhìn có cả quảng cáo và nội dung.
Sau đây là danh sách các lợi ích của tiện ích:
- Đơn giản hoá mã cần thiết để tích hợp các tính năng của IMA.
- Giảm thời gian cần thiết để cập nhật lên các phiên bản IMA mới.
Tiện ích IMA của ExoPlayer hỗ trợ giao thức truyền phát trực tiếp HLS và DASH. Sau đây là nội dung tóm tắt:
| Hỗ trợ luồng mở rộng ExoPlayer-IMA | ||
|---|---|---|
| Sự kiện phát trực tiếp | Luồng VOD | |
| HLS (Phát trực tuyến dựa trên HTTP) | ![]() |
![]() |
| DASH (Truyền phát thích ứng động qua HTTP) | ![]() |
![]() |
ExoPlayer-IMA phiên bản 1.1.0 trở lên hỗ trợ luồng phát trực tiếp DASH.
Hướng dẫn này sử dụng hướng dẫn về ExoPlayer để giúp bạn tạo một ứng dụng hoàn chỉnh và tích hợp tiện ích. Để xem một ứng dụng mẫu hoàn chỉnh, hãy xem ExoPlayerExample trên GitHub.
Điều kiện tiên quyết
- Android Studio
- AndroidX Media3 ExoPlayer phiên bản 1.0.0 trở lên để hỗ trợ DAI.
Tạo một dự án Android Studio mới
Để tạo dự án Android Studio, hãy làm theo các bước sau:
- Khởi động Android Studio.
- Chọn Start a new Android Studio project (Bắt đầu một dự án Android Studio mới).
- Trên trang Choose your project (Chọn dự án của bạn), hãy chọn mẫu No Activity (Không có hoạt động).
- Nhấp vào Tiếp theo.
- Trên trang Định cấu hình dự án của bạn, hãy đặt tên cho dự án và chọn Java làm ngôn ngữ. Lưu ý: IMA DAI SDK hoạt động với Kotlin, nhưng hướng dẫn này sử dụng các ví dụ về Java.
- Nhấp vào Hoàn tất.
Thêm tiện ích IMA của ExoPlayer vào dự án
Để thêm tiện ích IMA ExoPlayer, hãy làm như sau:
Đưa các nội dung nhập sau vào phần
dependenciescủa tệpbuild.gradletrong ứng dụng:dependencies { def media3_version = "1.8.0" implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0")) implementation 'androidx.appcompat:appcompat:1.7.1' implementation "androidx.media3:media3-ui:$media3_version" implementation "androidx.media3:media3-exoplayer:$media3_version" implementation "androidx.media3:media3-exoplayer-hls:$media3_version" implementation "androidx.media3:media3-exoplayer-dash:$media3_version" // The library adds the IMA ExoPlayer integration for ads. implementation "androidx.media3:media3-exoplayer-ima:$media3_version" }Thêm các quyền của người dùng mà IMA DAI SDK cần để yêu cầu quảng cáo:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Thiết lập giao diện người dùng ExoPlayer
Để thiết lập giao diện người dùng ExoPlayer, hãy làm như sau:
Tạo đối tượng
PlayerViewcho ExoPlayer.Thay đổi chế độ xem
androidx.constraintlayout.widget.ConstraintLayoutthành chế độ xemLinearLayout, theo đề xuất của tiện ích ExoPlayer IMA:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" 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:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!-- UI element for viewing SDK event log --> <TextView android:id="@+id/logText" android:gravity="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="100" android:scrollbars="vertical" android:textSize="@dimen/font_size"> </TextView> </LinearLayout>
Thêm thông số luồng phát
Hãy xem trang luồng phát mẫu IMA để biết các thành phần luồng phát mẫu nhằm kiểm thử dự án của bạn. Để thiết lập luồng phát của riêng bạn, hãy xem mục DAI trên Ad Manager.
Bước này thiết lập một sự kiện phát trực tiếp. Tiện ích IMA của ExoPlayer cũng hỗ trợ các luồng VOD DAI. Để tìm hiểu những thay đổi mà ứng dụng của bạn cần thực hiện đối với luồng VOD, hãy xem bước dành cho luồng video theo yêu cầu (VOD).
Nhập tiện ích IMA của ExoPlayer
Thêm các câu lệnh nhập sau đây cho tiện ích ExoPlayer:
import static androidx.media3.common.C.CONTENT_TYPE_HLS; import android.annotation.SuppressLint; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.widget.TextView; 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.ui.PlayerView; import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; import java.util.HashMap; import java.util.Map;Trong
MyActivity.java, hãy thêm các biến riêng tư sau:PlayerViewExoPlayerImaServerSideAdInsertionMediaSource.AdsLoaderImaServerSideAdInsertionMediaSource.AdsLoader.State
Để kiểm thử bằng luồng HLS Big Buck Bunny (Live), hãy thêm khoá tài sản của luồng đó. Bạn có thể tìm thêm các luồng để kiểm thử trên trang luồng mẫu của IMA.
Tạo một hằng số
KEY_ADS_LOADER_STATEđể lưu và truy xuất trạng tháiAdsLoader:/** Main Activity. */ @SuppressLint("UnsafeOptInUsageError") /* @SuppressLint is needed for new media3 APIs. */ 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 LOG_TAG = "ImaExoPlayerExample"; private PlayerView playerView; private TextView logText; private ExoPlayer player; private ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader; private ImaServerSideAdInsertionMediaSource.AdsLoader.State adsLoaderState; private ImaSdkSettings imaSdkSettings;
Tạo một thực thể adsLoader
Ghi đè phương thức onCreate. Trong đó, hãy tìm PlayerView và kiểm tra xem có AdsLoader.State đã lưu hay không.
Bạn có thể dùng trạng thái này khi khởi động đối tượng adsLoader.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// Initialize the IMA SDK as early as possible when the app starts. If your app already
// overrides Application.onCreate(), call this method inside the onCreate() method.
// https://developer.android.com/topic/performance/vitals/launch-time#app-creation
ImaSdkFactory.getInstance().initialize(this, getImaSdkSettings());
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);
}
}
}
private ImaSdkSettings getImaSdkSettings() {
if (imaSdkSettings == null) {
imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings();
// Set any IMA SDK settings here.
}
return imaSdkSettings;
}
Thêm các phương thức để khởi chạy trình phát
Thêm một phương thức để khởi chạy trình phát. Phương thức này phải thực hiện những việc sau:
- Tạo một thực thể
AdsLoader. - Tạo
ExoPlayer. - Tạo
MediaItembằng khoá tài sản của sự kiện phát trực tiếp. - Đặt
MediaItemcho trình phát.
// Create a server side ad insertion (SSAI) AdsLoader.
private ImaServerSideAdInsertionMediaSource.AdsLoader createAdsLoader() {
ImaServerSideAdInsertionMediaSource.AdsLoader.Builder adsLoaderBuilder =
new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(this, playerView);
// Attempts to set the AdsLoader state if available from a previous session.
if (adsLoaderState != null) {
adsLoaderBuilder.setAdsLoaderState(adsLoaderState);
}
return adsLoaderBuilder
.setAdEventListener(buildAdEventListener())
.setImaSdkSettings(getImaSdkSettings())
.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 a SimpleExoPlayer 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 stream URI.
Uri ssaiUri = buildLiveStreamUri(SAMPLE_ASSET_KEY, CONTENT_TYPE_HLS);
MediaItem ssaiMediaItem = MediaItem.fromUri(ssaiUri);
// 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);
}
/**
* Builds an IMA SSAI live stream URI for the given asset key and format.
*
* @param assetKey The asset key of the live stream.
* @param format The format of the live stream request, either {@code CONTENT_TYPE_HLS} or {@code
* CONTENT_TYPE_DASH}.
* @return The URI of the live stream.
*/
public Uri buildLiveStreamUri(String assetKey, int format) {
Map<String, String> adTagParams = new HashMap<String, String>();
// Update the adTagParams map with any parameters.
// For more information, see https://support.google.com/admanager/answer/7320899
return new ImaServerSideAdInsertionUriBuilder()
.setAssetKey(assetKey)
.setFormat(format)
.setAdTagParameters(adTagParams)
.build();
}
Thêm phương thức để phát hành trình phát
Thêm một phương thức để phát hành trình phát. Phương thức này phải thực hiện các thao tác sau theo trình tự:
- Đặt các tham chiếu của trình phát thành giá trị rỗng và giải phóng tài nguyên của trình phát.
- Giải phóng trạng thái
adsLoader.
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();
}
Xử lý sự kiện của trình phát
Để xử lý các sự kiện của trình phát, hãy tạo lệnh gọi lại cho các sự kiện trong vòng đời của hoạt động để quản lý hoạt động phát trực tuyến.
Đối với Android API cấp 24 trở lên, hãy sử dụng các phương thức sau:
Đối với các cấp API Android trước 24, hãy sử dụng các phương thức sau:
Các phương thức onStart() và onResume() ánh xạ đến playerView.onResume(), trong khi onStop() và onPause() ánh xạ đến playerView.onPause().
Bước này cũng sử dụng sự kiện onSaveInstanceState() để lưu adsLoaderState.
@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());
}
}
Thiết lập luồng VOD (không bắt buộc)
Nếu ứng dụng của bạn cần phát nội dung VOD có quảng cáo, hãy làm theo các bước sau:
- Thêm
CMS IDvàVideo IDcho luồng VOD. Để kiểm thử, hãy sử dụng các thông số luồng phát sau:- Mã CMS:
"2548831" - Mã video:
"tears-of-steel"
- Mã CMS:
Tạo URI VOD SSAI bằng phương thức
ImaServerSideAdInsertionUriBuilder():/** * Builds an IMA SSAI VOD stream URI for the given CMS ID, video ID, and format. * * @param cmsId The CMS ID of the VOD stream. * @param videoId The video ID of the VOD stream. * @param format The format of the VOD stream request, either {@code CONTENT_TYPE_HLS} or {@code * CONTENT_TYPE_DASH}. * @return The URI of the VOD stream. */ public Uri buildVodStreamUri(String cmsId, String videoId, int format) { Map<String, String> adTagParams = new HashMap<String, String>(); // Update the adTagParams map with any parameters. // For more information, see https://support.google.com/admanager/answer/7320899 return new ImaServerSideAdInsertionUriBuilder() .setContentSourceId(cmsId) .setVideoId(videoId) .setFormat(format) .setAdTagParameters(adTagParams) .build(); }Đặt URI của luồng VOD mới làm mục nội dung nghe nhìn của trình phát bằng phương thức
MediaItem.fromUri().
Nếu thành công, bạn có thể yêu cầu và phát một luồng nội dung nghe nhìn bằng tiện ích ExoPlayer IMA. Để xem ví dụ đầy đủ, hãy xem các mẫu DAI trên Android trên GitHub.
