关于KMM兼容广告服务(如Google Admob)的技术咨询
适配KMM的广告服务方案及独立实现思路
一、有没有适配KMM的Google Admob相关库?
目前社区有部分针对KMM的广告适配库,但成熟度和官方支持度远不如原生SDK。比如一些开发者维护的admob-kmp类库,能提供基础的跨平台Admob调用能力,但可能存在功能不全、版本更新滞后的问题,使用前需要结合项目需求评估库的维护状态。如果追求稳定性,官方暂时没有推出正式的KMM版Admob SDK,优先考虑原生实现方案更稳妥。
二、双平台独立实现(UI在common模块)的思路
核心是利用KMM的expect/actual机制,结合Compose Multiplatform的平台原生视图嵌入能力,把广告的加载、渲染逻辑下沉到平台模块,common模块只负责定义抽象接口和UI容器。
步骤1:Common层定义接口与UI容器
在common模块中,先定义广告管理的抽象接口,以及Compose广告容器组件:
// common/src/commonMain/kotlin/com/yourproject/ad/AdManager.kt expect class AdManager { fun loadBannerAd(unitId: String) val adState: StateFlow<AdState> } sealed class AdState { object Loading : AdState() data class Loaded(val adContent: Any?) : AdState() // 存储平台原生广告实例 data class Failed(val error: String) : AdState() } // common/src/commonMain/kotlin/com/yourproject/ui/AdCompose.kt @Composable fun BannerAd(unitId: String, adManager: AdManager) { val adState by adManager.adState.collectAsStateWithLifecycle() when (adState) { AdState.Loading -> { Box(modifier = Modifier.fillMaxWidth().height(50.dp).background(Color.Gray)) { Text(text = "广告加载中...", modifier = Modifier.align(Alignment.Center)) } } is AdState.Failed -> { Box(modifier = Modifier.fillMaxWidth().height(50.dp).background(Color.Red)) { Text(text = "广告加载失败", modifier = Modifier.align(Alignment.Center)) } } is AdState.Loaded -> { // 由平台层实现具体的广告视图渲染 PlatformBannerAd(adState.adContent) } } } expect @Composable fun PlatformBannerAd(adContent: Any?)
步骤2:Android平台实现
在Android模块中,实现actual类,用原生Admob SDK加载广告,并通过AndroidView嵌入Compose:
// android/src/androidMain/kotlin/com/yourproject/ad/AdManagerAndroid.kt actual class AdManager actual constructor() { private val _adState = MutableStateFlow<AdState>(AdState.Loading) actual val adState: StateFlow<AdState> = _adState actual fun loadBannerAd(unitId: String) { val adView = AdView(ApplicationProvider.getApplicationContext()) adView.adUnitId = unitId adView.adSize = AdSize.BANNER adView.adListener = object : AdListener() { override fun onAdLoaded() { _adState.value = AdState.Loaded(adView) } override fun onAdFailedToLoad(error: LoadAdError) { _adState.value = AdState.Failed(error.message) } } adView.loadAd(AdRequest.Builder().build()) } } // android/src/androidMain/kotlin/com/yourproject/ui/AdComposeAndroid.kt actual @Composable fun PlatformBannerAd(adContent: Any?) { AndroidView( factory = { adContent as AdView }, modifier = Modifier.fillMaxWidth() ) }
步骤3:iOS平台实现
在iOS模块中,用原生Admob SDK实现actual类,通过UIKitView嵌入Compose:
// ios/src/iosMain/kotlin/com/yourproject/ad/AdManagerIos.kt actual class AdManager actual constructor() { private val _adState = MutableStateFlow<AdState>(AdState.Loading) actual val adState: StateFlow<AdState> = _adState actual fun loadBannerAd(unitId: String) { val bannerView = GADBannerView(adSize = GADAdSizeBanner) bannerView.adUnitID = unitId bannerView.rootViewController = UIApplication.shared.keyWindow?.rootViewController bannerView.adDelegate = object : GADBannerViewDelegateProtocol { override fun adViewDidReceiveAd(bannerView: GADBannerView) { _adState.value = AdState.Loaded(bannerView) } override fun adView(bannerView: GADBannerView, didFailToReceiveAdWithError error: GADRequestError) { _adState.value = AdState.Failed(error.localizedDescription) } } bannerView.load(GADRequest()) } } // ios/src/iosMain/kotlin/com/yourproject/ui/AdComposeIos.kt actual @Composable fun PlatformBannerAd(adContent: Any?) { UIKitView( factory = { adContent as GADBannerView }, modifier = Modifier.fillMaxWidth() ) }
步骤4:在Common UI中使用
在common模块的任意Compose页面中,注入平台实现的AdManager即可调用广告组件:
@Composable fun HomeScreen(adManager: AdManager) { Column { // 其他页面内容 BannerAd(unitId = "your_ad_unit_id", adManager = adManager) } }
额外注意事项
- 依赖注入:可以用Koin等跨平台DI框架,在平台模块中提供
AdManager实例,common模块直接注入使用。 - 权限配置:Android需在
AndroidManifest.xml中添加Admob所需权限,iOS需在Info.plist中配置广告相关权限和说明。 - 生命周期管理:确保广告视图的生命周期与Compose页面同步,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

