개요
보상형 광고는 사용자가 동영상 광고를 끝까지 시청하면 게임 내 재화, 생명, 힌트 등의 보상을 제공하는 전면 동영상 광고입니다.주요 특징
- 전면 화면을 차지하는 동영상 광고
- 사용자가 광고를 완전히 시청한 경우에만 보상 제공
- 사용자가 직접 광고 시청을 선택 (예: “동영상 보고 생명 받기” 버튼)
- 보상 타입과 수량을 설정 가능
개발 환경에서는 테스트 유닛 ID를 사용하세요:
PUBLIC_TEST_UNIT_ID_REWARDED구현 방법
보상형 광고는 다음과 같은 단계로 구현합니다:- AdropRewardedAd 인스턴스 생성 - 유닛 ID로 광고 객체 생성
- Listener 설정 - 광고 이벤트 처리를 위한 리스너 지정
- 광고 로드 -
load()메서드로 광고 요청 - 광고 표시 -
show()메서드로 광고 표시 및 보상 처리
기본 구현
Kotlin 예제
import io.adrop.ads.rewardedAd.AdropRewardedAd
import io.adrop.ads.rewardedAd.AdropRewardedAdListener
import io.adrop.ads.model.AdropErrorCode
class RewardedActivity : AppCompatActivity() {
private var rewardedAd: AdropRewardedAd? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rewarded)
// 1. AdropRewardedAd 인스턴스 생성
rewardedAd = AdropRewardedAd(this, "YOUR_UNIT_ID")
// 2. Listener 설정
rewardedAd?.rewardedAdListener = object : AdropRewardedAdListener {
// 필수: 광고 수신 성공
override fun onAdReceived(ad: AdropRewardedAd) {
Log.d(TAG, "광고 수신 완료")
// 광고 시청 버튼 활성화 등
}
// 필수: 광고 수신 실패
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 수신 실패: $errorCode")
// 광고 시청 버튼 비활성화 유지 등
}
// 선택: 광고 노출
override fun onAdImpression(ad: AdropRewardedAd) {
Log.d(TAG, "광고 노출됨")
}
// 선택: 광고 클릭
override fun onAdClicked(ad: AdropRewardedAd) {
Log.d(TAG, "광고 클릭됨")
}
// 선택: 광고 화면 표시 직전
override fun onAdWillPresentFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 표시 예정")
// 배경 음악 일시정지 등
}
// 선택: 광고 화면 표시 완료
override fun onAdDidPresentFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 표시 완료")
}
// 선택: 광고 화면 닫기 직전
override fun onAdWillDismissFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 닫기 예정")
}
// 선택: 광고 화면 닫기 완료
override fun onAdDidDismissFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 닫힘")
// 배경 음악 재개 등
// 다음 광고 미리 로드
rewardedAd?.load()
}
// 선택: 광고 표시 실패
override fun onAdFailedToShowFullScreen(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 표시 실패: $errorCode")
}
}
// 3. 광고 로드
rewardedAd?.load()
// 광고 시청 버튼 클릭 처리
findViewById<Button>(R.id.btnShowRewardedAd).setOnClickListener {
showRewardedAd()
}
}
private fun showRewardedAd() {
// 광고가 로드되었는지 확인
if (rewardedAd?.isLoaded != true) {
Log.d(TAG, "광고가 아직 로드되지 않았습니다")
return
}
// 4. 광고 표시 및 보상 처리
rewardedAd?.show(this) { type, amount ->
// 보상 지급 처리
Log.d(TAG, "보상 획득 - 타입: $type, 수량: $amount")
grantReward(type, amount)
}
}
private fun grantReward(type: Int, amount: Int) {
// 사용자에게 보상 지급
// 예: 게임 재화 추가, 생명 회복 등
// ⚠️ 중요: 서버에서 보상을 검증하는 것을 권장합니다
// 클라이언트에서만 보상을 처리하면 부정행위가 가능합니다
}
override fun onDestroy() {
super.onDestroy()
rewardedAd?.destroy()
rewardedAd = null
}
companion object {
private const val TAG = "RewardedActivity"
}
}
Java 예제
import io.adrop.ads.rewardedAd.AdropRewardedAd;
import io.adrop.ads.rewardedAd.AdropRewardedAdListener;
import io.adrop.ads.model.AdropErrorCode;
public class RewardedActivity extends AppCompatActivity {
private static final String TAG = "RewardedActivity";
private AdropRewardedAd rewardedAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rewarded);
// 1. AdropRewardedAd 인스턴스 생성
rewardedAd = new AdropRewardedAd(this, "YOUR_UNIT_ID");
// 2. Listener 설정
rewardedAd.setRewardedAdListener(new AdropRewardedAdListener() {
// 필수: 광고 수신 성공
@Override
public void onAdReceived(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 수신 완료");
// 광고 시청 버튼 활성화 등
}
// 필수: 광고 수신 실패
@Override
public void onAdFailedToReceive(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 수신 실패: " + errorCode);
// 광고 시청 버튼 비활성화 유지 등
}
// 선택: 광고 노출
@Override
public void onAdImpression(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 노출됨");
}
// 선택: 광고 클릭
@Override
public void onAdClicked(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 클릭됨");
}
// 선택: 광고 화면 표시 직전
@Override
public void onAdWillPresentFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 표시 예정");
// 배경 음악 일시정지 등
}
// 선택: 광고 화면 표시 완료
@Override
public void onAdDidPresentFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 표시 완료");
}
// 선택: 광고 화면 닫기 직전
@Override
public void onAdWillDismissFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 닫기 예정");
}
// 선택: 광고 화면 닫기 완료
@Override
public void onAdDidDismissFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 닫힘");
// 배경 음악 재개 등
// 다음 광고 미리 로드
rewardedAd.load();
}
// 선택: 광고 표시 실패
@Override
public void onAdFailedToShowFullScreen(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 표시 실패: " + errorCode);
}
});
// 3. 광고 로드
rewardedAd.load();
// 광고 시청 버튼 클릭 처리
findViewById(R.id.btnShowRewardedAd).setOnClickListener(v -> showRewardedAd());
}
private void showRewardedAd() {
// 광고가 로드되었는지 확인
if (!rewardedAd.isLoaded()) {
Log.d(TAG, "광고가 아직 로드되지 않았습니다");
return;
}
// 4. 광고 표시 및 보상 처리
rewardedAd.show(this, (type, amount) -> {
// 보상 지급 처리
Log.d(TAG, "보상 획득 - 타입: " + type + ", 수량: " + amount);
grantReward(type, amount);
});
}
private void grantReward(int type, int amount) {
// 사용자에게 보상 지급
// 예: 게임 재화 추가, 생명 회복 등
// ⚠️ 중요: 서버에서 보상을 검증하는 것을 권장합니다
// 클라이언트에서만 보상을 처리하면 부정행위가 가능합니다
}
@Override
protected void onDestroy() {
super.onDestroy();
if (rewardedAd != null) {
rewardedAd.destroy();
rewardedAd = null;
}
}
}
AdropRewardedAd 클래스
생성자
AdropRewardedAd(context: Context, unitId: String)
속성
메서드
광고를 표시합니다.
activity: 광고를 표시할 ActivityuserDidEarnRewardHandler: 보상 지급 콜백(type: Int, amount: Int) -> Unit
AdropRewardedAdListener 인터페이스
필수 메서드
선택 메서드
보상 처리
보상 콜백
show() 메서드의 userDidEarnRewardHandler 파라미터로 보상 콜백을 전달합니다.
rewardedAd?.show(this) { type, amount ->
// type: 보상 타입 (Int)
// amount: 보상 수량 (Int)
Log.d(TAG, "보상 획득 - 타입: $type, 수량: $amount")
grantReward(type, amount)
}
rewardedAd.show(this, (type, amount) -> {
// type: 보상 타입 (Int)
// amount: 보상 수량 (Int)
Log.d(TAG, "보상 획득 - 타입: " + type + ", 수량: " + amount);
grantReward(type, amount);
});
보상 타입과 수량
- type: 애드컨트롤 콘솔에서 설정한 보상 타입 (정수 값)
- amount: 애드컨트롤 콘솔에서 설정한 보상 수량 (정수 값)
모범 사례
1. 광고 미리 로드하기
사용자 경험을 위해 광고를 미리 로드해두는 것이 좋습니다.class GameActivity : AppCompatActivity() {
private var rewardedAd: AdropRewardedAd? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
// 화면 진입 시 광고 미리 로드
loadRewardedAd()
}
private fun loadRewardedAd() {
rewardedAd = AdropRewardedAd(this, "YOUR_UNIT_ID")
rewardedAd?.rewardedAdListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
Log.d(TAG, "광고 준비 완료")
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 로드 실패: $errorCode")
}
override fun onAdDidDismissFullScreen(ad: AdropRewardedAd) {
// 광고가 닫힌 후 다음 광고 미리 로드
loadRewardedAd()
}
}
rewardedAd?.load()
}
private fun showRewardedAd() {
rewardedAd?.show(this) { type, amount ->
grantReward(type, amount)
}
}
}
public class GameActivity extends AppCompatActivity {
private AdropRewardedAd rewardedAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
// 화면 진입 시 광고 미리 로드
loadRewardedAd();
}
private void loadRewardedAd() {
rewardedAd = new AdropRewardedAd(this, "YOUR_UNIT_ID");
rewardedAd.setRewardedAdListener(new AdropRewardedAdListener() {
@Override
public void onAdReceived(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 준비 완료");
}
@Override
public void onAdFailedToReceive(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 로드 실패: " + errorCode);
}
@Override
public void onAdDidDismissFullScreen(@NonNull AdropRewardedAd ad) {
// 광고가 닫힌 후 다음 광고 미리 로드
loadRewardedAd();
}
});
rewardedAd.load();
}
private void showRewardedAd() {
rewardedAd.show(this, (type, amount) -> {
grantReward(type, amount);
});
}
}
2. 광고 준비 상태 확인
광고가 로드되었는지 확인하고 UI를 업데이트합니다.class GameActivity : AppCompatActivity() {
private var rewardedAd: AdropRewardedAd? = null
private var isAdReady = false
private fun updateButtonState() {
findViewById<Button>(R.id.btnWatchAd).apply {
isEnabled = isAdReady
alpha = if (isAdReady) 1.0f else 0.5f
text = if (isAdReady) "동영상 보고 생명 받기" else "광고 로딩 중..."
}
}
private val adListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
isAdReady = true
updateButtonState()
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
isAdReady = false
updateButtonState()
}
override fun onAdDidDismissFullScreen(ad: AdropRewardedAd) {
isAdReady = false
updateButtonState()
// 다음 광고 로드
rewardedAd?.load()
}
}
}
public class GameActivity extends AppCompatActivity {
private AdropRewardedAd rewardedAd;
private boolean isAdReady = false;
private void updateButtonState() {
Button btnWatchAd = findViewById(R.id.btnWatchAd);
btnWatchAd.setEnabled(isAdReady);
btnWatchAd.setAlpha(isAdReady ? 1.0f : 0.5f);
btnWatchAd.setText(isAdReady ? "동영상 보고 생명 받기" : "광고 로딩 중...");
}
private final AdropRewardedAdListener adListener = new AdropRewardedAdListener() {
@Override
public void onAdReceived(@NonNull AdropRewardedAd ad) {
isAdReady = true;
updateButtonState();
}
@Override
public void onAdFailedToReceive(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
isAdReady = false;
updateButtonState();
}
@Override
public void onAdDidDismissFullScreen(@NonNull AdropRewardedAd ad) {
isAdReady = false;
updateButtonState();
// 다음 광고 로드
rewardedAd.load();
}
};
}
3. 배경 음악 처리
광고 표시 전후로 배경 음악을 적절히 제어합니다.private val adListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
// 필수 구현
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
// 필수 구현
}
override fun onAdWillPresentFullScreen(ad: AdropRewardedAd) {
// 광고 표시 직전 배경 음악 일시정지
AudioManager.pauseBackgroundMusic()
}
override fun onAdDidDismissFullScreen(ad: AdropRewardedAd) {
// 광고 종료 후 배경 음악 재개
AudioManager.resumeBackgroundMusic()
}
}
private final AdropRewardedAdListener adListener = new AdropRewardedAdListener() {
@Override
public void onAdReceived(@NonNull AdropRewardedAd ad) {
// 필수 구현
}
@Override
public void onAdFailedToReceive(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
// 필수 구현
}
@Override
public void onAdWillPresentFullScreen(@NonNull AdropRewardedAd ad) {
// 광고 표시 직전 배경 음악 일시정지
AudioManager.pauseBackgroundMusic();
}
@Override
public void onAdDidDismissFullScreen(@NonNull AdropRewardedAd ad) {
// 광고 종료 후 배경 음악 재개
AudioManager.resumeBackgroundMusic();
}
};
4. 에러 처리
광고 로드 실패 시 재시도 로직을 구현합니다.private val adListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
Log.d(TAG, "광고 로드 성공")
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 로드 실패: $errorCode")
// 네트워크 에러인 경우 재시도
if (errorCode == AdropErrorCode.ERROR_CODE_NETWORK) {
Handler(Looper.getMainLooper()).postDelayed({
rewardedAd?.load()
}, 3000)
}
}
override fun onAdFailedToShowFullScreen(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 표시 실패: $errorCode")
// 사용자에게 알림
Toast.makeText(
this@GameActivity,
"광고를 표시할 수 없습니다. 나중에 다시 시도해주세요.",
Toast.LENGTH_SHORT
).show()
}
}
private final AdropRewardedAdListener adListener = new AdropRewardedAdListener() {
@Override
public void onAdReceived(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 로드 성공");
}
@Override
public void onAdFailedToReceive(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 로드 실패: " + errorCode);
// 네트워크 에러인 경우 재시도
if (errorCode == AdropErrorCode.ERROR_CODE_NETWORK) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
rewardedAd.load();
}, 3000);
}
}
@Override
public void onAdFailedToShowFullScreen(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 표시 실패: " + errorCode);
// 사용자에게 알림
Toast.makeText(
GameActivity.this,
"광고를 표시할 수 없습니다. 나중에 다시 시도해주세요.",
Toast.LENGTH_SHORT
).show();
}
};
5. 생명주기 관리
Activity 종료 시 광고 리소스를 정리합니다.class GameActivity : AppCompatActivity() {
private var rewardedAd: AdropRewardedAd? = null
override fun onDestroy() {
super.onDestroy()
rewardedAd?.destroy()
rewardedAd = null
}
}
public class GameActivity extends AppCompatActivity {
private AdropRewardedAd rewardedAd;
@Override
protected void onDestroy() {
super.onDestroy();
if (rewardedAd != null) {
rewardedAd.destroy();
rewardedAd = null;
}
}
}
완전한 예제
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import io.adrop.ads.rewardedAd.AdropRewardedAd
import io.adrop.ads.rewardedAd.AdropRewardedAdListener
import io.adrop.ads.model.AdropErrorCode
class GameActivity : AppCompatActivity() {
private var rewardedAd: AdropRewardedAd? = null
private var isAdReady = false
private lateinit var btnWatchAd: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
btnWatchAd = findViewById(R.id.btnWatchAd)
btnWatchAd.setOnClickListener {
showRewardedAd()
}
// 광고 미리 로드
loadRewardedAd()
}
private fun loadRewardedAd() {
rewardedAd = AdropRewardedAd(this, "PUBLIC_TEST_UNIT_ID_REWARDED")
rewardedAd?.rewardedAdListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
Log.d(TAG, "광고 수신 완료")
isAdReady = true
updateButtonState()
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 수신 실패: $errorCode")
isAdReady = false
updateButtonState()
// 네트워크 에러인 경우 3초 후 재시도
if (errorCode == AdropErrorCode.ERROR_CODE_NETWORK) {
Handler(Looper.getMainLooper()).postDelayed({
rewardedAd?.load()
}, 3000)
}
}
override fun onAdImpression(ad: AdropRewardedAd) {
Log.d(TAG, "광고 노출됨")
}
override fun onAdClicked(ad: AdropRewardedAd) {
Log.d(TAG, "광고 클릭됨")
}
override fun onAdWillPresentFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 표시 예정")
// 배경 음악 일시정지
pauseBackgroundMusic()
}
override fun onAdDidPresentFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 표시 완료")
}
override fun onAdWillDismissFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 닫기 예정")
}
override fun onAdDidDismissFullScreen(ad: AdropRewardedAd) {
Log.d(TAG, "광고 화면 닫힘")
isAdReady = false
updateButtonState()
// 배경 음악 재개
resumeBackgroundMusic()
// 다음 광고 미리 로드
loadRewardedAd()
}
override fun onAdFailedToShowFullScreen(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
Log.d(TAG, "광고 표시 실패: $errorCode")
Toast.makeText(
this@GameActivity,
"광고를 표시할 수 없습니다. 나중에 다시 시도해주세요.",
Toast.LENGTH_SHORT
).show()
}
}
rewardedAd?.load()
}
private fun showRewardedAd() {
if (!isAdReady) {
Toast.makeText(this, "광고가 아직 로드되지 않았습니다", Toast.LENGTH_SHORT).show()
return
}
rewardedAd?.show(this) { type, amount ->
Log.d(TAG, "보상 획득 - 타입: $type, 수량: $amount")
grantReward(type, amount)
}
}
private fun grantReward(type: Int, amount: Int) {
// 사용자에게 보상 지급
runOnUiThread {
Toast.makeText(
this,
"보상 획득! 타입: $type, 수량: $amount",
Toast.LENGTH_LONG
).show()
}
// 실제 보상 지급 로직 구현
// 예: 게임 재화 추가, 생명 회복 등
}
private fun updateButtonState() {
btnWatchAd.isEnabled = isAdReady
btnWatchAd.alpha = if (isAdReady) 1.0f else 0.5f
btnWatchAd.text = if (isAdReady) "동영상 보고 생명 받기" else "광고 로딩 중..."
}
private fun pauseBackgroundMusic() {
// 배경 음악 일시정지 로직
}
private fun resumeBackgroundMusic() {
// 배경 음악 재개 로직
}
override fun onDestroy() {
super.onDestroy()
rewardedAd?.destroy()
rewardedAd = null
}
companion object {
private const val TAG = "GameActivity"
}
}
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import io.adrop.ads.rewardedAd.AdropRewardedAd;
import io.adrop.ads.rewardedAd.AdropRewardedAdListener;
import io.adrop.ads.model.AdropErrorCode;
public class GameActivity extends AppCompatActivity {
private static final String TAG = "GameActivity";
private AdropRewardedAd rewardedAd;
private boolean isAdReady = false;
private Button btnWatchAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
btnWatchAd = findViewById(R.id.btnWatchAd);
btnWatchAd.setOnClickListener(v -> showRewardedAd());
// 광고 미리 로드
loadRewardedAd();
}
private void loadRewardedAd() {
rewardedAd = new AdropRewardedAd(this, "PUBLIC_TEST_UNIT_ID_REWARDED");
rewardedAd.setRewardedAdListener(new AdropRewardedAdListener() {
@Override
public void onAdReceived(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 수신 완료");
isAdReady = true;
updateButtonState();
}
@Override
public void onAdFailedToReceive(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 수신 실패: " + errorCode);
isAdReady = false;
updateButtonState();
// 네트워크 에러인 경우 3초 후 재시도
if (errorCode == AdropErrorCode.ERROR_CODE_NETWORK) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
rewardedAd.load();
}, 3000);
}
}
@Override
public void onAdImpression(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 노출됨");
}
@Override
public void onAdClicked(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 클릭됨");
}
@Override
public void onAdWillPresentFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 표시 예정");
// 배경 음악 일시정지
pauseBackgroundMusic();
}
@Override
public void onAdDidPresentFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 표시 완료");
}
@Override
public void onAdWillDismissFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 닫기 예정");
}
@Override
public void onAdDidDismissFullScreen(@NonNull AdropRewardedAd ad) {
Log.d(TAG, "광고 화면 닫힘");
isAdReady = false;
updateButtonState();
// 배경 음악 재개
resumeBackgroundMusic();
// 다음 광고 미리 로드
loadRewardedAd();
}
@Override
public void onAdFailedToShowFullScreen(@NonNull AdropRewardedAd ad, @NonNull AdropErrorCode errorCode) {
Log.d(TAG, "광고 표시 실패: " + errorCode);
Toast.makeText(
GameActivity.this,
"광고를 표시할 수 없습니다. 나중에 다시 시도해주세요.",
Toast.LENGTH_SHORT
).show();
}
});
rewardedAd.load();
}
private void showRewardedAd() {
if (!isAdReady) {
Toast.makeText(this, "광고가 아직 로드되지 않았습니다", Toast.LENGTH_SHORT).show();
return;
}
rewardedAd.show(this, (type, amount) -> {
Log.d(TAG, "보상 획득 - 타입: " + type + ", 수량: " + amount);
grantReward(type, amount);
});
}
private void grantReward(int type, int amount) {
// 사용자에게 보상 지급
runOnUiThread(() -> {
Toast.makeText(
this,
"보상 획득! 타입: " + type + ", 수량: " + amount,
Toast.LENGTH_LONG
).show();
});
// 실제 보상 지급 로직 구현
// 예: 게임 재화 추가, 생명 회복 등
}
private void updateButtonState() {
btnWatchAd.setEnabled(isAdReady);
btnWatchAd.setAlpha(isAdReady ? 1.0f : 0.5f);
btnWatchAd.setText(isAdReady ? "동영상 보고 생명 받기" : "광고 로딩 중...");
}
private void pauseBackgroundMusic() {
// 배경 음악 일시정지 로직
}
private void resumeBackgroundMusic() {
// 배경 음악 재개 로직
}
@Override
protected void onDestroy() {
super.onDestroy();
if (rewardedAd != null) {
rewardedAd.destroy();
rewardedAd = null;
}
}
}
테스트
테스트 유닛 ID
개발 중에는 항상 테스트 유닛 ID를 사용하세요.// 개발 환경
val rewardedAd = AdropRewardedAd(this, "PUBLIC_TEST_UNIT_ID_REWARDED")
// 프로덕션 환경
val rewardedAd = AdropRewardedAd(this, "YOUR_PRODUCTION_UNIT_ID")
// 개발 환경
AdropRewardedAd rewardedAd = new AdropRewardedAd(this, "PUBLIC_TEST_UNIT_ID_REWARDED");
// 프로덕션 환경
AdropRewardedAd rewardedAd = new AdropRewardedAd(this, "YOUR_PRODUCTION_UNIT_ID");
실제 유닛 ID로 테스트하면 무효 트래픽으로 간주되어 계정이 정지될 수 있습니다. 반드시 테스트 유닛 ID를 사용하세요.
환경별 유닛 ID 관리
빌드 타입에 따라 자동으로 유닛 ID를 변경하는 방법입니다.object AdUnitID {
val REWARDED: String
get() = if (BuildConfig.DEBUG) {
"PUBLIC_TEST_UNIT_ID_REWARDED"
} else {
"YOUR_PRODUCTION_UNIT_ID"
}
}
// 사용
val rewardedAd = AdropRewardedAd(this, AdUnitID.REWARDED)
public class AdUnitID {
public static String getREWARDED() {
if (BuildConfig.DEBUG) {
return "PUBLIC_TEST_UNIT_ID_REWARDED";
} else {
return "YOUR_PRODUCTION_UNIT_ID";
}
}
}
// 사용
AdropRewardedAd rewardedAd = new AdropRewardedAd(this, AdUnitID.getREWARDED());
백필 광고
백필 광고가 활성화된 경우, 직광고가 없을 때 자동으로 백필 광고가 로드됩니다.isBackfilled 프로퍼티로 백필 광고 여부를 확인할 수 있습니다.
rewardedAd.rewardedAdListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
if (ad.isBackfilled) {
println("백필 광고가 로드되었습니다")
} else {
println("직광고가 로드되었습니다")
}
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
when (errorCode) {
AdropErrorCode.ERROR_CODE_AD_NO_FILL -> {
println("직광고 없음, 백필 광고 요청 중...")
}
AdropErrorCode.ERROR_CODE_AD_BACKFILL_NO_FILL -> {
println("백필 광고도 없음")
}
else -> {
println("광고 로드 실패: $errorCode")
}
}
}
}
rewardedAd.setRewardedAdListener(new AdropRewardedAdListener() {
@Override
public void onAdReceived(AdropRewardedAd ad) {
if (ad.isBackfilled()) {
System.out.println("백필 광고가 로드되었습니다");
} else {
System.out.println("직광고가 로드되었습니다");
}
}
@Override
public void onAdFailedToReceive(AdropRewardedAd ad, AdropErrorCode errorCode) {
if (errorCode == AdropErrorCode.ERROR_CODE_AD_NO_FILL) {
System.out.println("직광고 없음, 백필 광고 요청 중...");
} else if (errorCode == AdropErrorCode.ERROR_CODE_AD_BACKFILL_NO_FILL) {
System.out.println("백필 광고도 없음");
} else {
System.out.println("광고 로드 실패: " + errorCode);
}
}
});
백필 광고를 사용하려면
io.adrop:adrop-ads-backfill 의존성을 추가해야 합니다. 시작하기를 참고하세요.서버 사이드 검증
서버 사이드 검증(SSV)을 사용하면 리워드 지급을 서버에서 안전하게 검증할 수 있습니다.ServerSideVerificationOptions를 사용하여 사용자 식별 정보와 커스텀 데이터를 서버 콜백에 포함시킬 수 있습니다.
서버에서 SSV 콜백을 수신하려면 콘솔 [관리] > [연동] > 리워드 광고 SSV에서 콜백 URL을 등록해야 해요. 여기서 설정한
userId와 customData는 해당 URL로 전송되는 암호화 페이로드에 포함됩니다. 페이로드 복호화 및 설정 방법은 리워드 광고 SSV 가이드를 참고하세요.SSV 설정
val rewardedAd = AdropRewardedAd(this, "YOUR_UNIT_ID")
// 광고 로드 전에 SSV 옵션 설정
rewardedAd.serverSideVerificationOptions = ServerSideVerificationOptions(
userId = "user_12345",
customData = "extra_info"
)
rewardedAd.rewardedAdListener = object : AdropRewardedAdListener {
override fun onAdReceived(ad: AdropRewardedAd) {
ad.show(this@MainActivity) { type, amount ->
Log.d("Reward", "Type: $type, Amount: $amount")
}
}
override fun onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode) {
// Handle error
}
}
rewardedAd.load()
AdropRewardedAd rewardedAd = new AdropRewardedAd(this, "YOUR_UNIT_ID");
// 광고 로드 전에 SSV 옵션 설정
rewardedAd.setServerSideVerificationOptions(
new ServerSideVerificationOptions("user_12345", "extra_info")
);
rewardedAd.setRewardedAdListener(new AdropRewardedAdListener() {
@Override
public void onAdReceived(AdropRewardedAd ad) {
ad.show(this, (type, amount) -> {
Log.d("Reward", "Type: " + type + ", Amount: " + amount);
});
}
});
rewardedAd.load();
ServerSideVerificationOptions
| 프로퍼티 | 타입 | 설명 |
|---|---|---|
userId | String? | 서버 사이드 검증에 사용할 사용자 식별자 |
customData | String? | 서버 콜백에 전달할 커스텀 데이터 문자열 |
백필 폴백 경로에서는
customData가 base64url로 sanitize되어 전달됩니다(+→-, /→_, = 제거, 백필 1.12.1+). customData에 base64 페이로드를 담는 경우 서버에서 base64url로 디코딩하세요.serverSideVerificationOptions는 load() 호출 전에 설정해야 합니다. userId와 customData 값은 사용자가 보상을 획득할 때 서버 콜백 URL로 전송됩니다.관련 문서
전면 광고
전면 광고 구현 가이드
에러 코드
AdropErrorCode 레퍼런스
예제 프로젝트
전체 예제 코드 보기