How to show a banner ad in Jetpack Compose?

Viewed 3460

I just started learning about Jetpack Compose, and it's really nice the UI is so simplified. I am learning how implement all the XML views using Jetpack compose like RecyclerView (Lazycolumn) and so on.

I wonder how can I show an AdMob banner ad in Jetpack Compose. I know that we can use classic XML views using Interoperability APIs.

AndroidView(...) {
    ...
}

Is there a Compose way to implement Admob? or I can only use AndroidView to create a banner ad view programmatically.

3 Answers

You can show a banner ad in compose like this:

@Composable
fun AdvertView(modifier: Modifier = Modifier) {
    val isInEditMode = LocalInspectionMode.current
    if (isInEditMode) {
        Text(
            modifier = modifier
                .fillMaxWidth()
                .background(Color.Red)
                .padding(horizontal = 2.dp, vertical = 6.dp),
            textAlign = TextAlign.Center,
            color = Color.White,
            text = "Advert Here",
        )
    } else {
        AndroidView(
            modifier = modifier.fillMaxWidth(),
            factory = { context ->
                AdView(context).apply {
                    adSize = AdSize.BANNER
                    adUnitId = context.getString(R.string.ad_id_banner)
                    loadAd(AdRequest.Builder().build())
                }
            }
        )
    }
}

@Preview(showBackground = true)
@Composable
fun AdvertPreview() {
    AdvertView()
}

(Taken from my blog: https://blog.blundellapps.co.uk/using-admob-banner-ads-in-a-compose-layout/)

Here is an alternative way. You may use ComposeView in XML and make it work.

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.screens.MainActivity">
    
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/composeView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/adView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.gms.ads.AdView
        android:id="@+id/adView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        app:adSize="BANNER"
        app:adUnitId="ca-app-pub-xxxxxxxxxxxxx/xxxxxxxxxx"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt

setContentView(R.layout.activity_main).apply {
    findViewById<ComposeView>(R.id.composeView).setContent {               
        MyAppTheme {
            Surface(modifier = Modifier.fillMaxSize()){
                MyApp()
            }
        }
    }
}

Just adding a bit on the Blundell's answer. Since Admob 21.0.0, you would get the following error:

Val cannot be reassigned

So, instead of

    adSize = AdSize.BANNER

use

    setAdSize(AdSize.BANNER)

The whole AndroidiView in the Blundell's answer should look like:

    AndroidView(
        modifier = modifier.fillMaxWidth(),
        factory = { context ->
            AdView(context).apply {
                setAdSize(AdSize.BANNER)
                adUnitId = context.getString(R.string.ad_id_banner)
                loadAd(AdRequest.Builder().build())
            }
        }
    )
Related