동영상 광고
동영상 광고(InStream Video Ad)는 동영상 컨텐츠 재생 전, 재생 중 또는 재생 후에 삽입되는 광고형태입니다.
본 페이지는 전/중/후 광고 호출을 위한 비디오 스케줄 매니저 GfpVideoAdScheduleManager (이하 VSM)
사용 가이드입니다.
동영상 광고가 재생될 Player 는 서비스가 사용하는 Player 를 주입받는 형태입니다.
플레이어 설정을 참고해 주시기 바랍니다.
[Step 1] Dependency 추가
- Kotlin DSL
- Groovy
dependencies {
implementation(platform("com.naver.gfpsdk:nam-bom:8.3.1"))
implementation("com.naver.gfpsdk:nam-core")
implementation("com.naver.gfpsdk:nam-ndavideo") // Naver InStream ads extension
}
dependencies {
implementation platform('com.naver.gfpsdk:nam-bom:8.3.1')
implementation 'com.naver.gfpsdk:nam-core'
implementation 'com.naver.gfpsdk:nam-ndavideo' // Naver InStream ads extension
}
[Step 2] Player 레이아웃이 포함될 수 있는 ViewGroup 추가
비디오 광고를 게재하기 위해서는 먼저 광고를 게재하려는 Activity
또는 Fragment
의 레이아웃에
비디오 광고와 본영상이 재생될 수 있는 영역에 대한 ViewGroup
을 추가해야 합니다.
아래 예제에서는 RelativeLayout
ViewGroup 에 video_ad_container
라는 id 로 비디오 광고가 게재될 Layout 을 선언했습니다.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/video_ad_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#000000"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
[Step 3] Player 와 광고 UI 가 포함될 레이아웃 생성
비디오 광고가 재생되는데 필요한 Player(AdVideoPlayer 에 대한 구현이 되어있어야 함) 와 광고 UI 가 포함될 레이아웃을 선언합니다.
아래는 player 와 광고 ui 가 포함될 frame layout 을 포함하는 레이아웃에 대한 예시 이며,
생성된 ad_video_player
와 ad_ui_container
는 광고 로더인 GfpVideoAdScheduleManager
의 생성자에서 사용됩니다.
아래에서 생성한 xml 파일의 이름은 video_ad_exoplayer_layout.xml
이라고 가정합니다.
outer_text_ad_container
의 경우 SMR 광고에서 사용되는 리마인드 광고에 사용되는 영역이고 아래와 같이 별도로 설정하게 됩니다.
videoAdScheduleManager.setOuterRemindTextAdViewContainer(outerTextAdContainer);
다만 이번 샘플에서는 사용되지 않습니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.naver.gfpsdk.adssample.video.SampleExoPlayerView
android:id="@+id/ad_video_player"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true" />
<FrameLayout
android:id="@+id/ad_ui_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/outer_text_ad_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
[Step 4] AdParam 과 VideoAdScheduleParam 생성
비디오 광고 요청을 위한 광고 파라미터(AdParam
) 와 스케줄 파라미터(VideoAdScheduleParam
)를 구성합니다.
4-1. AdParam
광고 요청 정보 를 참고하여 광고 요청에 대한 AdParam
를 생성합니다.
다른 광고와는 다르게, Ad Unit ID
는 필요하지 않으며 대신 동영상 관련 파라미터가 필요합니다.
필수(Required)
- vsi: 비디오 스케줄 아이디 (Video ad Schedule Id)
- vri: 비디오 스케줄 요청 아이디 (Video ad schedule Request id)
- vcl: 비디오 켄텐츠 길이 (Video Content Length)
- vsd: 비디오 전/중/후 여부 (Video StartDelay)
- vrr: 비디오 리마인드 광고 요청 여부 (Video ad Request a Remind ad)
선택사항(Optional)
- keywords: IMA 에서 세부적인 타게팅 및 리포팅을 위해서 사용되는 값
4-2 VideoAdScheduleParam
- 컨텐츠 길이(
contentDuration
)
필수 입력값 이며, 초단위로 정확히 입력해야 스케줄이 정상 동작 합니다.
- 스케줄아이디(
adScheduleId
)
필수값이며 NAM 담당자로 부터 사전에 안내 받아야 합니다.
- 스케줄 정책 설정(
setAdSchedulePolicy
)
전/중/후 광고를 선택적으로 제외할 수 있습니다.
부가적인 값으로, 각 스케쥴 아이디마다 NAM 어드민에서 설정한 정책이 있습니다.
어드민에 설정은 했지만 서비스에서 off 를 원할 때 사용됩니다.
- (라이브 컨텐츠의 경우) 컨텐츠 시작 시점(
setContentStartOffset
)
컨텐츠 시작 시점 기준으로 광고 스케줄 오프셋이 조정됩니다.
- Kotlin
- Java
val adParam = AdParam.Builder()
.setRefererPageUrl("https://tv.naver.com/r/")
.setCurrentPageUrl("https://tv.naver.com/v/36037577/list/67096")
.setVrr(1) // SMR 광고에서 Remind Ad를 요청할지 (1 = request, 0 = don't request)
.addCustomParam("lo", "Y") // Loudness Normalization 적용 여부
.addCustomParam("pt", "635") // 콘텐츠 클립 전체 시간 (second 단위)
.addCustomParam("pcmo", "mo") // pc or mo or tv - mo로 고정된 값 사용
.addCustomParam("vid", "0A7CFF5F2F5791DEE667757BD6F9E80411AA") // video ID
.addCustomParam("tid", "3Cb51Nn2ufoyPok6Tpct-A") // 트랜잭션 ID
.addCustomParam("cp", "1403") // 제휴사(창작자) 구분 ID
.addCustomParam("chl", "motline") // 채널 구분 ID
.addCustomParam("cl", "20539479") // 클립 ID
.addCustomParam("svc", "WAVVE_AOS") // 서비스 ID - 고정된 값 (NAM 담당자 통해 확인해 주세요.)
.addCustomParam("cc", "N") // 어린이 보호 콘텐츠 적용 여부
.addCustomParam("AreaId", "clip") // 광고 영역
.build()
/** 이하는 스케줄 정보 수신 이후 SDK 에서 설정합니다.
* 스케줄과 별도로 설정하고자 할 때만 사용해 주세요.
* .setVcl() // 비디오 켄텐츠 길이
* .setVri() // 비디오 스케줄 요청 아이디
* .setVrr() // 리마인드 광고 여부
* .setVsd() // 비디오 전/중/후 여부
* .setVsi() // 비디오 스케줄 아이디
*/
val contentDuration = 653L // 초 단위의 컨텐츠 영상 길이
val adScheduleId = "WAVVE_SCH" // Ad Unit ID 처럼 NAM 담당자에게 안내 받아야 함
val pre = true
val mid = false // 영상 중간에 광고 없음 선택
val post = true
val videoAdScheduleParam = VideoAdScheduleParam.Builder(adScheduleId)
.setDuration(contentDuration)
.setAdSchedulePolicy(pre, mid, post)
.setAdNoticeDurationSec(5) // mid 광고 시작 전 안내 문구 표시 시간
.build()
AdParam adParam = new AdParam.Builder()
.setRefererPageUrl("https://tv.naver.com/r/")
.setCurrentPageUrl("https://tv.naver.com/v/36037577/list/67096")
.setVrr(1) // SMR 광고에서 Remind Ad를 요청할지 (1 = request, 0 = don't request)
.addCustomParam("lo", "Y") // Loudness Normalazation 적용 여부
.addCustomParam("pt", "635") // 콘텐츠 클립 전체 시간 (second 단위)
.addCustomParam("pcmo", "mo") // pc or mo or tv - mo로 고정된 값 사용
.addCustomParam("vid", "0A7CFF5F2F5791DEE667757BD6F9E80411AA") // video ID
.addCustomParam("tid", "3Cb51Nn2ufoyPok6Tpct-A") // 트랜잭션 ID
.addCustomParam("cp", "1403") // 제휴사(창작자) 구분 ID
.addCustomParam("chl", "motline") // 채널 구분 ID
.addCustomParam("cl", "20539479") // 클립 ID
.addCustomParam("svc", "WAVVE_AOS") // 서비스 ID - 고정된 값 (NAM 담당자 통해 확인해 주세요.)
.addCustomParam("cc", "N") // 어린이 보호 콘텐츠 적용 여부
.addCustomParam("AreaId", "clip") // 광고 영역
.build();
/** 이하는 스케줄 정보 수신 이후 SDK 에서 설정합니다.
* 스케줄과 별도로 설정하고자 할 때만 사용해 주세요.
* .setVcl() // 비디오 켄텐츠 길이
* .setVri() // 비디오 스케줄 요청 아이디
* .setVrr() // 리마인드 광고 여부
* .setVsd() // 비디오 전/중/후 여부
* .setVsi() // 비디오 스케줄 아이디
*/
long contentDuration = 653L; // 초 단위의 컨텐츠 영상 길이
String adScheduleId = "WAVVE_SCH"; // Ad Unit ID 처럼 NAM 담당자에게 안내 받아야 함
boolean pre = true;
boolean mid = false; //영상 중간에 광고 없음 선택
boolean post = true;
VideoAdScheduleParam videoAdScheduleParam = new VideoAdScheduleParam.Builder(adScheduleId)
.setDuration(contentDuration)
.setAdSchedulePolicy(pre, mid, post)
.setAdNoticeDurationSec(5) // mid 광고 시작 전 안내 문구 표시 시간
.build();
4-3 비디오 광고 옵션 설정
GfpVideoAdScheduleManager
setVideoAdOptions() 을 통해 비디오 광고 옵션을 설정합니다.
GfpVideoAdOptions
에는 bitrateKbps
, videoLoadTimeout(ms)
, hls
지원여부를 설정할 수 있습니다.
-
hls 는 기본 미지원입니다.
( video/mp4만 지원 )
-
bitrateKbps 로 광고의 품질을 결정합니다.
기본값은 -1로 IMA 의 경우 자동 셋팅, 네이버 광고의 경우에는 최저 (hls 미지원 시) 해상도의 광고가 재생됩니다.
-
videoLoadTimeout 은 재생 start 요청 후 해당 시간까지 실제 재생이되지 않으면 에러를 발생시킵니다.
기본값은 5초(5000ms)
- Kotlin
- Java
val videoAdOptions = GfpVideoAdOptions().apply {
supportedStreamingHLS = false
bitrateKbps = -1
videoLoadTimeout = 5000
}
videoAdManager.setVideoAdOptions(videoAdOptions)
GfpVideoAdOptions videoAdOptions = new GfpVideoAdOptions();
videoAdOptions.setSupportedStreamingHLS(false);
videoAdOptions.setBitrateKbps(-1);
videoAdOptions.setVideoLoadTimeout(5000);
videoAdManager.setVideoAdOptions(videoAdOptions);
[Step 5] GfpVideoAdScheduleManager 생성
동영상 광고 호출을 위한 GfpVideoAdScheduleManager
를 생성합니다.
위에서 설정한 광고 파라미터(AdParam
) 와 스케줄 파라미터(VideoAdScheduleParam
)를 GfpVideoAdScheduleManager
생성자에 함께 전달합니다.
추가로 위에서 생성한 layout 을 inflate 하여서 player 레이아웃을 포함시키기 위해서 만들어 놓은 video_ad_container
에 add 합니다.
예시는 아래 광고 로드를 참고해 주세요.
[Step 6] 스케줄 이벤트 수신
동영상 광고 스케줄 이벤트는 VideoAdScheduleListener
interface 를 통해서 수신할 수 있습니다.
각 비디오 광고 스케쥴 한건마다 이벤트를 처리하므로, 광고 시작/종료시 본 컨텐츠의 시작/종료를 해당 리스너를 통해 처리해야 합니다.
광고가 로드되면 본 영상은 멈추고, 광고 영상 에러 처리시 본 영상이 재생 되도록 처리해 주셔야 합니다.
- Kotlin
- Java
videoAdScheduleManager.setAdScheduleListener(object: VideoAdScheduleListener {
override fun onScheduleLoaded(schedule: VideoScheduleResponse) {
// 광고 스케줄이 로드 완료 되었을 때 실행됩니다.
}
override fun onContentResumeRequest() {
// 컨텐츠를 재시작 할 때 실행됩니다.
}
override fun onContentPauseRequest() {
// 컨텐츠를 일시정지 할 때 실행됩니다.
}
override fun onScheduleCompleted() {
// 모든 광고의 재생이 완료되었을 때 실행됩니다.
}
override fun onError(error: GfpError) {
// 광고 요청이 실패했을 때 실행됩니다.
}
})
videoAdScheduleManager.setAdScheduleListener(new VideoAdScheduleListener() {
@Override
public void onScheduleLoaded(VideoScheduleResponse schedule) {
// 광고 스케줄이 로드 완료 되었을 때 실행됩니다.
}
@Override
public void onContentResumeRequest() {
// 컨텐츠를 재시작 할 때 실행됩니다.
}
@Override
public void onContentPauseRequest() {
// 컨텐츠를 일시정지 할 때 실행됩니다.
}
@Override
public void onScheduleCompleted() {
// 모든 광고의 재생이 완료되었을 때 실행됩니다.
}
@Override
public void onError(GfpError error) {
// 광고 요청이 실패했을 때 실행됩니다.
}
});
[Step 7] 광고 이벤트 수신
동영상 광고의 생명주기(로드, 재생 준비, 재생 시작, 비선형 광고 준비, 클릭, 재생 완료, 에러) 에 대한 이벤트는 VideoAdListener
interface 를 통해서 수신할 수 있습니다.
- Kotlin
- Java
videoAdScheduleManager.setAdListener(object: VideoAdListener {
override fun onAdLoaded(ad: GfpVideoAd) {
// 광고 load 가 성공했을 때 실행됩니다.
}
override fun onAdStartReady(ad: GfpVideoAd) {
// 광고 재생이 필요한 시점에 도달했을 때 실행됩니다.
}
override fun onAdStarted(ad: GfpVideoAd) {
// 광고 재생이 시작했을 때 실행됩니다.
}
override fun onAdNonLinearStartReady(ad: GfpVideoAd) {
// 비선형 광고 노출 시점에 도달했을 때 실행됩니다.
}
override fun onAdClicked(ad: GfpVideoAd) {
// 광고 click 이 발생했을 때 실행됩니다.
}
override fun onAdCompleted(ad: GfpVideoAd) {
// 광고 재생이 완료됐을 때 실행됩니다.
}
override fun onError(ad: GfpVideoAd, error: GfpError) {
// 광고 요청이 실패했을 때 실행됩니다.
}
})
videoAdScheduleManager.setAdListener(new VideoAdListener() {
@Override
public void onAdLoaded(GfpVideoAd ad) {
// 광고 load 가 성공했을 때 실행됩니다.
}
@Override
public void onAdStartReady(GfpVideoAd ad) {
// 광고 재생이 필요한 시점에 도달했을 때 실행됩니다.
}
@Override
public void onAdStarted(GfpVideoAd ad) {
// 광고 재생이 시작했을 때 실행됩니다.
}
@Override
public void onAdNonLinearStartReady(GfpVideoAd ad) {
// 비선형 광고 노출 시점에 도달했을 때 실행됩니다.
}
@Override
public void onAdClicked(GfpVideoAd ad) {
// 광고 click 이 발생했을 때 실행됩니다.
}
@Override
public void onAdCompleted(GfpVideoAd ad) {
// 광고 재생이 완료됐을 때 실행됩니다.
}
@Override
public void onError(GfpVideoAd ad, GfpError error) {
// 광고 요청이 실패했을 때 실행됩니다.
}
});
7-1. QOE(Quality of Experience) 정보
동영상 광고 재생과 관련한 더 상세한 이벤트를 얻기위해 GfpVideoAdScheduleManager
의 setQoeListener
를 통해 이벤트 정보를 받을 수 있습니다.
- Kotlin
- Java
videoAdManager.setQoeListener(object: GfpVideoAdQoeListener {
override fun onAdLoaded(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", String.format("GfpVideoAdQoeListener.onAdLoaded \tinfo:\n\t\tplacement: %s\n\t\tprovider: %s \n\t\tmedia_h: %d\n\t\tmedia_w: %d \n\t\tcurrent time: %f\n\t\tduration: %f\n\t\toffset: %f",
info.placementType,
info.provider,
info.mediaHeight,
info.mediaWidth,
info.currentTime,
info.duration,
info.skipOffset
))
}
override fun onAdStarted(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdStarted")
}
override fun onAdPaused(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdPaused")
}
override fun onAdSkipped(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdSkipped")
}
override fun onAdResumed(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdResumed")
}
override fun onAdClicked(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdClicked")
}
override fun onAdCompleted(info: GfpVideoAdQoeInfo) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdCompleted")
}
override fun onError(error: GfpError) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onError")
}
})
videoAdManager.setQoeListener(new GfpVideoAdQoeListener() {
@Override
public void onAdLoaded(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", String.format("GfpVideoAdQoeListener.onAdLoaded \tinfo:\n\t\tplacement: %s\n\t\tprovider: %s \n\t\tmedia_h: %d\n\t\tmedia_w: %d \n\t\tcurrent time: %f\n\t\tduration: %f\n\t\toffset: %f",
info.getPlacementType(),
info.getProvider(),
info.getMediaHeight(),
info.getMediaWidth(),
info.getCurrentTime(),
info.getDuration(),
info.getSkipOffset()
));
}
@Override
public void onAdStarted(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdStarted");
}
@Override
public void onAdPaused(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdPaused");
}
@Override
public void onAdSkipped(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdSkipped");
}
@Override
public void onAdResumed(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdResumed");
}
@Override
public void onAdClicked(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdClicked");
}
@Override
public void onAdCompleted(GfpVideoAdQoeInfo info) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onAdCompleted");
}
@Override
public void onError(GfpError error) {
Log.d("MainActivity", "GfpVideoAdQoeListener.onError");
}
});
[Step 8] 타임아웃 설정
GfpVideoAdScheduleManager 를 통해 광고 요청마다 타임아웃을 설정할 수 있습니다.
GfpVideoAdScheduleManager 객체를 통해 별도의 타임아웃을 설정하지 않을 경우,
기본값은 SdkProperties
를 통해 전역 설정된 값(기본값 : 60초)을 사용합니다.
- Kotlin
- Java
videoAdScheduleManager.setGfpVideoProperties(GfpVideoProperties(60_000L, null))
videoAdScheduleManager.setGfpVideoProperties(new GfpVideoProperties(60_000L, null));
[Step 9] 광고 로드 (샘플)
GfpVideoAdScheduleManager 에 대한 설정이 마무리 되었다면 광고를 로드할 수 있습니다.
다음은 Activity 의 onCreate() method 에서 광고를 로드하는 방법을 보여주는 예시입니다.
- Kotlin
- Java
package ...
import ...
class MainActivity : AppCompatActivity() {
private lateinit var playerContainer: RelativeLayout
private lateinit var adVideoPlayer: AdVideoPlayer
private lateinit var videoAdScheduleManager: GfpVideoAdScheduleManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playerContainer = findViewById(R.id.video_ad_container)
// VSM 을 사용하는 경우, setAdUnitId 설정이 불필요하며 설정 시 무시됩니다.
val adParam = AdParam.Builder().build()
// 위에서 선언한 video_ad_exoplayer_layout inflate.
val playerLayout = layoutInflater.inflate(R.layout.video_ad_exoplayer_layout, null, false)
// 본영상과 광고영상 재생을 위한 Sample player 를 가정.
val exoPlayerView = playerLayout.findViewById<SampleExoPlayerView>(R.id.ad_video_player)
val adUiContainer = playerLayout.findViewById<FrameLayout>(R.id.ad_ui_container)
// SampleExoPlayerView 에서 AdVideoPlayer 를 포함하고 있는 형태로 구현했다고 가정.
adVideoPlayer = exoPlayerView.createAdVideoPlayer("YOUR_CONTENTS_URL")
// Schedule Param 설정
val contentDuration: Long = ***L // 컨텐츠 본영상의 길이를 '초' 단위로 정확히 입력해야 스케줄이 정상 동작 합니다.
val adScheduleId = "VIDEO_AD_SCHEDULE_ID" // 스케줄아이디는 광고 기획 담당자로 부터 사전에 안내 받아야 합니다.
val videoAdScheduleParam = VideoAdScheduleParam.Builder(adScheduleId)
.setDuration(contentDuration)
.setAdSchedulePolicy(true, false, true)
.setAdNoticeDurationSec(5)
.build()
// manager 생성
videoAdScheduleManager = GfpVideoAdScheduleManager(
this,
videoAdScheduleParam,
adParam,
adVideoPlayer,
adUiContainer
)
// 비디오 옵션 설정
val videoAdOptions = GfpVideoAdOptions()
videoAdOptions.setSupportedStreamingHLS(true)
videoAdScheduleManager.setVideoAdOptions(videoAdOptions)
/**
* 필요시 QOE 리스너 설정
videoAdScheduleManager.setQoeListener(object: GfpVideoAdQoeListener {
override fun onAdLoaded(info: GfpVideoAdQoeInfo) {
...
}
...
})
*/
// Naver 서비스이면서 공유 기능을 사용 한다면...
// videoAdScheduleManager.setAdvertiseParams(naver_share_uri_param_json_string);
// Naver 서비스이면서 SMR 광고를 서빙한다면, remind text 관련 설정 필요
// videoAdScheduleManager.setOuterRemindTextAdViewContainer(outerTextAdContainer);
// 스케쥴 리스너 설정
videoAdScheduleManager.setAdScheduleListener(object: VideoAdScheduleListener {
override fun onScheduleLoaded(schedule: VideoScheduleResponse) {
Log.d("MainActivity", String.format("onScheduleLoaded - AdBreak size: %d", schedule.adBreaks.size))
}
override fun onContentResumeRequest() {
Log.d("MainActivity", "컨텐츠 재생")
// 본 영상 재생
if (exoPlayerView.isPlaying.not()) {
exoPlayerView.resumeContentsRequest()
}
}
override fun onContentPauseRequest() {
Log.d("MainActivity", "컨텐츠 일시정지")
exoPlayerView.pauseContentsRequest()
}
override fun onScheduleCompleted() {
Log.d("MainActivity", "스케줄 내 모든 광고 완료")
// 본 영상 재생
if (exoPlayerView.isPlaying.not()) {
exoPlayerView.resumeContentsRequest()
}
}
override fun onError(gfpError: GfpError) {
Log.d("MainActivity", "스케줄 광고 요청 에러 Error: $gfpError")
// 본 영상 재생
if (exoPlayerView.isPlaying.not()) {
exoPlayerView.resumeContentsRequest()
}
}
})
// 광고 응답 정보 리스너 설정
videoAdScheduleManager.setAdListener(object: VideoAdListener {
override fun onAdLoaded(ad: GfpVideoAd) {
// NonLinearAdInfo nonLinearAdInfo = ad.getNonLinearAdInfo();
// remind 배너 정보 확인 가능
Log.d("MainActivity", "onAdLoaded()\tResponseInfo: ${ad.responseInfo}")
}
override fun onAdStartReady(ad: GfpVideoAd) {
ad.start(true)
Log.d("MainActivity", "광고 재생 준비 완료")
}
override fun onAdNonLinearStartReady(ad: GfpVideoAd) {
Log.d("MainActivity", "Non Linear 광고 재생 준비 완료")
// NonLinear 광고 사용 시 구현 및 확인은 SDK 담당과 논의해 주세요.
ad.showNonLinearAd(GfpNonLinearAdView.ContainerType.INNER)
}
override fun onAdStarted(ad: GfpVideoAd) {
Log.d("MainActivity", "광고 재생")
}
override fun onAdClicked(ad: GfpVideoAd) {
Log.d("MainActivity", "클릭 발생")
}
override fun onAdCompleted(ad: GfpVideoAd) {
Log.d("MainActivity", "광고 재생 완료")
// 본 영상 재생
if (exoPlayerView.isPlaying.not()) {
exoPlayerView.resumeContentsRequest()
}
}
override fun onError(ad: GfpVideoAd, error: GfpError) {
Log.e("MainActivity", "에러 발생\t" +
String.format(
"code[%d] subCode[%s] message[%s] responseInfo[%s]",
error.errorCode,
error.errorSubCode,
error.errorMessage,
ad.responseInfo.toString()
)
)
// 본 영상 재생
if (!exoPlayerView.isPlaying) {
exoPlayerView.resumeContentsRequest()
}
}
})
playerContainer.addView(playerLayout)
videoAdScheduleManager.load()
}
override fun onPause() {
super.onPause()
if (::videoAdScheduleManager.isInitialized) {
videoAdScheduleManager.pause()
}
}
override fun onResume() {
super.onResume()
if (::videoAdScheduleManager.isInitialized) {
videoAdScheduleManager.resume()
}
}
override fun onDestroy() {
super.onDestroy()
if (::videoAdScheduleManager.isInitialized) {
videoAdScheduleManager.destroy()
}
}
}
package ...
import ...
public class MainActivity extends AppCompatActivity {
private RelativeLayout playerContainer;
private AdVideoPlayer adVideoPlayer;
private GfpVideoAdScheduleManager videoAdScheduleManager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playerContainer = findViewById(R.id.video_ad_container);
// VSM 을 사용하는 경우, setAdUnitId 설정이 불필요하며 설정 시 무시됩니다.
AdParam adParam = new AdParam.Builder().build();
// 위에서 선언한 video_ad_exoplayer_layout inflate.
View playerLayout = getLayoutInflater().inflate(R.layout.video_ad_exoplayer_layout, null, false);
// 본영상과 광고영상 재생을 위한 Sample player 를 가정.
SampleExoPlayerView exoPlayerView = playerLayout.findViewById(R.id.ad_video_player);
FrameLayout adUiContainer = playerLayout.findViewById(R.id.ad_ui_container);
// SampleExoPlayerView 에서 AdVideoPlayer 를 포함하고 있는 형태로 구현했다고 가정.
adVideoPlayer = exoPlayerView.createAdVideoPlayer("YOUR_CONTENTS_URL");
// Schedule Param 설정
long contentDuration = ***L; // 컨텐츠 본영상의 길이를 '초' 단위로 정확히 입력해야 스케줄이 정상 동작 합니다.
String adScheduleId = "VIDEO_AD_SCHEDULE_ID"; // 스케줄아이디는 광고 기획 담당자로 부터 사전에 안내 받아야 합니다.
VideoAdScheduleParam videoAdScheduleParam = new VideoAdScheduleParam.Builder(adScheduleId)
.setDuration(contentDuration)
.setAdSchedulePolicy(true, false, true)
.setAdNoticeDurationSec(5)
.build();
// manager 생성
videoAdScheduleManager = new GfpVideoAdScheduleManager(
this,
videoAdScheduleParam,
adParam,
adVideoPlayer,
adUiContainer
);
// 비디오 옵션 설정
GfpVideoAdOptions videoAdOptions = new GfpVideoAdOptions();
videoAdOptions.setSupportedStreamingHLS(true);
videoAdScheduleManager.setVideoAdOptions(videoAdOptions);
/**
* 필요시 QOE 리스너 설정
videoAdScheduleManager.setQoeListener(new GfpVideoAdQoeListener() {
@Override
public void onAdLoaded(GfpVideoAdQoeInfo info) {
...
}
...
});
*/
// Naver 서비스이면서 공유 기능을 사용 한다면...
// videoAdScheduleManager.setAdvertiseParams(naver_share_uri_param_json_string);
// Naver 서비스이면서 SMR 광고를 서빙한다면, remind text 관련 설정 필요
// videoAdScheduleManager.setOuterRemindTextAdViewContainer(outerTextAdContainer);
// 스케쥴 리스너 설정
videoAdScheduleManager.setAdScheduleListener(new VideoAdScheduleListener() {
@Override
public void onScheduleLoaded(VideoScheduleResponse schedule) {
Log.d("MainActivity", String.format("onScheduleLoaded - AdBreak size: %d", schedule.getAdBreaks().size()));
}
@Override
public void onContentResumeRequest() {
Log.d("MainActivity", "컨텐츠 재생");
// 본 영상 재생
if (!exoPlayerView.isPlaying()) {
exoPlayerView.resumeContentsRequest();
}
}
@Override
public void onContentPauseRequest() {
Log.d("MainActivity", "컨텐츠 일시정지");
exoPlayerView.pauseContentsRequest();
}
@Override
public void onScheduleCompleted() {
Log.d("MainActivity", "스케줄 내 모든 광고 완료");
// 본 영상 재생
if (!exoPlayerView.isPlaying()) {
exoPlayerView.resumeContentsRequest();
}
}
@Override
public void onError(GfpError gfpError) {
Log.d("MainActivity", "스케줄 광고 요청 에러 Error: " + gfpError.toString());
// 본 영상 재생
if (!exoPlayerView.isPlaying()) {
exoPlayerView.resumeContentsRequest();
}
}
});
// 광고 응답 정보 리스너 설정
videoAdScheduleManager.setAdListener(new VideoAdListener() {
@Override
public void onAdLoaded(GfpVideoAd ad) {
// NonLinearAdInfo nonLinearAdInfo = ad.getNonLinearAdInfo();
// remind 배너 정보 확인 가능
Log.d("MainActivity", "onAdLoaded()\tResponseInfo: " + ad.getResponseInfo().toString());
}
@Override
public void onAdStartReady(GfpVideoAd ad) {
ad.start(true);
Log.d("MainActivity", "광고 재생 준비 완료");
}
@Override
public void onAdNonLinearStartReady(GfpVideoAd ad) {
Log.d("MainActivity", "Non Linear 광고 재생 준비 완료");
// NonLinear 광고 사용 시 구현 및 확인은 SDK 담당과 논의해 주세요.
ad.showNonLinearAd(GfpNonLinearAdView.ContainerType.INNER);
}
@Override
public void onAdStarted(GfpVideoAd ad) {
Log.d("MainActivity", "광고 재생");
}
@Override
public void onAdClicked(GfpVideoAd ad) {
Log.d("MainActivity", "클릭 발생");
}
@Override
public void onAdCompleted(GfpVideoAd ad) {
Log.d("MainActivity", "광고 재생 완료");
// 본 영상 재생
if (!exoPlayerView.isPlaying()) {
exoPlayerView.resumeContentsRequest();
}
}
@Override
public void onError(GfpVideoAd ad, GfpError error) {
Log.e("MainActivity", "에러 발생\t" + String.format(
"code[%d] subCode[%s] message[%s] responseInfo[%s]",
error.getErrorCode(),
error.getErrorSubCode(),
error.getErrorMessage(),
ad.getResponseInfo().toString()
));
// 본 영상 재생
if (!exoPlayerView.isPlaying()) {
exoPlayerView.resumeContentsRequest();
}
}
});
playerContainer.addView(playerLayout);
videoAdScheduleManager.load();
}
@Override
public void onPause() {
super.onPause();
if (videoAdScheduleManager != null) {
videoAdScheduleManager.pause();
}
}
@Override
public void onResume() {
super.onResume();
if (videoAdScheduleManager != null) {
videoAdScheduleManager.resume();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (videoAdScheduleManager != null) {
videoAdScheduleManager.destroy();
}
}
}
[Step 10] 광고 삭제
스케줄에 등록된 모든 광고가 종료되었거나 광고 화면을 벗어나는 경우 광고가 올바르게 폐기되도록 스케줄 매니저를 제거해 주어야 합니다.
스케줄 매니저 제거는 아래와 같이 GfpVideoAdScheduleManager
가 제공하는 destory()
를 호출하면 됩니다.
- Kotlin
- Java
if (::videoAdScheduleManager.isInitialized) {
videoAdScheduleManager.destroy()
}
if (videoAdScheduleManager != null) {
videoAdScheduleManager.destroy();
}