보상형 광고는 사용자가 동영상 광고를 끝까지 시청하면 게임 내 재화, 생명, 힌트 등의 보상을 제공하는 전면 동영상 광고입니다.
주요 특징
- 전면 화면을 차지하는 동영상 광고
- 사용자가 광고를 완전히 시청한 경우에만 보상 제공
- 사용자가 직접 광고 시청을 선택 (예: “동영상 보고 생명 받기” 버튼)
- 보상 타입과 수량을 설정 가능
개발 환경에서는 테스트 유닛 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 또는 Application의 Context
광고가 로드되어 표시 가능한 상태인지 여부 (읽기 전용)
로드된 광고의 크리에이티브 ID (읽기 전용)
메서드
광고를 요청합니다. 광고 로드 결과는 리스너의 onAdReceived 또는 onAdFailedToReceive로 전달됩니다.
show(activity, userDidEarnRewardHandler)
광고를 표시합니다.
activity: 광고를 표시할 Activity
userDidEarnRewardHandler: 보상 지급 콜백 (type: Int, amount: Int) -> Unit
광고 리소스를 해제합니다. Activity의 onDestroy()에서 호출해야 합니다.
AdropRewardedAdListener 인터페이스
필수 메서드
onAdReceived(ad: AdropRewardedAd)
광고 수신에 성공했을 때 호출됩니다. 이 시점부터 show() 메서드로 광고를 표시할 수 있습니다.
onAdFailedToReceive(ad: AdropRewardedAd, errorCode: AdropErrorCode)
광고 수신에 실패했을 때 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.
선택 메서드
onAdImpression(ad: AdropRewardedAd)
광고가 노출되어 노출 기록이 전송되었을 때 호출됩니다.
onAdClicked(ad: AdropRewardedAd)
사용자가 광고를 클릭했을 때 호출됩니다.
onAdWillPresentFullScreen(ad: AdropRewardedAd)
광고 화면이 표시되기 직전에 호출됩니다. 배경 음악을 일시정지하는 등의 처리를 할 수 있습니다.
onAdDidPresentFullScreen(ad: AdropRewardedAd)
광고 화면이 완전히 표시된 후 호출됩니다.
onAdWillDismissFullScreen(ad: AdropRewardedAd)
광고 화면이 닫히기 직전에 호출됩니다.
onAdDidDismissFullScreen(ad: AdropRewardedAd)
광고 화면이 완전히 닫힌 후 호출됩니다. 배경 음악을 재개하거나 다음 광고를 미리 로드할 수 있습니다.
onAdFailedToShowFullScreen(ad: AdropRewardedAd, errorCode: AdropErrorCode)
광고 표시에 실패했을 때 호출됩니다. 에러 코드를 통해 실패 원인을 확인할 수 있습니다.
보상 처리
보상 콜백
show() 메서드의 userDidEarnRewardHandler 파라미터로 보상 콜백을 전달합니다.
rewardedAd?.show(this) { type, amount ->
// type: 보상 타입 (Int)
// amount: 보상 수량 (Int)
Log.d(TAG, "보상 획득 - 타입: $type, 수량: $amount")
grantReward(type, amount)
}
보상 타입과 수량
- type: 애드컨트롤 콘솔에서 설정한 보상 타입 (정수 값)
- amount: 애드컨트롤 콘솔에서 설정한 보상 수량 (정수 값)
Best Practices
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)
}
}
}
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()
}
}
}
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()
}
}
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()
}
}
5. 생명주기 관리
Activity 종료 시 광고 리소스를 정리합니다.
class GameActivity : AppCompatActivity() {
private var rewardedAd: AdropRewardedAd? = null
override fun onDestroy() {
super.onDestroy()
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"
}
}
테스트
테스트 유닛 ID
개발 중에는 항상 테스트 유닛 ID를 사용하세요.
// 개발 환경
val rewardedAd = AdropRewardedAd(this, "PUBLIC_TEST_UNIT_ID_REWARDED")
// 프로덕션 환경
val rewardedAd = 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)
관련 문서