applovin_admob_sdk 1.0.12
applovin_admob_sdk: ^1.0.12 copied to clipboard
Dual-provider ad SDK for Flutter (AdMob + AppLovin MAX) with built-in safety throttle, VIP bypass, RouteAware banner lifecycle management, and animated TopToast feedback.
1.0.12 #
Memory Leaks #
- Fix N:
SimpleEventBuslistener accumulation — AddedclearAll()method, called fromdestroy()to prevent closure-held widget tree leaks. - Fix O:
WidgetsBindingObservernot re-added afterdestroy()+ reinit — Lifecycle observer now re-adds itself oninitialize()via_ensureObserverAdded(). Without this, App Open on resume and all lifecycle features silently stopped working after reinit.
Invalid Traffic #
- Fix J: Banner impressions now tracked for CTR —
recordBannerImpression()counts initial banner loads in_totalImpressions, so CTR-based fraud detection covers banner clicks too. - Fix L: Suspicious violation count persists across days — No longer reset at midnight. Progressive cooldown (30min → 24h) properly escalates for repeat offenders.
Fill Rate #
- Fix R/T: Periodic ad retry timer (every 5 min) — Proactively refills empty App Open, Interstitial, and Rewarded slots. Also detects expired AdMob App Open ads (>4 hours) and reloads them.
Bug Fixes #
-
Fix U:
SafeLogger.eno longer logs in release — AddedkDebugModeguard to prevent internal SDK info leaking to device logs in production. -
Fix V:
_isFirstAdLoadTriggerednow resets indestroy()— Without this, Inter + Rewarded ads were never preloaded after reinit because the load chain was skipped. -
Fix W:
AdConfig.logLevelnow wired toSafeLogger— Previously the config field was ignored; nownoneandwarninglevels suppress verbose logs. -
Fix Y: AdMob App Open
onAdFailedToShowreturnsfalse— Was returningtrue(implying ad was shown). Now correctly returnsfalseand triggers reload. -
Bug fix (F): No ad reload after AppLovin display fail —
onAdDisplayFailedCallbackfor App Open, Interstitial, and Rewarded now callsloadAppOpenAd/loadInterstitial/loadRewardedAdafter failure, so a fresh ad is preloaded for the next attempt. -
Bug fix (G): App Open display-fail returned
true—_onAppOpenDismissed?.call(true)changed tocall(false). The caller now correctly knows the ad was NOT shown. -
Bug fix (H):
canShowInterstitial/canShowRewardedAddidn't check dialog state — Both pre-check methods now returnfalsewhenAdLoadingDialog.isShowing == true, preventing a second ad flow from starting while the first dialog buffer is still active. -
Bug fix (I):
AdSafetyConfig._isColdStartnot reset ondestroy()+ reinit — AddedAdSafetyConfig.resetForReinit()which resets cold start flag, session state, timestamps, and suspicious pause. Called fromAdManager.destroy(). -
Bug fix (A): AdMob Interstitial early lock not released on null-ad —
_showInterstitialAdmobnow releases_isInterstitialShowingwhen the cached ad is null, preventing permanent interstitial blockage. -
Bug fix (B):
showRewardedAdmissing early concurrent guard — Added_isRewardedShowingearly lock at the top ofshowRewardedAd()(mirrors 1.0.9 interstitial fix), preventing double rewarded flows from double-tap. -
Bug fix (C): AdMob Rewarded early lock not released on null-ad —
_showRewardedAdmobnow releases_isRewardedShowingwhen the cached ad is null. -
Bug fix (D): App Open timeout fires while ad is still showing — Timeout (10s) now checks
!_isMaxAppOpenShowingbefore force-callingonAdDismiss(false), preventing the callback firing mid-ad (e.g. during a long video). -
Bug fix (E): Redundant
_isRewardedShowingcheck in_showRewardedAppLovin— Removed duplicate guard now handled by the early lock inshowRewardedAd(). -
Bug fix: Concurrent dialog guard (
AdLoadingDialog) — Added_isShowingstatic flag. IfshowAdBufferis called a second time while a dialog is already showing (double-tap), the duplicate call immediately invokesonCompletewithout pushing a second dialog. Previously, two stacked dialogs causednavigator.pop()to dismiss the wrong one. -
Bug fix: Early interstitial lock (
AdManager.showInterstitial) —_isInterstitialShowing = trueis now set at the START ofshowInterstitial(), before the 1s dialog buffer. Previously, a double-tap during the buffer could pass thecanShowInterstitial()check twice and show two dialogs. -
Bug fix: AppLovin App Open timeout fallback —
_showAppOpenAdAppLovinnow starts a 10-second timer. If no AppLovin callback fires within 10s (AppLovin internal loading hang),onAdDismiss(false)is force-called to unblock the splash screen's navigation flow. -
Bug fix: Loading dialog hang (root cause — real fix)
- Root cause:
AdLoadingDialogcapturedNavigator.of(context)AFTER the async delay, then guardedpop()withcontext.mounted. If the parent screen was disposed during the 1s buffer (e.g., user navigated back),context.mounted == false→pop()was skipped → dialog stayed on screen forever with no one to dismiss it - Fix: Capture
NavigatorStateviaNavigator.of(context, rootNavigator: true)BEFORE theawaitdelay.NavigatorStateis owned by the root navigator widget (not the screen) and outlives any screen disposal. The dialog is now always dismissed regardless ofcontext.mounted - Note: version 1.0.7 partially addressed related symptoms (rewarded skip callback orphan, safety re-check logging) but did not fix the actual dismissal race condition
- Root cause:
-
Bug fix: Loading dialog hang — Fixed 3 root causes that caused
AdLoadingDialogto get stuck on screen permanently:- AppLovin Rewarded skip bug (critical):
onAdHiddenCallbackwas not calling_pendingRewardedDoneFlow(false)when user closed the rewarded ad without watching it fully. This left the callback orphaned and the loading dialog visible indefinitely - Safety re-check log gap:
showInterstitial/showRewardedAdsafety failures after the 1s dialog buffer now log the reason (safetyResult.reason) and explicitly guaranteeonDoneFlow/onEarnedRewardis always called - AdLoadingDialog logging: Added
SafeLoggerthroughout — pop errors (context detached) are now caught and logged instead of crashing silently
- AppLovin Rewarded skip bug (critical):
-
Replaced real AppLovin credentials in example app with
YOUR_*placeholders — prevents accidental credential exposure in published package -
Merged example app into a single
main.dartfile for simplicity -
Completely rewrote README with detailed step-by-step integration guide (Android setup, iOS setup, AdMob/AppLovin setup, 7-step guide, ad types reference, AdConfig reference, safety layer table, VIP bypass, TopToast, troubleshooting)
-
Fixed double
loadAppOpenAdin-flight guard for AppLovin provider —_isAppOpenLoadingis now set/reset in_loadAppOpenAdAppLovinand its loaded/failed callbacks, preventing duplicate requests and callback overwrites that broke the splash App Open flow -
Fixed hard cap timer not being cancelled before
showAppOpenAdis called in splash — prevents force-navigation while an ad is actively displaying (example + WiFi splash screens) -
Replaced all
debugPrintinAdScreenRouteLoggerwithSafeLogger.d— consistent logging across the entire SDK -
Bumped dependencies:
google_mobile_ads: ^7.0.0,shared_preferences: ^2.5.4,connection_notifier: ^3.0.0,flutter_lints: ^6.0.0 -
Renamed package from
ad_sdktoapplovin_admob_sdk -
AdConfignow supportsadNotReadyMessageandadLoadingMessagefor localizable UI strings -
showRewardedAdauto-showsTopToastwithadNotReadyMessagewhen no ad is available — callers no longer need to show their own feedback -
AdLoadingDialogusesadLoadingMessagefrom config instead of hardcoded'Loading...' -
AdManagerexposes publicconfiggetter
1.0.1 #
- Added
TopToast— animated, glassmorphism top-center toast widget (overlay-based, no Scaffold needed) showRewardedAd: changed to hard gate —onEarnedReward(false)when ad unavailable (caller shows user feedback)- Fixed
_hasPlaceholderIds()logic bug in example app splash screen
1.0.0 #
- Initial release
- Dual-provider support: AdMob (google_mobile_ads) and AppLovin MAX (applovin_max)
- Ad types: App Open, Banner, Interstitial, Rewarded
- 12-measure AdSafety layer: throttle, session/hourly/daily caps, CTR fraud, progressive cooldown
- RouteAware banner with auto pause/resume on navigation
- VIP device bypass via GAID list
- Shimmer loading placeholder for banner
- AdLoadingDialog buffer before fullscreen ads
- Provider-agnostic AdScreen base class (no external state manager required)