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

Kotlin Android App Open Ads首次启动onStart无法展示问题

问题根因

首次启动广告无法展示是两个时序逻辑错误导致的:

  • 生命周期回调顺序不对:应用冷启动时,ProcessLifecycleOwner的onStart回调早于首个Activity的生命周期方法执行。此时currentActivity还没通过ActivityLifecycleCallbacks完成赋值,为null,不满足广告展示的宿主Activity要求。
  • 广告加载时机太晚:第一次触发onStart调用展示逻辑时,广告还没开始拉取;广告加载是异步网络请求,等广告返回结果时onStart的执行流程已经走完,自然不会触发展示。等你退出应用切回前台时,之前触发加载的广告已经准备完成,currentActivity也有了有效值,所以能正常展示。
修复方案

1. 调整广告预加载时机

不要等要展示广告的时候才发起加载请求,等AdMob SDK初始化完成后立刻预加载广告,提前留出广告加载的时间窗口,同时避免SDK未初始化就发请求导致加载失败。
修改MyApplication代码:

class MyApplication : Application() {
    private var appOpenManager: AppOpenManager? = null
    override fun onCreate() {
        super.onCreate()
        appOpenManager = AppOpenManager(this)
        ProcessLifecycleOwner.get().lifecycle.addObserver(appOpenManager!!.defaultLifecycleObserver)

        MobileAds.initialize(this) {
            Log.d("tag", "MobileAds init ")
            // SDK初始化完成后触发第一次广告预加载
            appOpenManager?.fetchAd()
        }
    }
}

注意要把AppOpenManager里的fetchAd方法的可见性从private改成public,方便在Application里调用。

2. 补全空判断与冷启动展示逻辑

给广告展示逻辑加非空校验,同时在首个Activity获取到焦点(onActivityResumed)时补一次展示检查,解决冷启动时的时序冲突;另外增加冷启动标记,避免重复展示。
修改AppOpenManager代码:
首先新增冷启动标记变量:

class AppOpenManager(private val myApplication: MyApplication) :
    Application.ActivityLifecycleCallbacks,
    LifecycleObserver {

    private var appOpenAd: AppOpenAd? = null
    private var loadCallback: AppOpenAd.AppOpenAdLoadCallback? = null
    private var currentActivity: Activity? = null
    private var isShowingAd = false
    // 新增冷启动标记
    private var isColdStart = true
    // ... 其余原有变量不变

然后修改showAdIfAvailable方法,增加空判断,优化失败重试逻辑:

fun showAdIfAvailable() {
    Log.d("tag", "isShowing:$isShowingAd - hasAd:$isAdAvailable - hasActivity:${currentActivity != null}")
    // 同时满足 未在展示、有可用广告、有有效Activity 三个条件才展示
    if (!isShowingAd && isAdAvailable && currentActivity != null) {
        Log.d("tag", "show ad")
        val fullScreenContentCallback: FullScreenContentCallback =
            object : FullScreenContentCallback() {

                override fun onAdDismissedFullScreenContent() {
                    appOpenAd = null
                    isShowingAd = false
                    // 广告关闭后预加载下一次的广告
                    fetchAd()
                }

                override fun onAdFailedToShowFullScreenContent(p0: AdError) {
                    isShowingAd = false
                    // 展示失败重新拉取广告
                    fetchAd()
                }

                override fun onAdShowedFullScreenContent() {
                    isShowingAd = true
                    // 广告展示完成后关闭冷启动标记
                    isColdStart = false
                }
            }
        appOpenAd!!.fullScreenContentCallback = fullScreenContentCallback
        appOpenAd!!.show(currentActivity!!)
    } else {
        Log.d("tag", "can't show ad")
        // 没可用广告时才触发拉取,避免重复请求
        if (!isAdAvailable) {
            fetchAd()
        }
    }
}

然后修改onActivityResumed回调,补冷启动的展示检查:

override fun onActivityResumed(activity: Activity) {
    currentActivity = activity
    // 冷启动场景下,Activity拿到焦点后补一次展示检查,解决时序问题
    if (isColdStart) {
        showAdIfAvailable()
    }
}

把原来init块里的fetchAd()调用删掉,避免SDK未初始化就发起广告请求。
原有DefaultLifecycleObserver里的onStart逻辑保留即可,用来处理应用切后台回前台的热启动广告展示场景。

注意事项
  • 不要在广告加载完成的onAdLoaded回调里直接调用show方法,此时大概率Activity还没完成渲染,容易出现展示异常、崩溃或者广告政策违规问题。
  • 开发测试阶段请使用官方提供的测试广告位ID,使用正式ID频繁触发请求、展示很容易被判定为异常流量,导致广告位被限制填充。
  • 如果你的应用有启动页(SplashActivity),建议把广告展示逻辑绑定到SplashActivity的生命周期,而不是全局ProcessLifecycle,避免在其他页面切回时误弹广告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:21:13