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

AdMob警告布局易引发误触:意外启动插屏广告(Jetpack Compose)

解决AdMob“Layout Encourages Accidental Clicks - Unexpected Launch Interstitials”警告

问题背景

使用Kotlin+Jetpack Compose开发的应用收到AdMob警告,原因是用户返回页面后广告才加载完成并弹出,触发了AdMob的误触检测机制。现有逻辑中,返回操作与广告加载/展示不同步,广告加载速度慢于页面切换,导致广告在用户回到上一页后意外弹出。

核心问题分析

  1. 广告加载时机滞后:当前在用户点击返回时才开始加载广告,若广告加载耗时较长,会出现页面已经返回、广告才弹出的情况,符合AdMob禁止的“意外插屏广告”场景。
  2. 页面返回与广告展示不同步:返回操作(navController.popBackStack())直接执行,未等待广告展示完成或确认广告是否已加载,导致广告状态与页面状态脱节。

解决方案

1. 提前预加载广告,避免返回时才启动加载

在应用启动或进入目标页面时就预加载插屏广告,确保用户点击返回时广告已准备就绪。修改MainActivity的初始化逻辑:

class MainActivity : ComponentActivity() {
    private var mInterstitialAd: InterstitialAd? = null
    private var adId: String = "some_id_123456"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 启动时立即预加载广告
        loadInterstitialAd { initialAdStatus ->
            runOnUiThread {
                setContent {
                    val currentTheme = isSystemInDarkTheme()
                    var darkTheme by remember { mutableStateOf(currentTheme) }
                    var adStatusState by remember { mutableStateOf(initialAdStatus) }

                    MyAppTheme(darkTheme = darkTheme) {
                        Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                            MY_APP(
                                darkTheme = darkTheme,
                                onThemeUpdated = { darkTheme = !darkTheme },
                                onBackButtonClicked = { adDismissedCallback ->
                                    if (adStatusState) {
                                        // 展示已预加载的广告
                                        showInterstitialAd {
                                            adStatusState = false
                                            // 广告关闭后立即预加载下一个
                                            loadInterstitialAd { adStatusState = it }
                                            adDismissedCallback()
                                        }
                                    } else {
                                        // 无可用广告,直接执行返回回调
                                        adDismissedCallback()
                                        // 同时预加载下一个广告
                                        loadInterstitialAd { adStatusState = it }
                                    }
                                }
                            )
                        }
                    }
                }
            }
        }
    }

    private fun loadInterstitialAd(adStatus: (Boolean) -> Unit) {
        val adRequest = AdRequest.Builder().build()
        InterstitialAd.load(
            this,
            adId,
            adRequest,
            object : InterstitialAdLoadCallback() {
                override fun onAdFailedToLoad(adError: LoadAdError) {
                    mInterstitialAd = null
                    adStatus(false)
                }

                override fun onAdLoaded(interstitialAd: InterstitialAd) {
                    mInterstitialAd = interstitialAd
                    adStatus(true)
                }
            }
        )
    }

    // 修改showInterstitialAd,添加广告关闭回调
    private fun showInterstitialAd(onAdDismissed: () -> Unit) {
        mInterstitialAd?.let { ad ->
            ad.fullScreenContentCallback = object : FullScreenContentCallback() {
                override fun onAdShowedFullScreenContent() {
                    mInterstitialAd = null
                }

                override fun onAdDismissedFullScreenContent() {
                    onAdDismissed()
                }

                // 处理广告展示失败的情况,确保回调执行
                override fun onAdFailedToShowFullScreenContent(adError: AdError) {
                    mInterstitialAd = null
                    onAdDismissed()
                }
            }
            ad.show(this)
        } ?: run {
            Toast.makeText(this, "No ad shows", Toast.LENGTH_SHORT).show()
            onAdDismissed()
        }
    }
}

2. 同步页面返回与广告展示逻辑

确保只有在广告展示完成(或确认无可用广告)后,才执行页面返回操作,避免广告在页面切换后弹出。修改返回逻辑:

val onMoveBack: () -> Unit = {
    // 通过回调控制页面返回时机
    onBackButtonClicked {
        navController.popBackStack()
    }
}

3. 遵守AdMob插屏广告规范

  • 广告仅在用户主动触发的操作(如明确点击返回按钮)后立即展示,绝不延迟弹出。
  • 广告展示后,确保用户可正常关闭,关闭后回到预期页面。
  • 避免在页面加载、切换等用户未主动触发的场景下弹出广告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:43:19