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 스튜디오
- DAI 지원을 위한 AndroidX Media3 ExoPlayer 버전 1.0.0 이상
새 Android 스튜디오 프로젝트 만들기
Android 스튜디오 프로젝트를 만들려면 다음 단계를 따르세요.
- Android 스튜디오를 시작합니다.
- Start a new Android Studio project를 선택합니다.
- Choose your project 페이지에서 No Activity 템플릿을 선택합니다.
- 다음을 클릭합니다.
- 프로젝트 구성 페이지에서 프로젝트 이름을 지정하고 언어로 Java를 선택합니다. 참고: IMA DAI SDK는 Kotlin과 호환되지만 이 가이드에서는 Java 예시를 사용합니다.
- 마침을 클릭합니다.
프로젝트에 ExoPlayer IMA 확장 프로그램 추가
ExoPlayer IMA 확장 프로그램을 추가하려면 다음 단계를 따르세요.
앱의
build.gradle파일의dependencies섹션에 다음 가져오기를 포함합니다.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" }IMA DAI SDK가 광고를 요청하는 데 필요한 사용자 권한을 추가합니다.
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
ExoPlayer UI 설정
ExoPlayer UI를 설정하려면 다음 단계를 따르세요.
ExoPlayer의
PlayerView객체를 만듭니다.ExoPlayer IMA 확장 프로그램에서 권장하는 대로
androidx.constraintlayout.widget.ConstraintLayout뷰를LinearLayout뷰로 변경합니다.<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>
스트림 매개변수 추가
프로젝트를 테스트할 샘플 스트림 애셋은 IMA 샘플 스트림 페이지를 참고하세요. 자체 스트림을 설정하려면 DAI의 Ad Manager 섹션을 참고하세요.
이 단계에서는 라이브 스트림을 설정합니다. ExoPlayer IMA 확장 프로그램은 DAI VOD 스트림도 지원합니다. VOD 스트림에 필요한 앱 변경사항을 알아보려면 주문형 비디오 (VOD) 스트림 단계를 참고하세요.
ExoPlayer IMA 확장 프로그램 가져오기
ExoPlayer 확장 프로그램에 다음 import 문을 추가합니다.
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;MyActivity.java에서 다음 비공개 변수를 추가합니다.PlayerViewExoPlayerImaServerSideAdInsertionMediaSource.AdsLoaderImaServerSideAdInsertionMediaSource.AdsLoader.State
Big Buck Bunny (라이브) HLS 스트림으로 테스트하려면 애셋 키를 추가하세요. IMA 샘플 스트림 페이지에서 테스트할 스트림을 더 많이 찾을 수 있습니다.
AdsLoader상태를 저장하고 검색하는KEY_ADS_LOADER_STATE상수를 만듭니다./** 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;
adsLoader 인스턴스 만들기
onCreate 메서드를 재정의합니다. 여기에서 PlayerView를 찾아 저장된 AdsLoader.State이 있는지 확인합니다.
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;
}
플레이어를 초기화하는 메서드 추가
플레이어를 초기화하는 메서드를 추가합니다. 이 메서드는 다음을 실행해야 합니다.
AdsLoader인스턴스를 만듭니다.ExoPlayer을 만듭니다.- 라이브 스트림의 애셋 키를 사용하여
MediaItem를 만듭니다. - 플레이어의
MediaItem를 설정합니다.
// 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();
}
플레이어를 해제하는 메서드 추가
플레이어를 해제하는 메서드 추가 이 메서드는 다음 작업을 순서대로 실행해야 합니다.
- 플레이어 참조를 null로 설정하고 플레이어의 리소스를 해제합니다.
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();
}
플레이어 이벤트 처리
플레이어 이벤트를 처리하려면 스트림 재생을 관리하는 활동의 수명 주기 이벤트에 대한 콜백을 만드세요.
Android API 수준 24 이상의 경우 다음 메서드를 사용하세요.
Android API 수준이 24보다 이전인 경우 다음 메서드를 사용하세요.
onStart() 및 onResume() 메서드는 playerView.onResume()에 매핑되고 onStop() 및 onPause()은 playerView.onPause()에 매핑됩니다.
이 단계에서는 onSaveInstanceState() 이벤트를 사용하여 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());
}
}
VOD 스트림 설정 (선택사항)
앱에서 광고가 포함된 VOD 콘텐츠를 재생해야 하는 경우 다음 단계를 따르세요.
- VOD 스트림에
CMS ID및Video ID추가 테스트에는 다음 스트림 매개변수를 사용하세요.- CMS ID:
"2548831" - 동영상 ID:
"tears-of-steel"
- CMS ID:
ImaServerSideAdInsertionUriBuilder()메서드를 사용하여 SSAI VOD URI를 만듭니다./** * 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(); }MediaItem.fromUri()메서드를 사용하여 새 VOD 스트림 URI를 플레이어의 미디어 항목으로 설정합니다.
성공하면 ExoPlayer IMA 확장 프로그램으로 미디어 스트림을 요청하고 재생할 수 있습니다. 전체 예는 GitHub의 Android DAI 샘플을 참고하세요.
