ANTIGRAVITY LABJP
Articles/App Development
App Development/2026-06-30Advanced

The App Open Ad Antigravity Wrote for Me Fires Every Time I Return From My Own Paywall or Rewarded Video

Ask Antigravity to add an App Open ad and it shows one the instant you return from your own rewarded video or the Google Play purchase sheet — which also brushes against AdMob policy. Here is a foreground arbiter that records why the app came back, with working Kotlin and a verification matrix.

antigravity403admob17app-open-adandroid26monetization31

Premium Article

I wanted to add an App Open ad to one of the wallpaper apps I run as an indie developer, and I let Antigravity's agent write the implementation itself. The code it produced was a few dozen lines, it worked, and an ad appeared when I returned from the home screen. But testing on a device, an App Open ad also stacked on top the moment I finished my own rewarded video and came back. It fired right after I closed the purchase sheet too. From a reader's point of view that is the worst possible experience: "I watched an ad, and here is another ad."

I cannot blame the agent. The naive implementation of an App Open ad is "show one when the app returns to the foreground," and that is exactly what it wrote. What was missing was a single idea: don't ask only whether we returned, ask why we returned. Skip that, and you also run into AdMob's policy intent of not showing an App Open ad immediately after your own full-screen content.

Why "show on every foreground return" becomes an incident

An App Open ad is meant to fill the natural gap when a user leaves the app and comes back. The trouble is that, from an Android Activity's view, "the user went to the home screen and returned" and "the user returned from a full-screen ad I showed" both look like the same onStart.

The returns I had to suppress fell into four kinds.

  • Returning from my own interstitial or rewarded video (ad-on-ad stacking, policy trouble)
  • Closing the Google Play purchase sheet (an ad right after a purchase destroys trust)
  • Coming back from a Chrome Custom Tab opened for an external link
  • Cold start (the launch splash and the App Open ad collide)

The only return you should show on is when the user left and came back of their own accord. You simply cannot make that distinction from onStart alone.

The naive implementation an agent writes, and its blind spot

Ask Antigravity to "add an App Open ad" and you roughly get this skeleton: observe the whole process going foreground via ProcessLifecycleOwner, and call show() when it returns.

// The typical first draft an agent produces (this one misfires)
class MyApp : Application(), DefaultLifecycleObserver {
    private lateinit var appOpenAdManager: AppOpenAdManager
 
    override fun onCreate() {
        super<Application>.onCreate()
        MobileAds.initialize(this)
        appOpenAdManager = AppOpenAdManager(this)
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }
 
    // ★ The blind spot: it never asks WHY we came back to the foreground
    override fun onStart(owner: LifecycleOwner) {
        appOpenAdManager.showAdIfAvailable(currentActivity)
    }
}

This fires on onStart identically for a home return and for a return from a rewarded video. When I review an agent's output, I have learned to ask not "does it work" but "is this correct no matter which path brought us to the foreground." For App Open ads, that question always catches this.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Stop the double App Open ad that fired every time users returned from a rewarded video or purchase sheet, by identifying the reason for the foreground return
Understand why a naive ProcessLifecycleOwner ON_START implementation causes AdMob policy trouble and churn, and design the suppression conditions yourself
Drop a Kotlin implementation into your own app that separates cold start, full-screen ads, billing flows, and external-link returns
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

App Dev2026-06-25
An Agent Granted 'Watch an Ad to Unlock a Wallpaper' Entirely Client-Side — Re-Verifying Reward Grants with AdMob SSV
I asked an Antigravity agent to wire up 'watch a rewarded ad to unlock a wallpaper,' and it returned an implementation that wrote the unlock flag client-side only. Here is why that is not enough, how I re-verified the reward grant with AdMob server-side verification (SSV), and how I stopped double grants too.
App Dev2026-06-21
The Back Button Showed an Interstitial Sometimes, Not Others — Rewriting Nested ifs Into a List of Independent Guards
Interstitial display on back press was unstable because nested if statements hid the priority between conditions. Here is how I split it into reason-returning guards and generated tests from a decision table.
App Dev2026-06-19
I Started the Ad SDK Before Asking for ATT — the Init-Order Bug That Quietly Lowered First-Session eCPM
When I rolled AdMob mediation out to four iOS apps, only the very first session showed weaker ad revenue. The cause was the order between the ATT prompt and MobileAds initialization. Here is why the order matters, plus how I had Antigravity audit the init sequence across all four apps.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →