通过 Jetpack 撰写显示 AdMob Native 广告。但 onAdImpression 函数没有被调用

问题描述 投票:0回答:2

通过 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 函数就被调用了!

admob android-jetpack-compose native-ads
2个回答
1
投票

我找到了一个解决这个问题的方法。您需要拨打

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)

0
投票

我已经实现了上述解决方案,它在调试模式下工作得很好,但在发布版本中,它没有按预期工作

postDelayed(delayMillis) {
            val k = parent.findAndroidComposeViewParent()
            if (k != null) {
                k.requestLayout()
            } else {
                Log.i("TAG", "This should never happen")
            }
  }

它位于发布版本中的 else 条件内。任何帮助表示赞赏

© www.soinside.com 2019 - 2024. All rights reserved.