DEV Community

Trinadh Thatakula
Trinadh Thatakula

Posted on

🚀 Jetpack Compose + AdMob Made Easy: Modern, Reusable Kotlin Composables for Android Developers

Bringing Google AdMob ads into your Jetpack Compose app doesn’t have to be a struggle. I’ve assembled a suite of reusable, straightforward composable functions to help you quickly integrate Banner, Adaptive Banner, Collapsible Banner, Interstitial, and Native Ads—all with the modern, declarative style of Compose and best practices for MVVM.

Check out the original Gist for copy-paste code! Here’s a practical, dive-right-in guide for your next Android project.

Why Compose Your Ads This Way?

  • Uncluttered, Idiomatic Kotlin: Pure Jetpack Compose, leveraging state and side effects.
  • Reusable & Modular: Just drop the composable you need into any screen.
  • Best Practices Baked In: Lifecycle awareness, error handling, and MVVM-friendly APIs.
  • Ready for Production: Supports all major AdMob formats and follows Google’s latest SDK updates.

đź›  Prerequisites

  • Android app using Jetpack Compose
  • Google AdMob account + registered app & ad unit IDs
  • Your AdMob App ID in AndroidManifest.xml:
<manifest>
    <application>
        <!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="YOUR_ADMOB_APP_ID"/>
    </application>
</manifest>

Enter fullscreen mode Exit fullscreen mode

📦 Dependencies

Add Google Mobile Ads SDK to your build.gradle:

implementation("com.google.android.gms:play-services-ads:23.0.0")
Enter fullscreen mode Exit fullscreen mode

🖼️ Banner, Adaptive, & Collapsible Ads

Composable functions for flexible ad placement:

@Composable
fun AdMobBanner(
    unitIdRes: Int,
    adSize: AdSize = AdSize.FULL_BANNER,
    modifier: Modifier = Modifier
) { /* ... */ }

@Composable
fun AdMobAdaptiveBanner(
    unitIdRes: Int,
    margin: Dp = 0.dp,
    /* ... */
) { /* ... */ }

@Composable
fun AdMobCollapsableBanner(
    unitIdRes: Int,
    adSize: AdSize = AdSize.FULL_BANNER,
    collapseDirection: CollapseDirection = CollapseDirection.TOP,
    /* ... */
) { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

🕹 Interstitial Ads (Full-Screen)

Integrate rewarding ad breaks with a simple loader and callback flow:

fun Activity.loadFullScreenAd(
    unitIdRes: Int,
    onAdLoaded: (InterstitialAd) -> Unit,
    onAdFailedToLoad: (LoadAdError) -> Unit,
    onAdDismissed: () -> Unit
)
Enter fullscreen mode Exit fullscreen mode

Load the ad after the previous one is dismissed for smooth user experience.

🦄 Native Ads

For a more custom look, use the composable that auto-loads and lays out the ad components:

@Composable
fun NativeAdComposable(
    adUnitId: String,
    modifier: Modifier = Modifier
)
Enter fullscreen mode Exit fullscreen mode

Tip: To bind native ad views correctly, define IDs in res/values/ids.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item type="id" name="ad_headline" />
    <item type="id" name="ad_body" />
    <item type="id" name="ad_call_to_action" />
    <item type="id" name="ad_media" />
    <item type="id" name="ad_icon" />
</resources> 




Enter fullscreen mode Exit fullscreen mode

đź§© Usage Example

Compose a sample ad screen in seconds:

@Composable
fun AdScreen() {
    val context = LocalContext.current as Activity
    var interstitialAd by remember { mutableStateOf(null) }
    // Load and display ads...
    AdMobAdaptiveBanner(unitIdRes = R.string.your_banner_ad_unit_id)
    NativeAdComposable(adUnitId = stringResource(R.string.your_native_ad_unit_id))
    Button(onClick = { interstitialAd?.show(context) }, enabled = interstitialAd != null) {
        Text("Show Interstitial Ad")
    }
}
Enter fullscreen mode Exit fullscreen mode

⚡ Pro Tips & Considerations

  • Use Test IDs during development to avoid violating AdMob policies.
  • Strategic Placement: Don’t overwhelm users—show interstitial ads only at natural app transitions.
  • Handle Errors Gracefully: Hide ad containers or swap in placeholders if loading fails.
  • Lifecycle-aware: Release resources as shown.

📚 Full Code & Deep Dives

  • See the full Gist for all code.
  • Tweak, contribute, and ask questions in the comments!

Compose modern, clean mobile apps and monetize faster—happy coding! 🎉

Did you find this helpful, or want to see support for rewarded ads? Let me know in the comments!

[1] https://gist.github.com/trinadhthatakula/e4db4a7219f6ef6d066e109015edc44e

Top comments (0)