You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数集中后RewardedAd异常,需返回广告完整播放确认值

问题分析与修复方案

你的代码核心问题在于异步逻辑处理错误,以及奖励状态的判断逻辑不符合需求,具体问题和修复如下:

主要问题点

  • 同步返回异步结果:loadRewardedAd是同步方法,但广告的加载、展示、奖励发放都是异步回调操作,你直接返回adRewardedBoolean时,回调还没执行,返回的永远是初始的false,根本拿不到真实的广告完成状态。
  • 奖励状态判断错误:
    • 你在onAdDismissedFullScreenContent里把adRewardedBoolean设为true,但这个回调是广告被关闭就触发,不管用户有没有看完广告拿到奖励(比如用户中途手动关闭广告)。
    • 加载失败3次就强制设为true,这完全不符合“广告完整播放完毕”的需求,加载失败不等于用户完成了广告观看。
  • 状态未重置:每次调用loadRewardedAd时,没有重置adRewardedBoolean、adRewardedTimes这些状态变量,导致多次调用后状态混乱。
  • 递归重试风险:加载失败直接递归调用loadRewardedAd,容易引发栈溢出或者频繁请求广告服务器的问题。

修复后的代码

我们改用回调接口来传递广告完成状态(因为异步操作无法同步返回结果),同时修正奖励判断逻辑:

//Rewarded
private const val adRewardedID = "ca-app-pub-3306064401573277/5337641258"
private var adRewardedIsLoading = false
private var adRewarded: RewardedAd? = null
private var adRewardAmount: Int = 0
private var adRewardedTimes: Int = 0

// 定义回调接口,用于通知广告是否完成并获取奖励
interface RewardedAdCallback {
    fun onAdRewarded(amount: Int) // 广告完成,拿到奖励
    fun onAdFailed() // 广告加载/展示失败,未获得奖励
}

//Call loadRewardedAd from any activities
//Ads.loadRewardedAd(this, object : RewardedAdCallback { ... })
fun loadRewardedAd(context: Context, callback: RewardedAdCallback) {
    val activity = context as? Activity ?: run {
        callback.onAdFailed()
        return
    }
    
    // 正在加载时直接返回,避免重复请求
    if (adRewardedIsLoading) {
        return
    }
    
    // 重置状态
    adRewardedTimes = 0
    adRewardAmount = 0
    
    loadAdInternal(activity, callback)
}

private fun loadAdInternal(activity: Activity, callback: RewardedAdCallback) {
    adRewardedIsLoading = true
    val adRequest = AdRequest.Builder().build()
    
    RewardedAd.load(activity, adRewardedID, adRequest, object : RewardedAdLoadCallback() {
        override fun onAdFailedToLoad(adError: LoadAdError) {
            adRewardedIsLoading = false
            adRewarded = null
            
            if (adRewardedTimes >= 3) {
                // 重试3次后仍失败,通知回调
                callback.onAdFailed()
                log("广告加载重试3次失败")
            } else {
                adRewardedTimes++
                // 延迟1秒重试,避免频繁请求
                activity.window.decorView.postDelayed({
                    loadAdInternal(activity, callback)
                }, 1000)
                log("广告加载失败,重试第${adRewardedTimes}次")
            }
        }

        override fun onAdLoaded(rewardedAd: RewardedAd) {
            adRewarded = rewardedAd
            adRewardedIsLoading = false
            
            adRewarded?.fullScreenContentCallback = object : FullScreenContentCallback() {
                override fun onAdDismissedFullScreenContent() {
                    adRewarded = null
                    log("广告被关闭")
                }

                override fun onAdFailedToShowFullScreenContent(adError: AdError) {
                    adRewarded = null
                    // 展示失败,重新加载
                    loadAdInternal(activity, callback)
                    log("广告展示失败")
                }

                override fun onAdShowedFullScreenContent() {
                    log("广告开始展示")
                }
            }
            
            // 展示广告,在奖励回调里标记广告完成
            adRewarded?.show(activity) { rewardItem ->
                adRewardAmount = rewardItem.amount
                // 只有拿到奖励时,才通知广告完成
                callback.onAdRewarded(adRewardAmount)
                log("广告播放完成,获得奖励:${adRewardAmount}")
            }
        }
    })
}

关键修改说明

  1. 改用回调接口:通过RewardedAdCallback异步传递广告状态,解决同步方法无法返回异步结果的问题。
  2. 修正奖励判断逻辑:只有在广告展示后的奖励回调(show方法的lambda参数)里,才触发onAdRewarded,确保用户确实完整观看广告并获得奖励。
  3. 状态重置:每次调用loadRewardedAd时重置重试次数和奖励金额,避免状态污染。
  4. 安全重试:用延迟重试替代递归,避免栈溢出,同时限制重试次数(3次),防止无限请求。
  5. 类型安全检查:增加context转Activity的安全判断,避免类型转换异常。

使用示例

在Activity中调用:

Ads.loadRewardedAd(this, object : Ads.RewardedAdCallback {
    override fun onAdRewarded(amount: Int) {
        // 这里处理广告完成后的逻辑,比如给用户发奖励
        Toast.makeText(this@MainActivity, "获得奖励:${amount}", Toast.LENGTH_SHORT).show()
    }

    override fun onAdFailed() {
        // 处理广告失败的逻辑
        Toast.makeText(this@MainActivity, "广告加载失败", Toast.LENGTH_SHORT).show()
    }
})

内容的提问来源于stack exchange,提问作者Suleiman Mohammed Fahim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:20:46