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

Android Kotlin插屏广告无法显示问题求助及代码排查

插屏广告无法显示的代码问题排查与修复

核心问题与修复步骤

1. 广告加载是异步操作,点击时立即判断必然失败

你在点击thumbnail后,刚调用interAds(context)就立刻判断mInterstitialAd != null。但InterstitialAd.load()是异步方法,广告加载需要网络请求时间,此时mInterstitialAd还未被赋值,所以永远不会进入显示广告的逻辑。

修复方案:

  • 提前预加载广告,比如在Application启动、页面初始化时就调用加载方法,而非用户点击时才开始加载;
  • 在InterstitialAdLoadCallback的onAdLoaded回调中标记广告就绪,点击时直接判断就绪状态再显示。

2. 每次点击新建InterstitialAds实例,广告状态无法保留

点击时创建新的InterstitialAds()对象,之前加载的广告实例会被丢弃,且重复调用MobileAds.initialize完全没必要。

修复方案:

  • 将InterstitialAds设计为单例,让全局共享一个实例,避免每次点击都重建;
  • MobileAds.initialize(context)只在Application的onCreate()中调用一次,无需每次加载广告都执行。

3. FullScreenContentCallback设置时机错误

你在调用show()之后才设置回调,会导致广告展示失败等关键回调无法被捕获,逻辑顺序完全颠倒。

修复方案:
在onAdLoaded回调中,广告加载完成后就设置FullScreenContentCallback,再等待用户点击触发显示。

4. 空安全处理不严谨,强制非空存在崩溃风险

直接使用!!强制非空,若广告加载失败mInterstitialAd为null时,会触发空指针异常。

修复方案:
使用?.安全调用,或先做非空判断再执行操作。


修复后的参考代码

1. 优化后的InterstitialAds单例类

class InterstitialAds private constructor() {
    var mInterstitialAd: InterstitialAd? = null
    private var adDismissCallback: (() -> Unit)? = null

    companion object {
        val instance: InterstitialAds by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            InterstitialAds()
        }
    }

    // 全局初始化,仅调用一次
    fun initialize(context: Context) {
        MobileAds.initialize(context)
    }

    // 预加载广告,传入广告关闭后的回调
    fun loadAd(context: Context, dismissCallback: (() -> Unit)? = null) {
        this.adDismissCallback = dismissCallback
        val adRequest = AdRequest.Builder().build()
        InterstitialAd.load(
            context,
            "ca-app-pub-3940256099942544/1033173712", // 测试ID,正式环境替换为你的广告ID
            adRequest,
            object : InterstitialAdLoadCallback() {
                override fun onAdFailedToLoad(adError: LoadAdError) {
                    Log.d("InterstitialAd", "加载失败: ${adError.message}")
                    mInterstitialAd = null
                    // 可选:加载失败后延迟重试
                    // Handler(Looper.getMainLooper()).postDelayed({ loadAd(context) }, 3000)
                }

                override fun onAdLoaded(interstitialAd: InterstitialAd) {
                    mInterstitialAd = interstitialAd
                    // 提前设置全屏回调
                    interstitialAd.fullScreenContentCallback = object : FullScreenContentCallback() {
                        override fun onAdDismissedFullScreenContent() {
                            Log.d("InterstitialAd", "广告关闭")
                            mInterstitialAd = null
                            adDismissCallback?.invoke() // 执行广告关闭后的业务逻辑
                            loadAd(context) // 预加载下一个广告
                        }

                        override fun onAdFailedToShowFullScreenContent(adError: AdError) {
                            Log.d("InterstitialAd", "展示失败: ${adError.message}")
                            mInterstitialAd = null
                        }
                    }
                }
            }
        )
    }

    // 尝试显示广告,返回是否成功触发
    fun showAd(activity: Activity): Boolean {
        return if (mInterstitialAd != null) {
            mInterstitialAd?.show(activity)
            true
        } else {
            Log.d("InterstitialAd", "广告未加载完成,无法显示")
            loadAd(activity)
            false
        }
    }
}

2. 在Application中初始化广告

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        InterstitialAds.instance.initialize(this)
        InterstitialAds.instance.loadAd(this) // 预加载第一个广告
    }
}

3. Adapter中的点击事件修改

holder.thumbnail.setOnClickListener {
    val activity = context as? Activity ?: return@setOnClickListener
    val isAdShown = InterstitialAds.instance.showAd(activity)
    if (!isAdShown) {
        // 广告未加载好,直接展示视频内容
        showVideoContent(holder)
    } else {
        // 广告已触发显示,等待回调执行后续逻辑
        InterstitialAds.instance.loadAd(context) {
            showVideoContent(holder)
        }
    }
}

// 提取视频展示逻辑为单独方法
private fun showVideoContent(holder: ViewHolder) {
    holder.progressBar.visibility = View.VISIBLE
    holder.webView.visibility = View.VISIBLE
    holder.thumnail.visibility = View.GONE

    val webSettings = holder.webView.settings
    webSettings.javaScriptEnabled = true

    holder.webView.webViewClient = object : WebViewClient() {
        override fun onPageFinished(view: WebView?, url: String?) {
            holder.progressBar.visibility = View.GONE
            holder.fullButton.visibility = View.VISIBLE
        }
    }

    holder.webView.loadData(item.videoEmbed!!, "text/html", "utf-8")
}

额外注意事项

  • 确保AndroidManifest.xml中配置了AdMob应用ID:<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="你的应用ID"/>;
  • 测试阶段使用AdMob官方测试广告ID,避免触发真实广告的限制;
  • 不要在已销毁的Activity中调用show()方法,注意生命周期判断;
  • 广告加载失败可添加重试逻辑,但需避免无限重试。

内容的提问来源于stack exchange,提问作者Sabuj Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 00:05:54