IMA SDK를 사용하면 멀티미디어 광고를 웹사이트와 앱에 쉽게 통합할 수 있습니다. IMA SDK는 원하는 형식에서 광고를 <ph type="x-smartling-placeholder"></ph> VAST 호환 광고 서버를 사용하고 앱에서 광고 재생을 관리할 수 있습니다. IMA DAI SDK를 사용하면 앱에서 광고 및 콘텐츠 동영상(VOD 또는 라이브 콘텐츠)에 대한 스트림 요청 그러면 SDK는 광고와 콘텐츠 동영상 간의 전환을 관리할 필요가 없음 표시할 수 있습니다.
관심 있는 DAI 솔루션 선택
전체 서비스 DAI
이 가이드에서는 IMA DAI SDK를 간단한 동영상 플레이어에 통합하는 방법을 보여줍니다. 있습니다. 완성된 샘플을 보거나 함께 보고 싶다면 BasicExample을 다운로드하세요. GitHub를 참고하세요.
IMA DAI 개요
IMA DAI를 구현하려면 가이드:
StreamDisplayContainer
: 동영상 재생 요소 위에 배치되고 광고 UI 요소를 포함하는 컨테이너 객체입니다.AdsLoader
: 스트림을 요청하고 스트림 요청 응답 객체에 의해 트리거된 이벤트를 처리하는 객체입니다. 하나의 광고 로더만 인스턴스화해야 하며, 이는 애플리케이션입니다.StreamRequest
: 스트림 요청을 정의하는 객체입니다. 스트림 요청은 VOD 또는 라이브일 수 있습니다. 있습니다. 요청은 콘텐츠 ID는 물론 API 키 또는 인증 토큰 및 기타 매개변수입니다.StreamManager
: 동적 광고 삽입 스트림 및 DAI 백엔드와의 상호작용을 처리하는 객체입니다. 이 스트림 관리자는 핑 추적을 처리하고 스트림 및 광고 이벤트를 있습니다.
기본 요건
- Android 스튜디오
- SDK 통합을 위한 샘플 동영상 플레이어 앱
샘플 동영상 플레이어 앱 다운로드 및 실행
샘플 앱은 HLS 동영상을 재생하는 작동하는 동영상 플레이어를 제공합니다. 다음 용도로 사용 이는 IMA DAI SDK의 DAI 기능을 통합하기 위한 시작점입니다.
샘플 동영상 플레이어를 앱 및 추출해 보겠습니다.
Android 스튜디오를 시작하고 Open an existing Android Studio project를 선택합니다. Android 스튜디오가 이미 실행 중인 경우에는 File > 신규 > 가져오기 Project(프로젝트)를 참조하세요. 그런 다음
SampleVideoPlayer/build.gradle
를 선택합니다.Tools > Android > Gradle 파일로 프로젝트 동기화
플레이어 앱이 실제 Android 기기에서 컴파일되고 실행되는지 확인합니다. Android Virtual Device에서 Run > 'app'을 실행합니다. 동영상이 정상적으로 작동함 잠시 기다려야 합니다.
샘플 동영상 플레이어 검사
샘플 동영상 플레이어에는 아직 IMA DAI SDK 통합 코드가 포함되어 있지 않습니다. 샘플 앱은 두 가지 주요 부분으로 구성됩니다.
samplevideoplayer/SampleVideoPlayer.java
: 다음과 같은 역할을 하는 ExoPlayer 기반 HLS 플레이어 IMA DAI 통합의 기초가 됩니다.videoplayerapp/MyActivity.java
: 이 활동은 동영상 플레이어를 만들고Context
및SimpleExoPlayerView
를 전달합니다.
플레이어 앱에 IMA DAI SDK 추가
IMA DAI SDK에 대한 참조도 포함해야 합니다. Android 스튜디오에서
다음을 애플리케이션 수준 build.gradle
파일에 추가합니다.
app/build.gradle
:
repositories {
google()
mavenCentral()
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.media3:media3-exoplayer:1.3.1'
implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.35.0'
}
IMA DAI SDK 통합
videoplayerapp
패키지에SampleAdsWrapper
라는 새 클래스를 만듭니다. (app/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/
후) ~ 기존SampleVideoPlayer
를 래핑하고 IMA DAI를 구현하는 로직을 추가합니다. 받는사람 이렇게 하려면 먼저 광고를 요청하는 데 사용되는AdsLoader
를 만들어야 합니다. 광고를 요청할 수 있습니다.videoplayerapp/SampleAdsWrapper.java
package com.google.ads.interactivemedia.v3.samples.videoplayerapp; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.view.ViewGroup; import android.webkit.WebView; import com.google.ads.interactivemedia.v3.api.AdErrorEvent; import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.AdsLoader; import com.google.ads.interactivemedia.v3.api.AdsManagerLoadedEvent; import com.google.ads.interactivemedia.v3.api.CuePoint; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; import com.google.ads.interactivemedia.v3.api.StreamDisplayContainer; import com.google.ads.interactivemedia.v3.api.StreamManager; import com.google.ads.interactivemedia.v3.api.StreamRequest; import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import com.google.ads.interactivemedia.v3.api.player.VideoStreamPlayer; import com.google.ads.interactivemedia.v3.samples.samplevideoplayer.SampleVideoPlayer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class SampleAdsWrapper implements AdEvent.AdEventListener, AdErrorEvent.AdErrorListener, AdsLoader.AdsLoadedListener { // Livestream asset key. private static final String TEST_ASSET_KEY = "sN_IYUG8STe1ZzhIIE_ksA"; // VOD content source and video IDs. private static final String TEST_CONTENT_SOURCE_ID = "2548831"; private static final String TEST_VIDEO_ID = "tears-of-steel"; private static final String PLAYER_TYPE = "DAISamplePlayer"; /** * Log interface, so you can output the log commands to the UI or similar. */ public interface Logger { void log(String logMessage); } private ImaSdkFactory sdkFactory; private AdsLoader adsLoader; private StreamDisplayContainer displayContainer; private StreamManager streamManager; private List<VideoStreamPlayer.VideoStreamPlayerCallback> playerCallbacks; private SampleVideoPlayer videoPlayer; private Context context; private ViewGroup adUiContainer; private String fallbackUrl; private Logger logger; public SampleAdsWrapper(Context context, SampleVideoPlayer videoPlayer, ViewGroup adUiContainer) { this.videoPlayer = videoPlayer; this.context = context; this.adUiContainer = adUiContainer; sdkFactory = ImaSdkFactory.getInstance(); playerCallbacks = new ArrayList<>(); createAdsLoader(); displayContainer = sdkFactory.createStreamDisplayContainer( this.adUiContainer, videoStreamPlayer ); } private void createAdsLoader() { ImaSdkSettings settings = new ImaSdkSettings(); adsLoader = sdkFactory.createAdsLoader(context); } public void requestAndPlayAds() { adsLoader.addAdErrorListener(this); adsLoader.addAdsLoadedListener(this); adsLoader.requestStream(buildStreamRequest()); } }
buildStreamRequest()
메서드를AdsLoader
에 추가하여 스트리밍하는 방법 광고가 포함된 라이브 스트림 (기본적으로 설정됨) 또는 광고와 함께 사전 녹화된 콘텐츠를 재생하는 VOD 스트림입니다. 받는사람 VOD 스트림을 사용 설정하고 라이브 스트림 요청을 주석 처리하고 VOD 스트림 요청DAI를 사용하려면 플레이어가 라이브 스트림의 ID3 이벤트를 IMA DAI에 전달해야 합니다. 지원합니다 다음 샘플 코드에서는
callback.onUserTextReceived()
메서드를 사용하여 지도 가장자리에 패딩을 추가할 수 있습니다.videoplayerapp/SampleAdsWrapper.java
private StreamRequest buildStreamRequest() { VideoStreamPlayer videoStreamPlayer = createVideoStreamPlayer(); videoPlayer.setSampleVideoPlayerCallback( new SampleVideoPlayer.SampleVideoPlayerCallback() { @Override public void onUserTextReceived(String userText) { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onUserTextReceived(userText); } } @Override public void onSeek(int windowIndex, long positionMs) { // See if you would seek past an ad, and if so, jump back to it. long newSeekPositionMs = positionMs; if (streamManager != null) { CuePoint prevCuePoint = streamManager.getPreviousCuePointForStreamTime(positionMs / 1000); if (prevCuePoint != null && !prevCuePoint.isPlayed()) { newSeekPositionMs = (long) (prevCuePoint.getStartTime() * 1000); } } videoPlayer.seekTo(windowIndex, newSeekPositionMs); } @Override public void onContentComplete() { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onContentComplete(); } } @Override public void onPause() { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onPause(); } } @Override public void onResume() { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onResume(); } } @Override public void onVolumeChanged(int percentage) { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onVolumeChanged(percentage); } } }); // Livestream request. StreamRequest request = sdkFactory.createLiveStreamRequest( TEST_ASSET_KEY, null, displayContainer); // VOD request. Comment the createLiveStreamRequest() line above and uncomment this // createVodStreamRequest() below to switch from a livestream to a VOD stream. // StreamRequest request = sdkFactory.createVodStreamRequest(TEST_CONTENT_SOURCE_ID, // TEST_VIDEO_ID, null, displayContainer); return request; }
스트림을 재생하려면
VideoStreamPlayer
도 필요하므로createVideoStreamPlayer()
메서드 - 다음과 같은 익명 클래스를 만듭니다.VideoStreamPlayer
를 구현합니다.videoplayerapp/SampleAdsWrapper.java
private VideoStreamPlayer createVideoStreamPlayer() { VideoStreamPlayer player = new VideoStreamPlayer() { @Override public void loadUrl(String url, List<HashMap<String, String>> subtitles) { videoPlayer.setStreamUrl(url); videoPlayer.play(); } @Override public void addCallback( VideoStreamPlayerCallback videoStreamPlayerCallback) { playerCallbacks.add(videoStreamPlayerCallback); } @Override public void removeCallback( VideoStreamPlayerCallback videoStreamPlayerCallback) { playerCallbacks.remove(videoStreamPlayerCallback); } @Override public void onAdBreakStarted() { // Disable player controls. videoPlayer.enableControls(false); log("Ad Break Started\n"); } @Override public void onAdBreakEnded() { // Re-enable player controls. videoPlayer.enableControls(true); log("Ad Break Ended\n"); } @Override public VideoProgressUpdate getContentProgress() { return new VideoProgressUpdate(videoPlayer.getCurrentPosition(), videoPlayer.getDuration()); } @Override public int getVolume() { return videoPlayer.getVolume(); } }; return player; }
필수 리스너를 구현하고 오류 처리 지원을 추가합니다.
다음과 같은 경우 대체 URL을 호출하므로
AdErrorListener
구현에 유의하세요. 문제가 있을 수 있습니다. 콘텐츠와 광고가 하나의 스트림에 있으므로 DAI 스트림에 오류가 발생하면 대체 스트림을 호출할 준비가 되어야 합니다.videoplayerapp/SampleAdsWrapper.java
/** AdErrorListener implementation **/ @Override public void onAdError(AdErrorEvent event) { // play fallback URL. videoPlayer.setStreamUrl(fallbackUrl); videoPlayer.enableControls(true); videoPlayer.play(); } /** AdEventListener implementation **/ @Override public void onAdEvent(AdEvent event) { switch (event.getType()) { case AD_PROGRESS: // Do nothing or else log are filled by these messages. break; default: log(String.format("Event: %s\n", event.getType())); break; } } /** AdsLoadedListener implementation **/ @Override public void onAdsManagerLoaded(AdsManagerLoadedEvent event) { streamManager = event.getStreamManager(); streamManager.addAdErrorListener(this); streamManager.addAdEventListener(this); streamManager.init(); } /** Sets fallback URL in case ads stream fails. **/ void setFallbackUrl(String url) { fallbackUrl = url; }
로깅을 위해 코드를 추가합니다.
videoplayerapp/SampleAdsWrapper.java
/** Sets logger for displaying events to screen. Optional. **/ void setLogger(Logger logger) { this.logger = logger; } private void log(String message) { if (logger != null) { logger.log(message); } }
인스턴스화하고 호출하도록
videoplayerapp
의MyActivity
수정SampleAdsWrapper
입니다.videoplayerapp/MyActivity.java
import android.view.ViewGroup; import android.widget.ScrollView; ... public class MyActivity extends AppCompatActivity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); View rootView = findViewById(R.id.videoLayout); videoPlayer = new SampleVideoPlayer(rootView.getContext(), (SimpleExoPlayerView) rootView.findViewById(R.id.playerView)); videoPlayer.enableControls(false); final SampleAdsWrapper sampleAdsWrapper = new SampleAdsWrapper(this, videoPlayer, (ViewGroup) rootView.findViewById(R.id.adUiContainer)); sampleAdsWrapper.setFallbackUrl(DEFAULT_STREAM_URL); final ScrollView scrollView = (ScrollView) findViewById(R.id.logScroll); final TextView textView = (TextView) findViewById(R.id.logText); sampleAdsWrapper.setLogger(new SampleAdsWrapper.Logger() { @Override public void log(String logMessage) { Log.i(APP_LOG_TAG, logMessage); if (textView != null) { textView.append(logMessage); } if (scrollView != null) { scrollView.post(new Runnable() { @Override public void run() { scrollView.fullScroll(View.FOCUS_DOWN); } }); } } }); playButton = (ImageButton) rootView.findViewById(R.id.playButton); // Set up play button listener to play video then hide play button. playButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sampleAdsWrapper.requestAndPlayAds(); playButton.setVisibility(View.GONE); } }); } ... }
UI 요소를 추가하도록 활동의 레이아웃 파일
activity_my.xml
을 수정합니다. 사용할 수 있습니다res/layout/activity_my.xml
... <TextView android:id="@+id/playerDescription" android:text="@string/video_description" android:textAlignment="center" android:gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.1" android:textSize="@dimen/font_size" /> <!-- UI element for viewing SDK event log --> <ScrollView android:id="@+id/logScroll" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.5" android:padding="5dp" android:background="#DDDDDD"> <TextView android:id="@+id/logText" android:layout_width="match_parent" android:layout_height="wrap_content"> </TextView> </ScrollView> ...
축하합니다. 이제 Android에서 동영상 광고를 요청하고 표시합니다. 있습니다. 구현을 세밀하게 조정하려면 다음을 참조하세요. 북마크, 스냅백, 및 API 문서를 참조하세요.
문제 해결
동영상 광고를 재생하는 데 문제가 있는 경우 완료된 BasicExample BasicExample에서 제대로 작동한다면 앱의 IMA 통합 코드를 삽입합니다.
그래도 문제가 해결되지 않으면 IMA SDK 포럼에서 확인할 수 있습니다.