2

I recently converted a screen to Jetpack Compose, and Ad team reported that they observe a significant fall in ad impressions. I wrapped AdManagerAdView in a Compose AndroidView and ads are loaded and shown on the screen successfully. But when I debug, I saw that onAdImpression was not called for ads implemented with Compose. To compare, I have another screen still in XML/recyclerview, and there onAdImpression is called right after onAdLoaded. My compose implementation is as follows:

Column(
        modifier = modifier.fillMaxWidth(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        val lifecycleState = LocalLifecycleOwner.current.lifecycle.observeAsState()
        val context = LocalContext.current
        val adView: AdManagerAdView = remember {
            AdManagerAdView(context)
        }
        when (lifecycleState.value) {
            Lifecycle.Event.ON_PAUSE -> {
                adView.pause()
            }

            Lifecycle.Event.ON_RESUME -> {
                adView.resume()
            }

            Lifecycle.Event.ON_DESTROY -> {
                adView.destroy()
            }

            else -> {}
        }

        AndroidView(
            factory = { context ->
                val unitId = AdUtils.buildAdUnitId(context, adMetadata)
                val params = AdUtils.buildAdParams(context, adMetadata)
                val builder = AdManagerAdRequest.Builder()
                params.keys.forEach { key ->
                    params[key]?.let { value ->
                        builder.addCustomTargeting(key, value)
                    }
                }
                adMetadata.advertisable?.url?.let {
                    builder.setContentUrl(it)
                }
                adView.apply {
                    setAdSizes(*adMetadata.adSizes)
                    adUnitId = unitId
                    importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
                    adListener = object : AdListener() {
                        override fun onAdLoaded() {
                            super.onAdLoaded()
                            Timber.d("ad loaded location ${adMetadata.location} postion ${adMetadata.position}")
                        }

                      override fun onAdFailedToLoad(adError: LoadAdError) {
                            super.onAdFailedToLoad(adError)
                            Timber.e("ad failed: message = ${adError.message}, cause = ${adError.cause}, response info = ${adError.responseInfo}")
                      }

                      override fun onAdImpression() {
                           super.onAdImpression()
                           Timber.d("onAdImpression location ${adMetadata.location} postion ${adMetadata.position}")
                      }
                    }
                    loadAd(builder.build())
                }
            },
            modifier = Modifier
                .width(Utils.findWidestAdSize(adMetadata.adSizes).dp)
                .height(Utils.findHighestAdSize(adMetadata.adSizes).dp)
        )
        Text(
            text = stringResource(id = R.string.adfree_ad_remove),
            color = TextGrey,
            textDecoration = TextDecoration.Underline,
            fontSize = 14.sp,
            fontFamily = FontFamily.Default,
            textAlign = TextAlign.Center,
            modifier = Modifier
                .clickable {
                    onAdFreeClicked()
                }
                .padding(vertical = 8.dp, horizontal = 16.dp)
        )
    }

This means although users see ads, impressions are not count and company is not paid for them!

How can I fix this problem?

Oya Canli
  • 1,996
  • 1
  • 15
  • 27

1 Answers1

2

I found this workaround proposed in Kotlin slack for NativeAdView in Jetpack Compose, https://kotlinlang.slack.com/archives/CJLTWPH7S/p1664105063510709, and I improved it a bit. Calling adView.rootView.requestLayout() from onAdLoaded solved the issue and I see now onAdImpression is called right after onAdLoaded.

           adListener = object : AdListener() {
                        override fun onAdLoaded() {
                            super.onAdLoaded()
                            Timber.d("ad loaded location ${adMetadata.location} postion ${adMetadata.position}")
                            adView.rootView.requestLayout()
                        }

                      override fun onAdFailedToLoad(adError: LoadAdError) {
                            super.onAdFailedToLoad(adError)
                            Timber.e("ad failed: message = ${adError.message}, cause = ${adError.cause}, response info = ${adError.responseInfo}")
                      }

                      override fun onAdImpression() {
                           super.onAdImpression()
                           Timber.d("onAdImpression location ${adMetadata.location} postion ${adMetadata.position}")
                      }
                    }
Oya Canli
  • 1,996
  • 1
  • 15
  • 27
  • I want to ask but not about the solution, because it is already worked as I expect. But the kotlin slack workspace, did they disable new joiner? Because it seems when I attempt to join that slack they said ' doesn’t have an account on this workspace.' – axelbrians Jun 19 '23 at 08:19