applovin_admob_sdk 1.0.14
applovin_admob_sdk: ^1.0.14 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.14 #
Bug Fixes #
- Fix #48:
_assertInitializedcrash — Changed from throwingStateErrorto returningboolwith a warning log. All 11 call sites now gracefully early-return when SDK is not yet initialized, preventing crashes during hot restart, early widget builds, or whenAdScreenState.initStateruns beforeAdManager().initialize().
1.0.13 #
New Feature: Navigator Key for SDK Dialogs #
AdManager.setNavigatorKey()— Register your app'sGlobalKey<NavigatorState>so the SDK can showAdLoadingDialogfrom lifecycle callbacks (e.g. App Open on resume) without aBuildContext.- Fix #47: App Open resume now shows
AdLoadingDialog— Previously used a silentFuture.delayed(1s)hack becauseshowAppOpenAdOnResume()runs from the lifecycle observer (noBuildContext). Now uses the registered navigator key to show the actual loading dialog with spinner, matching the same UX as interstitial and rewarded ad flows. - Fallback: if no navigator key is registered, the old 1s delay buffer is used.
Bug Fixes #
- Fix #44/45/46: App Open resume guards — Throttle check (
_lastFullscreenAdTime), dismiss timestamp guard (_lastFullscreenDismissTime), and 1s buffer all now work correctly together.
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)