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

Jetpack Compose中安全获取Activity的方案?广告管理器适配难题

问题:Jetpack Compose+Hilt集成插屏广告管理器的Activity获取问题

我在Jetpack Compose应用中实现了处理插屏广告的InterstitialAdManager类,代码如下:

class InterstitialAdManager(private val context: Context) {

    private var mInterstitialAd: InterstitialAd? = null
    private var lastLoadedUnitAd: String? = null

    init {
        loadInterstitial()
    }

    private fun loadInterstitial() {
        InterstitialAd.load(
            context,
            lastLoadedUnitAd.orEmpty(),
            AdRequest.Builder().build(),
            object : InterstitialAdLoadCallback() {

                override fun onAdFailedToLoad(adError: LoadAdError) {
                    mInterstitialAd = null
                }

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

    fun showInterstitial(
        onAdDismissed: () -> Unit = {},
        onAdShowedFullScreen: () -> Unit = {}
    ) {
        val activity = context.findActivity()

        if (mInterstitialAd != null && activity != null) {

            mInterstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback() {

                override fun onAdFailedToShowFullScreenContent(e: AdError) {
                    mInterstitialAd = null
                    onAdDismissed()
                }

                override fun onAdDismissedFullScreenContent() {
                    mInterstitialAd = null

                    loadInterstitial()
                    onAdDismissed()
                }

                override fun onAdShowedFullScreenContent() {
                    onAdShowedFullScreen()
                }
            }
            mInterstitialAd?.show(activity)

        } else {
            onAdDismissed()
        }
    }

    fun removeInterstitial() {
        mInterstitialAd?.fullScreenContentCallback = null
        mInterstitialAd = null
    }

    fun setAdUnit(unitAd: String) {
        lastLoadedUnitAd = unitAd
        loadInterstitial()
    }

    private fun Context.findActivity(): Activity? = when (this) {
        is Activity -> this
        is ContextWrapper -> baseContext.findActivity()
        else -> null
    }
}

该类在XML开发中运行正常,但在Jetpack Compose结合Hilt注入时遇到问题:

我通过DetailState管理状态:

data class DetailState(
    val interstitialAdManager: InterstitialAdManager? = null,
    val currentDesign: Design? = null
)

并在ViewModel中注入广告管理器:

@HiltViewModel
class DetailViewModel @Inject constructor(interstitialAdManager: InterstitialAdManager,   
) : ViewModel() {

    var state by mutableStateOf(DetailState())
        private set

    init {
        state = state.copy(interstitialAdManager = interstitialAdManager)
        state.interstitialAdManager?.setAdUnit("hidden_unit_ad")
    }
}

最初的Hilt模块提供Application Context:

@Module
@InstallIn(SingletonComponent::class)
class AdsModule {

    @Provides
    @Singleton
    fun interstitialAdManagerProvider(@ApplicationContext context: Context) =
        InterstitialAdManager(context)
}

这导致管理器的findActivity方法无法找到Activity。

尝试将模块改为ActivityComponent的ActivityScoped:

@Module
@InstallIn(ActivityComponent::class)
class AdsModule {

    @Provides
    @ActivityScoped
    fun interstitialAdManagerProvider(@ActivityContext context: Context) =
        InterstitialAdManager(context)
}

但因ViewModel与Activity组件范围不匹配出现编译错误。

目前可行但不够安全的方案是在showInterstitial方法中传入Activity,通过val activity = LocalContext.current as Activity获取,希望得到更优的实现方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:06:21