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
相关产品推荐
相关产品推荐

