通过 Jetpack Compose 显示原生广告。以下是如何使用 Jetpack Compose 展示原生广告的示例:
import android.view.LayoutInflater
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdLoader
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.nativead.MediaView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
@Composable
fun MyNativeAdView(adUnitId: String) {
val context = LocalContext.current
val nativeAdFlow = remember { mutableStateOf<NativeAd?>(null) }
val adLoader = remember {
AdLoader.Builder(context, adUnitId)
.forNativeAd { nativeAd ->
nativeAdFlow.value = nativeAd
}
.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(p0: LoadAdError) {
super.onAdFailedToLoad(p0)
println("AdmobNativeAd onAdFailedToLoad $p0")
}
override fun onAdLoaded() {
super.onAdLoaded()
println("AdmobNativeAd onAdLoaded")
}
override fun onAdImpression() {
super.onAdImpression()
println("AdmobNativeAd onAdImpression")
// FIXME Here is not being executed
}
})
.build()
}
LaunchedEffect(key1 = Unit, block = {
adLoader.loadAd(AdRequest.Builder().build())
})
AndroidView(
factory = { context ->
LayoutInflater.from(context)
.inflate(R.layout.native_ad_admob_medium, null) as NativeAdView
},
modifier = Modifier.fillMaxWidth(),
update = { adView ->
// Find the view IDs defined in the XML layout file
val adIconView = adView.findViewById<ImageView>(R.id.ad_app_icon)
val adHeadlineView = adView.findViewById<TextView>(R.id.ad_headline)
val adBodyView = adView.findViewById<TextView>(R.id.ad_body)
val adCallToActionView = adView.findViewById<Button>(R.id.ad_call_to_action)
val adAdvertiserView = adView.findViewById<TextView>(R.id.ad_flag)
val adMediaView = adView.findViewById<MediaView>(R.id.ad_media)
// Register the view IDs with the native ad view.
adView.headlineView = adHeadlineView
adView.bodyView = adBodyView
adView.callToActionView = adCallToActionView
adView.iconView = adIconView
adView.advertiserView = adAdvertiserView
adView.mediaView = adMediaView
// Populate the native ad view.
val nativeAd = nativeAdFlow.value
nativeAd?.let {
adIconView.setImageDrawable(nativeAd.icon?.drawable)
adHeadlineView.text = nativeAd.headline
adBodyView.text = nativeAd.body
adCallToActionView.text = nativeAd.callToAction
adAdvertiserView.text = nativeAd.advertiser
adMediaView.mediaContent = nativeAd.mediaContent
adMediaView.setImageScaleType(ImageView.ScaleType.CENTER_CROP)
// Register the native ad view with the native ad object.
adView.setNativeAd(nativeAd)
}
}
)
}
只需在 UI 层次结构中调用 MyNativeAdView Composable 函数即可在 UI 中使用它。
@Composable
fun MyScreen() {
MyNativeAdView("ca-app-pub-3940256099942544/2247696110")
}
原生广告展示时,onAdImpression函数并没有被调用。 如果现在我们将屏幕切换到启动器屏幕并立即返回。然后 onAdImpression 函数就被调用了!
我找到了一个解决这个问题的方法。您需要拨打
requestLayout
上的 AndroidComposeView
。我正在做的是将这些辅助方法称为 update
的 AndroidView
部分的最后一个方法。
private fun View.requestLayoutWithDelay(delayMillis: Long) {
post {
val t = parent.findAndroidComposeViewParent()
if (t == null) {
postDelayed(delayMillis) {
val k = parent.findAndroidComposeViewParent()
if (k != null) {
k.requestLayout()
} else {
Log.i("TAG", "This should never happen")
}
}
} else {
t.requestLayout()
}
}
}
private fun ViewParent?.findAndroidComposeViewParent(): ViewParent? = when {
this != null && this::class.java.simpleName == "AndroidComposeView" -> this
this != null -> this.parent.findAndroidComposeViewParent()
else -> null
}
问题中提供的代码应用示例用法:
...
adView.setNativeAd(nativeAd)
adView.requestLayoutWithDelay(400)
我已经实现了上述解决方案,它在调试模式下工作得很好,但在发布版本中,它没有按预期工作
postDelayed(delayMillis) {
val k = parent.findAndroidComposeViewParent()
if (k != null) {
k.requestLayout()
} else {
Log.i("TAG", "This should never happen")
}
}
它位于发布版本中的 else 条件内。任何帮助表示赞赏