Keep asking for a banner after one does not fill - #643
Merged
Conversation
The AdView was loaded while still detached and only added to the container in onAdLoaded; on a failure the house ad took the container instead, so it never entered the hierarchy at all. The ad unit only refreshes a banner that is on screen, and nothing else asks again inside a session - showGoogleAds runs once per launch and refreshAds only on a configuration change - so one request that did not fill ended the session's advertising. The banner is now built once and kept for the life of the activity, beside the house ad, exactly one of them shown at a time. A configuration change lays the house ad out again and asks for a new banner only when the width really changed, as AdSlot does on iOS; nothing is torn out mid-request and the slot never collapses while one is in flight. A failure schedules its own ask, rescheduling before each request so one that never answers cannot end the chain, and onPause/onResume stop and start both it and the sdk's refresh. A refresh that does not fill keeps the ad already on screen, and paying for ad removal destroys the banner rather than leaving it attached and refreshing.
andiwand
force-pushed
the
keep-asking-after-a-banner-does-not-fill
branch
from
September 1, 2026 19:25
7113997 to
31f91dd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
showAdaptiveBanner()calledloadAd()on anAdViewthat was still detached from the view hierarchy and added it to the container only insideonAdLoaded. OnonAdFailedToLoadthe house ad took the container instead, so theAdViewnever entered the hierarchy at all.The ad unit's automatic refresh only runs for a banner that is on screen, and nothing else asks again inside a session:
showGoogleAds()runs once per launch andrefreshAds()only on a configuration change. One request that did not fill therefore ended the session's advertising until the user rotated the screen or came back to the app.What changes
One banner for the life of the activity. The
AdViewis built once and kept — no destroy on a configuration change, so nothing tears out a banner mid-request, the slot never collapses while a request is in flight, and there can be no secondAdViewto be stale against. A width that has not changed asks for nothing, which is whatAdSlot.swifton iOS already does; a keyboard opening or a rotation back is now free.Both views take turns. The banner and the house ad are in the container together, exactly one visible at a time. The house ad is never stacked over a live banner — an impression nobody can see is invalid traffic.
A failure asks again, rescheduling itself before each request so one that never comes back cannot end the chain and leave the slot as silent as before. The delay doubles up to the rate the unit refreshes at, so a slot that is never going to fill settles on what the sdk would have done anyway. The first ask is not shorter than 10s on purpose: the sdk throttles a burst of failed requests by itself, and an ask it answers never reaches the auction.
The lifecycle drives it.
onPause/onResumestop and restart both the retry and the sdk's own refresh, replacing ahasWindowFocus()check that never backed off while unfocused and stalled on any dialog that took focus — including the consent form.A refresh that does not fill keeps the ad already on screen instead of hiding a live one behind the house ad, which also let the sdk keep refreshing it.
Paying for ad removal destroys the banner.
removeAds()previously left it attached and refreshing for someone who had just bought their way out of it, and a late callback could still advance the house ad's stored rotation and report a house ad that was never displayed.The house-ad rotation moves when one is shown, not when one is built, so a session that never fills no longer walks through all three texts.
Notes
GONEAdViewacceptsloadAd()and deliversonAdLoaded— true for the sdk version pinned here, and the explicit retry means the fix does not depend on the sdk refreshing a hidden banner.IS_TESTING), so no automated test covers this path. Worth a manual pass on a device forced to no-fill.🤖 Generated with Claude Code