Releases: i2hammad/AdManageKit
v3.4.4
Release Notes - v3.4.4
Release Date: March 13, 2026
Overview
v3.4.4 fixes native ad show rate issues across all native ad views (NativeBannerSmall, NativeBannerMedium, NativeLarge, NativeTemplateView) and adds null safety to RewardedAdManager. The root cause of low show rates was parent container visibility not being restored after a previous ad load failure — children were set to VISIBLE but remained invisible because their parent was still GONE.
What's New
Native Ad Show Rate Fix (All Views)
After a failed ad load, error callbacks hide the parent container (binding.root, binding.adContainer, or binding.adUnit). On subsequent loads, child views were set to VISIBLE but remained invisible because the parent was still GONE.
Before: Error → parent GONE → next load sets children VISIBLE → ad invisible (parent still GONE)
After: loadAd() now resets parent container visibility to VISIBLE before loading. displayAd() also ensures parent visibility is restored for cached/waterfall ad display paths.
Affected views:
- NativeBannerSmall:
binding.rootnow reset inloadAd()anddisplayAd() - NativeBannerMedium:
binding.adContainernow reset inloadAd(),displayAd(),displayCachedAdSafely(), and waterfall success path - NativeLarge:
binding.adUnitnow reset inloadAd()andbinding.rootindisplayAd() - NativeTemplateView:
binding.rootnow reset inloadAd()anddisplayAd()
NativeBannerMedium: Synchronous setNativeAd()
populateNativeAdView() was deferring setNativeAd() via nativeAdView.post {}, which risked the call never executing if the view was detached. Changed to a synchronous call for reliable impression registration.
NativeBannerMedium: Shimmer Overlap Fix
When displaying cached or waterfall ads via displayCachedAdSafely(), the shimmer loading animation was not hidden, causing it to overlap the actual ad content. Shimmer is now explicitly set to GONE in all display paths.
RewardedAdManager Null Safety
RewardedAdManager.adUnitId was a lateinit var that would crash with UninitializedPropertyAccessException if any method was called before initialize(). Changed to var adUnitId: String = "" with .isEmpty() guards on all 5 public entry points:
loadRewardedAd(context)loadRewardedAd(context, callback)loadRewardedAdWithTimeout(context, timeout, callback)showAd(activity, callback)preload(context)
Each guard logs a warning and returns the appropriate callback (e.g., onAdFailedToLoad() or onAdDismissed()).
Empty adUnitId Guards (All Native Views)
All native ad views (NativeBannerSmall, NativeBannerMedium, NativeLarge, NativeTemplateView) now use var adUnitId: String = "" instead of lateinit var and guard against empty ad unit IDs in their load methods.
Full Changelog
- Fixed: Low native ad show rate caused by parent container visibility not restored after previous load failure (NativeBannerSmall, NativeBannerMedium, NativeLarge, NativeTemplateView)
- Fixed:
NativeBannerMedium.populateNativeAdView()deferredsetNativeAd()viapost {}— changed to synchronous call for reliable impression registration - Fixed: Shimmer overlay on cached/waterfall ads in
NativeBannerMedium.displayCachedAdSafely() - Fixed:
RewardedAdManagercrash when methods called beforeinitialize()—lateinit var adUnitIdchanged to empty string default with guards - Fixed:
NativeBannerSmall,NativeLarge,NativeTemplateViewcrash whenadUnitIdaccessed before assignment —lateinitchanged to empty string default - Added: Empty
adUnitIdvalidation with warning logs and appropriate callback responses across all native views andRewardedAdManager
Installation
// Core modules
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.4.4'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.4.4'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.4.4'
// Jetpack Compose support
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.4.4'
// Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.4.4'Full Changelog: v3.4.3...v3.4.4
v3.4.3
Release Notes - v3.4.3
Release Date: March 6, 2026
Overview
v3.4.3 fixes several race conditions in AppOpenManager that caused duplicate ad loads, missed ad shows, and auto-navigation on splash screens — with both waterfall and non-waterfall (single-provider) setups.
What's New
Duplicate Ad Load Prevention
When multiple code paths (e.g. onStart background preload and splash fetchAd) triggered concurrent waterfall loads, the same ad could be fetched twice. fetchViaWaterfall(callback, timeout) now checks if a load is already in progress and attaches to it instead of starting a duplicate.
- If a dialog-based fetch is running, the callback is attached to
dialogFetchCallback - If a background preload is running (excluded-activity preload), the callback is attached to
pendingFetchCallbackwith proper timeout handling - Works for both waterfall (
fetchViaWaterfall) and non-waterfall (fetchAdWithRetry) paths
Splash Auto-Navigation Fix
When the splash screen's fetchAd callback attached to an in-progress background preload, orphaned timeouts could fire onFailedToLoad after the ad had already loaded and shown — causing the splash to navigate away while the ad was still displayed.
Before: Multiple fetchViaWaterfall(callback, timeout) calls each created timeouts, but only the last was tracked. Earlier timeouts fired stale callbacks.
After: Previous pending timeouts are cancelled before creating new ones. All completion paths (load, fail, timeout) clear pendingFetchCallback state.
Resume App Open Ad Show After Auto-Reload
showAdIfAvailable() was blocked by isLoading from a background auto-reload preload, preventing app open ads from showing on resume.
Before: After dismissing an app open ad, appOpenAutoReload triggered fetchViaWaterfall() which set isLoading=true. The immediate onStart → showAdIfAvailable() saw isLoading=true and skipped.
After: showAdIfAvailable() only skips for dialog-based fetches (isFetchingWithDialog), not background preloads. Background preloads don't block ad display since they're non-interactive.
Comprehensive Ad Lifecycle Logging
All paths in AppOpenManager now emit AdDebugUtils.logEvent events:
loading: Logged when any ad load request starts (fetchAdWithRetry,fetchAd(callback),showAdWithWelcomeDialog,fetchAndShowFresh)showCachedAd: Logged when a cached ad is about to be shown (both regular and forced paths)onAdLoaded/onFailedToLoad: Already present, now added to dialog-based and waterfall paths that were previously missing
Full Changelog
- Fixed: Duplicate ad loads on cold start when
onStartpreload and splashfetchAdrun concurrently (both waterfall and non-waterfall) - Fixed: Splash auto-navigation caused by orphaned
pendingFetchTimeoutRunnablefiring staleonFailedToLoadcallbacks - Fixed:
showAdIfAvailable()blocked by background auto-reload preload, preventing app open ads on resume - Fixed: ON_DEMAND strategy cold start no longer triggers automatic ad load from
onStart(explicitfetchAd/forceShowhandles it) - Fixed: Hot-start duplicate loads when returning to SplashActivity
- Added:
pendingFetchCallbackmechanism to attach splash callbacks to in-progress background preloads - Added:
hasBeenBackgroundedflag to distinguish cold start from resume for ON_DEMAND strategy - Added:
loadinglog event to all ad load start paths (background preload, dialog fetch, fresh fetch, timeout fetch) - Added:
showCachedAdlog event when cached ads are shown (regular and forced paths) - Added:
AdDebugUtils.logEventcalls to all previously missing load/failure paths inAppOpenManager
Installation
// Core modules
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.4.3'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.4.3'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.4.3'
// Jetpack Compose support
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.4.3'
// Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.4.3'Full Changelog: v3.4.2...v3.4.3
v3.4.2
Release Notes - v3.4.2
Release Date: March 6, 2026
Overview
v3.4.2 improves App Open ad reliability by integrating autoRetryFailedAds support and preserving late-loading ads that arrive after a timeout.
What's New
App Open Ads: autoRetryFailedAds Support
App open ads now respect AdManageKitConfig.autoRetryFailedAds, matching the behavior already present in interstitial, rewarded, and native ads. When enabled, failed app open ad loads are automatically retried with exponential backoff via AdRetryManager.
Previously, AppOpenManager had its own hardcoded retry logic that always ran regardless of the autoRetryFailedAds setting. This has been unified with the centralized retry system.
AdManageKitConfig.apply {
autoRetryFailedAds = true // Now respected by app open ads
maxRetryAttempts = 3 // Used instead of hardcoded value
}Affected paths:
- Background preload (
fetchAd()/fetchAdWithRetry()) — now gated on config - Waterfall preload (
fetchViaWaterfall()) — retry added on failure
App Open Ads: Late-Loading Ad Preservation
When an app open ad loads after the timeout has already fired, the ad is now cached for later use instead of being silently discarded.
Before: If fetchAd(timeout=8000) timed out at 8s but the ad loaded at 9s, the ad was thrown away.
After: The ad is stored in appOpenAd and available for the next showAdIfAvailable() call. The original timeout callback still fires normally (no double-callback).
Full Changelog
- Fixed:
AppOpenManagernow respectsAdManageKitConfig.autoRetryFailedAds(was always retrying with hardcoded values) - Fixed:
AppOpenManagernow usesAdManageKitConfig.maxRetryAttemptsinstead of hardcoded retry limit - Fixed:
AppOpenManagerretry now usesAdRetryManagerfor consistent exponential backoff across all ad types - Added: Auto-retry on failure for waterfall-based app open ad preloading
- Improved: App open ads that load after timeout are cached for later use instead of discarded
- Deprecated:
AppOpenManager.updateRetryConfiguration()— useAdManageKitConfigproperties directly
Installation
// Core modules
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.4.2'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.4.2'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.4.2'
// Jetpack Compose support
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.4.2'
// Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.4.2'Full Changelog: v3.4.1...v3.4.2
v3.4.1
Release Notes - v3.4.1
Release Date: February 25, 2026
Overview
v3.4.1 adds product metadata and billing period APIs to AppPurchase, allowing you to display Play Console localized product titles, descriptions, trial info, and billing periods directly in your UI without manual translation.
What's New
Product Metadata APIs
New methods on AppPurchase expose the localized product information configured in the Google Play Console:
val billing = AppPurchase.getInstance()
// Title with app name appended (e.g. "Monthly Premium (My App)")
val title = billing.getProductTitle("premium_monthly")
// Clean name without app name (e.g. "Monthly Premium")
val name = billing.getProductName("premium_monthly")
// Description from Play Console
val description = billing.getProductDescription("premium_monthly")
// Raw ProductDetails for anything not covered above
val details = billing.getProductDetails("premium_monthly")All methods check subscriptions first, then fall back to in-app products. Returns null if the product hasn't been loaded yet.
Why this matters: getProductTitle() and getProductName() return Google-localized strings based on the user's device language. You no longer need to maintain local translations for product names — set them once in Play Console, and the library returns the correct localization automatically.
Free Trial Detection
Detect whether a subscription offers a free trial and retrieve its duration:
val billing = AppPurchase.getInstance()
if (billing.hasFreeTrial("premium_monthly")) {
val trialPeriod = billing.getFreeTrialPeriod("premium_monthly")
// trialPeriod = "P3D" (3 days), "P7D" (7 days), "P1M" (1 month), etc.
showTrialBadge("Free trial: $trialPeriod")
}Trial detection works by scanning offer phases for a zero-price phase with finite recurrence — matching Google's standard free trial offer structure.
Billing Period
Get the subscription's billing cycle duration:
val period = AppPurchase.getInstance().getBillingPeriod("premium_monthly")
// "P1M" = monthly, "P1Y" = yearly, "P1W" = weekly, "P3M" = quarterlyReturns the billing period of the last pricing phase from the last subscription offer, which represents the regular billing cycle after any introductory phases.
API Summary
| Method | Returns | Example |
|---|---|---|
getProductTitle(productId) |
String? |
"Monthly Premium (My App)" |
getProductName(productId) |
String? |
"Monthly Premium" |
getProductDescription(productId) |
String? |
"Unlock all premium features" |
getProductDetails(productId) |
ProductDetails? |
Raw object |
hasFreeTrial(productId) |
boolean |
true / false |
getFreeTrialPeriod(productId) |
String? |
"P7D" |
getBillingPeriod(productId) |
String? |
"P1M" |
Example: Dynamic Paywall UI
val billing = AppPurchase.getInstance()
// Display product info from Play Console (auto-localized)
titleTextView.text = billing.getProductName("premium_monthly")
descriptionTextView.text = billing.getProductDescription("premium_monthly")
priceTextView.text = billing.getPrice("premium_monthly")
// Show trial badge if available
if (billing.hasFreeTrial("premium_monthly")) {
trialBadge.visibility = View.VISIBLE
trialBadge.text = "Free trial available"
}
// Show billing period
val period = billing.getBillingPeriod("premium_monthly")
periodTextView.text = when (period) {
"P1M" -> "Billed monthly"
"P1Y" -> "Billed yearly"
"P1W" -> "Billed weekly"
else -> ""
}Installation
// Core modules
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.4.1'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.4.1'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.4.1'
// Jetpack Compose support
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.4.1'
// Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.4.1'Full Changelog
- New:
AppPurchase.getProductTitle(productId)— Play Console localized title with app name - New:
AppPurchase.getProductName(productId)— Clean product name without app name - New:
AppPurchase.getProductDescription(productId)— Play Console product description - New:
AppPurchase.getProductDetails(productId)— RawProductDetailsobject access - New:
AppPurchase.hasFreeTrial(productId)— Check if subscription has a free trial offer - New:
AppPurchase.getFreeTrialPeriod(productId)— Get trial period in ISO 8601 format - New:
AppPurchase.getBillingPeriod(productId)— Get subscription billing period
Full Changelog: v3.4.0...v3.4.1
v3.4.0
Release Notes - v3.4.0
Release Date: February 17, 2026
Overview
v3.4.0 fixes two AppOpenManager correctness issues — a ~50% splash show-rate bug and a tablet layout regression — and consolidates all improvements introduced in the 3.3.x series (multi-provider waterfall, Yandex Ads, app open ad callback improvements, and adaptive banner sizing).
What's New
Fix: App Open Ad ~50% Show Rate on Splash
forceShowAdIfAvailable() was silently skipping the ad roughly half the time when no cached ad was available. The fix closes a race condition between the lifecycle-driven showAdIfAvailable() and the explicit splash call.
Root cause: On every foreground return, AppOpenManager.onStart() calls showAdIfAvailable(), which — when no cached ad exists — starts a dialog-based ad fetch with a null callback. If forceShowAdIfAvailable() was then called (e.g. from onResume()), it found the dialog already showing and immediately fired onNextAction() via the guard, causing navigation to proceed before the ad could be shown. The ad would eventually load and appear over the wrong screen with no callback wired up.
Why ~50%: Roughly half of app opens have a cached ad (background prefetch from onStop) and half don't. Cached-ad opens worked fine; no-cache opens always missed.
Fixes applied (AppOpenManager.kt):
-
showAdIfAvailable()now guards againstisFetchingWithDialog— preventsonStart()'s automatic path from starting a competing dialog fetch whenforceShowAdIfAvailable()has already started one. -
Added
dialogFetchCallbackfield — the callback for the current dialog-based fetch is stored as a mutable field rather than only in a captured local variable, allowing it to be replaced at any time before the ad loads. -
forceShowAdIfAvailable()takes over an in-progress fetch — when called whileisFetchingWithDialogistrue, it replacesdialogFetchCallbackwith the splash callback. The ongoing load then delivers its result (ad shown / failed / timed out) to the correct caller.
// Works correctly regardless of whether the ad is cached or loading
appOpenManager.forceShowAdIfAvailable(this, object : AdManagerCallback() {
override fun onNextAction() { navigateToMain() } // always fires
override fun onAdTimedOut() { navigateToMain() } // timeout path
override fun onFailedToLoad(error: AdKitError?) { navigateToMain() } // failure path
})No API changes — existing integration code is unaffected.
Fix: Native Large Ad Tablet Layout
Fixed a layout rendering issue in the native large ad view on tablet-sized screens (sw600dp+).
Root cause: layout_native_large.xml (sw600dp) used LinearLayout as the root container, which caused incorrect measurement and layout-pass behaviour for the native ad content on larger screens.
Fix: Container changed from LinearLayout to FrameLayout, matching the intended single-child wrapping semantics.
This change is transparent — no API or integration changes are required.
Summary of 3.3.x Series (Included in This Release)
Multi-Provider Waterfall & Yandex Ads (3.3.8)
A new provider abstraction layer allows multiple ad networks to work as a fallback chain with zero changes to existing ad-loading code.
// Register providers once (e.g. in Application.onCreate)
AdProviderConfig.registerProvider(AdProvider.ADMOB, AdMobProviderRegistration())
AdProviderConfig.registerProvider(AdProvider.YANDEX, YandexProviderRegistration())
// Configure waterfall chains per ad type
AdProviderConfig.setInterstitialChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setAppOpenChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setBannerChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setNativeChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setRewardedChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))See Multi-Provider Waterfall and Yandex Integration for the full guide.
App Open Ad Callback Improvements (3.3.9)
AdManagerCallback now properly fires failure and timeout callbacks for app open ads, and the welcome dialog is always dismissed before any callback fires.
appOpenManager.forceShowAdIfAvailable(activity, object : AdManagerCallback() {
override fun onNextAction() { navigateNext() }
override fun onFailedToLoad(error: AdKitError?) { /* load failure */ }
override fun onAdTimedOut() { /* timeout */ }
})Adaptive Full-Width Banner in Waterfall (3.3.9)
AdMobBannerProvider now uses adaptive full-width sizing by default (was fixed 320×50dp). Collapsible banner settings pass through the waterfall chain to the provider.
Installation
// Core modules
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.4.0'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.4.0'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.4.0'
// Jetpack Compose support
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.4.0'
// Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.4.0'Full Changelog
- Fix:
AppOpenManagersplash ad show rate —forceShowAdIfAvailable()now correctly takes over an in-progress dialog fetch instead of firingonNextAction()prematurely - Fix:
showAdIfAvailable()skips early when a dialog-based fetch is already in progress (isFetchingWithDialogguard) - Fix:
dialogFetchCallbackfield ensures the most recentforceShowAdIfAvailable()caller always receives the ad result - Fix:
layout_native_large.xml(sw600dp) container changed fromLinearLayouttoFrameLayoutfor correct tablet rendering - Fix:
AdManagerCallback.onFailedToLoad()now fires for app open ad failures (dialog dismissed first) - Fix: Welcome dialog always dismissed before any callback fires (
onFailedToLoad,onAdTimedOut,onNextAction) - Fix: Waterfall banner ads now use adaptive full-width sizing (was fixed 320×50dp)
- Fix: Collapsible banner settings now passed through waterfall to
AdMobBannerProvider - New:
AdManagerCallback.onAdTimedOut()callback for app open ad load timeout events - New:
admanagekit-yandexmodule with full Yandex Mobile Ads SDK integration - New: Multi-provider waterfall for interstitial, app open, banner, native, and rewarded ad types
- Change:
AdMobBannerProviderdefault ad size is now adaptive full-width (wasAdSize.BANNER) - Change:
AdMobProviderRegistration.create()default banner size is now adaptive
Full Changelog: v3.3.9...v3.4.0
v3.3.9
Release Notes - v3.3.9
Release Date: February 2026
App Open Ad Callback Improvements
Enhanced AdManagerCallback with proper failure and timeout callbacks for app open ads. The welcome dialog is now always dismissed before any callback fires.
New Callback: onAdTimedOut()
New dedicated callback on AdManagerCallback for when the ad load times out:
appOpenManager.forceShowAdIfAvailable(activity, object : AdManagerCallback() {
override fun onNextAction() {
// Always called after ad flow completes
navigateNext()
}
override fun onFailedToLoad(error: AdKitError?) {
// Called when ad fails to load (not timeout)
Log.e("Ads", "Ad failed: ${error?.message}")
}
override fun onAdTimedOut() {
// Called when ad load exceeds timeout duration
Log.w("Ads", "Ad load timed out")
}
})onFailedToLoad() Now Called for App Open Ads
Previously, AdManagerCallback.onFailedToLoad() was never invoked when app open ads failed to load with a dialog showing. Now it fires correctly (after dialog dismissal) for both AdMob and waterfall paths.
Callback order on failure:
- Dialog dismisses (animated)
onFailedToLoad(error)firesonNextAction()fires
Callback order on timeout:
- Dialog dismisses (animated)
onAdTimedOut()firesonNextAction()fires
Adaptive Full-Width Banner in Waterfall
Fixed banner ads displaying at 320x50dp (left-aligned) when loaded via the waterfall provider chain. AdMobBannerProvider now uses adaptive full-width sizing by default, matching the behavior of the direct BannerAdView path.
What Changed
AdMobBannerProvider: Default ad size changed fromAdSize.BANNER(320x50dp fixed) to adaptive full-width, calculated from the Activity context at load timeAdMobProviderRegistration.create(): DefaultbannerAdSizeparameter changed fromAdSize.BANNERtonull(adaptive)- Explicit size still supported: Pass
AdMobProviderRegistration.create(AdSize.BANNER)if you need the old fixed-size behavior
Collapsible Banner Support in Waterfall
AdMobBannerProvider now supports collapsible banners when used via the waterfall chain:
- Reads
AdManageKitConfig.enableCollapsibleBannersByDefaultat load time BannerAdViewpasses per-call collapsible settings through the waterfall to AdMob providers- New
collapsibleandcollapsiblePlacementproperties onAdMobBannerProvider
Installation
// Core modules
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.3.9'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.3.9'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.3.9'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.3.9'
// Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.3.9'Full Changelog
- New:
AdManagerCallback.onAdTimedOut()callback for ad load timeout events - Fix:
AdManagerCallback.onFailedToLoad()now fires for app open ad failures (dialog dismissed first) - Fix: Welcome dialog always dismissed before
onFailedToLoad/onAdTimedOut/onNextActioncallbacks - Fix: Waterfall banner ads now use adaptive full-width sizing instead of fixed 320x50dp
- Fix: Collapsible banner settings now passed through waterfall to
AdMobBannerProvider - Change:
AdMobBannerProviderdefault ad size is now adaptive (wasAdSize.BANNER) - Change:
AdMobProviderRegistration.create()default banner size is now adaptive
Full Changelog: v3.3.8...v3.3.9
v3.3.8
Release Notes - v3.3.8
Release Date: February 2026
Multi-Provider Waterfall & Yandex Ads Support
This release introduces a multi-ad-provider architecture with waterfall mediation, allowing you to chain multiple ad networks (AdMob, Yandex, and custom providers) with automatic fallback. The existing AdMob-only API remains fully backward compatible.
New Features
Multi-Provider Ad Architecture
New core interfaces in admanagekit-core enable ad network abstraction with zero external dependencies:
InterstitialAdProvider- Load and show interstitial ads from any networkAppOpenAdProvider- Load and show app open ads from any networkBannerAdProvider- Load banner ads from any networkNativeAdProvider- Load native ads from any networkRewardedAdProvider- Load and show rewarded ads from any network
// Register providers in your Application class
AdProviderConfig.registerProvider(AdProvider.ADMOB, AdMobProviderRegistration())
AdProviderConfig.registerProvider(AdProvider.YANDEX, YandexProviderRegistration())
// Configure waterfall chains
AdProviderConfig.setInterstitialChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setAppOpenChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setBannerChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setNativeChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
AdProviderConfig.setRewardedChain(listOf(AdProvider.ADMOB, AdProvider.YANDEX))
// Map ad unit IDs per provider
AdProviderConfig.setAdUnitMapping(AdUnitMapping(
interstitial = mapOf(
AdProvider.ADMOB to "ca-app-pub-xxx/yyy",
AdProvider.YANDEX to "R-M-XXXXX-Y"
),
// ... other ad types
))Waterfall Orchestrators
Waterfall classes automatically try the next provider when the current one fails:
InterstitialWaterfall- Interstitial ad waterfall with full AdManager integrationAppOpenWaterfall- App open ad waterfall with lifecycle awarenessBannerWaterfall- Banner ad waterfallNativeWaterfall- Native ad waterfallRewardedWaterfall- Rewarded ad waterfall
The waterfall is transparent to existing code - AdManager, AppOpenManager, BannerAdView, native ad views, and RewardedAdManager all detect waterfall configuration automatically and delegate to the waterfall when providers are configured.
New Module: admanagekit-yandex
Full Yandex Mobile Ads SDK integration as a provider:
YandexInterstitialProviderYandexAppOpenProviderYandexBannerProviderYandexNativeProviderYandexRewardedProvider
// Add Yandex provider module
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.3.8'AdMob Provider Wrappers
AdMob functionality is now also available as provider interfaces for waterfall use:
AdMobInterstitialProviderAdMobAppOpenProviderAdMobBannerProviderAdMobNativeProviderAdMobRewardedProvider
Backward Compatibility
The existing single-network API is completely unchanged. If you don't configure any waterfall chains, everything works exactly as before:
// This still works identically
AdManager.getInstance().loadInterstitialAd(context, adUnitId)
AdManager.getInstance().showInterstitialAd(activity, callback)Waterfall mode activates only when AdProviderConfig.getInterstitialChain() (or other chain getters) returns a non-empty list.
Installation
// Core modules (same as before)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.3.8'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.3.8'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.3.8'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.3.8'
// New: Yandex provider (optional)
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v3.3.8'Full Changelog
- Multi-provider ad architecture with core interfaces in
admanagekit-core - Waterfall mediation for all ad types (interstitial, app open, banner, native, rewarded)
- New
admanagekit-yandexmodule for Yandex Mobile Ads SDK integration - AdMob provider wrappers for waterfall compatibility
AdProviderConfigfor registering providers and configuring waterfall chainsAdUnitMappingfor per-provider ad unit ID configuration- Transparent waterfall integration - existing API unchanged
- Sample app updated with waterfall test activity
Full Changelog: v3.3.7...v3.3.8
v3.3.7
Release Notes - v3.3.7
Release Date: February 2026
App Open Ad Improvements & Default Changes
This release improves app open ad UX with welcome dialog on cached ads, adds background prefetching control, and changes default caching behavior.
New Features
Welcome Dialog for Cached App Open Ads
showCachedAd now displays the welcome back dialog before showing the cached ad, providing a consistent user experience across all app open ad display paths (ON_DEMAND, ONLY_CACHE, HYBRID).
Previously, cached ads would appear abruptly without any transition. Now all app open ad paths show the welcome dialog first.
Background Ad Prefetching (appOpenFetchFreshAd)
The appOpenFetchFreshAd setting has been repurposed (previously deprecated) to control when app open ads are fetched:
AdManageKitConfig.apply {
// false (default): Prefetch ad when app goes to background (onStop)
// Ad is ready immediately when user returns - no loading dialog needed
appOpenFetchFreshAd = false
// true: Fetch fresh ad when app comes to foreground (onStart)
// May show loading dialog while ad loads
appOpenFetchFreshAd = true
}When appOpenFetchFreshAd = false, the library automatically starts loading an app open ad when the app goes to background, so it's ready to show instantly when the user returns.
Breaking Changes
Native Ad Caching Disabled by Default
NativeAdManager.enableCachingNativeAds now defaults to false (was true).
If your app relies on native ad caching, explicitly enable it:
NativeAdManager.enableCachingNativeAds = trueAuto-Retry Disabled by Default
AdManageKitConfig.autoRetryFailedAds now defaults to false (was true).
If your app relies on automatic retry, explicitly enable it:
AdManageKitConfig.autoRetryFailedAds = trueConfiguration Changes
| Setting | Old Default | New Default | Description |
|---|---|---|---|
enableCachingNativeAds |
true |
false |
Native ad caching |
autoRetryFailedAds |
true |
false |
Auto-retry failed ad loads |
appOpenFetchFreshAd |
deprecated | false |
Background prefetch (false) vs foreground fetch (true) |
Installation
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.3.7'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.3.7'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.3.7'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.3.7'Full Changelog
- Welcome dialog now shown before cached app open ads for consistent UX
appOpenFetchFreshAdun-deprecated and repurposed for background prefetch control- App open ads prefetch on background (onStop) when
appOpenFetchFreshAd = false NativeAdManager.enableCachingNativeAdsdefault changed tofalseAdManageKitConfig.autoRetryFailedAdsdefault changed tofalse
Full Changelog: v3.3.6...v3.3.7
v3.3.6
Release Notes - v3.3.6
Release Date: January 2025
Multi-Language Support & Dark Mode
This release adds comprehensive internationalization support for ad loading dialogs and fixes dark mode compatibility issues.
New Features
42 Language Translations
Ad loading dialogs now display in the user's language. Supported languages include:
| Region | Languages |
|---|---|
| Asia | Chinese (Simplified & Traditional), Japanese, Korean, Hindi, Bengali, Tamil, Telugu, Marathi, Thai, Vietnamese, Indonesian, Malay, Urdu |
| Europe | German, French, Spanish, Italian, Portuguese, Russian, Ukrainian, Polish, Dutch, Swedish, Norwegian, Danish, Finnish, Czech, Slovak, Hungarian, Romanian, Bulgarian, Greek, Croatian, Serbian |
| Middle East | Arabic, Persian, Hebrew, Turkish |
| Africa | Swahili |
| Americas | Spanish, Portuguese, Catalan, Filipino/Tagalog |
Translated strings:
ad_loading_title- "Loading Ad"ad_loading_message- "Please wait a moment…"welcome_back_title- "Welcome Back!"welcome_back_subtitle- "Loading your content…"welcome_back_footer- "Just a moment…"
Dark Mode Support for Ad Loading Dialog
The ad loading dialog (dialog_loading_ad_fullscreen.xml) now properly adapts to night mode:
Light Mode:
- Card background: White (#FFFFFF)
- Title text: Dark gray (#212121)
- Message text: Medium gray (#757575)
- Progress indicator: Blue (#2196F3)
Dark Mode:
- Card background: Dark (#1E1E1E)
- Title text: Light gray (#ECECEC)
- Message text: Medium gray (#B0B0B0)
- Progress indicator: Light blue (#64B5F6)
Bug Fixes
Splash Ad Loading Optimization
loadInterstitialAdForSplash() now prevents redundant ad requests:
// Before: Would make network request even if ad was already loaded
AdManager.getInstance().loadInterstitialAdForSplash(context, adUnitId, timeout, callback)
// After: Skips request if ad is ready, immediately calls callbacks
// - If ad is loaded: Calls onNextAction() + onAdLoaded() immediately
// - If ad is loading: Waits for existing request with timeout
// - If neither: Makes new request (existing behavior)This optimization:
- Reduces unnecessary network requests
- Prevents duplicate ad loads during configuration changes
- Maintains timeout behavior for callback guarantees
Technical Details
New Color Resources
Added to values/colors.xml and values-night/colors.xml:
ad_dialog_overlayad_dialog_card_backgroundad_dialog_title_colorad_dialog_message_colorad_dialog_progress_colorad_dialog_progress_track
New String Resources
Added to values/strings.xml with translations in 42 values-{locale}/strings.xml files:
ad_loading_titlead_loading_messagewelcome_back_titlewelcome_back_subtitlewelcome_back_footerapp_icon_description
loadInterstitialAdForSplash Improvements
- Now tracks loading state with
loadingAdUnitsset (consistent withloadInterstitialAd) - Checks
mInterstitialAdandadPoolbefore making new requests - Properly cleans up loading state in all callback paths
Installation
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.3.6'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.3.6'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.3.6'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.3.6'Full Changelog
- Added translations for 42 languages
- Added dark mode support for ad loading dialog
- Fixed
loadInterstitialAdForSplashto skip loading when ad is ready - Fixed duplicate load requests during splash screen
- Added proper
loadingAdUnitstracking for splash ad loading - Updated dialog layouts to use string resources
- Updated dialog layouts to use theme-aware color resources
Full Changelog: v3.3.5...v3.3.6
v3.3.5
Release Notes - v3.3.5
Release Date: January 2025
App Open Loading Strategies
This release brings full loading strategy support to AppOpenManager, aligning it with the existing interstitial and native ad loading patterns.
New Features
Loading Strategy Support
AppOpenManager now properly uses AdManageKitConfig.appOpenLoadingStrategy:
- ON_DEMAND: Fetches fresh ad with welcome dialog. Uses cached ad if still fresh (within
appOpenAdFreshnessThreshold). - ONLY_CACHE: Only shows cached ads instantly. Silently loads new ad in background if unavailable.
- HYBRID: Shows cached if available, fetches with welcome dialog otherwise (recommended).
AdManageKitConfig.apply {
appOpenLoadingStrategy = AdLoadingStrategy.HYBRID // default
}Ad Freshness Tracking
Cached ads now track when they were loaded to prevent showing stale content:
// Configure freshness threshold (default: 4 hours per Google recommendation)
AdManageKitConfig.appOpenAdFreshnessThreshold = 4.hours
// Check cached ad age
val ageMs = appOpenManager.getCachedAdAgeMs()Auto-Reload Configuration
Control whether ads automatically reload after being dismissed:
AdManageKitConfig.appOpenAutoReload = true // default: trueBug Fixes
- Fixed auto-reload after ad dismissal: Previously,
fetchAd()was not being called after ad dismissal. Now properly reloads based onappOpenAutoReloadsetting. - Fixed wasted ads: ON_DEMAND strategy now checks if cached ad is still fresh before discarding it and fetching a new one.
Deprecations
appOpenFetchFreshAd: Deprecated in favor ofappOpenLoadingStrategyappOpenFetchFreshAd = true→appOpenLoadingStrategy = AdLoadingStrategy.ON_DEMANDappOpenFetchFreshAd = false→appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
Migration
If you were using appOpenFetchFreshAd:
// Before (deprecated)
AdManageKitConfig.appOpenFetchFreshAd = true
// After
AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.ON_DEMANDAPI Changes
New Methods in AppOpenManager
getCachedAdAgeMs(): Long- Returns age of cached ad in milliseconds
New Config Options in AdManageKitConfig
appOpenAdFreshnessThreshold: Duration- Max age for "fresh" cached ad (default: 4 hours)appOpenAutoReload: Boolean- Auto-reload after dismissal (default: true)
Installation
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.3.5'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.3.5'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.3.5'
implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.3.5'Full Changelog
- Full
AdLoadingStrategysupport for AppOpenManager - Ad freshness tracking with
adLoadTimeandappOpenAdFreshnessThreshold - Auto-reload configuration with
appOpenAutoReload - Deprecated
appOpenFetchFreshAdin favor ofappOpenLoadingStrategy - Fixed auto-reload after ad dismissal
- Fixed wasted ads when using ON_DEMAND strategy
- Added
getCachedAdAgeMs()method - Updated documentation for app open ads
Full Changelog: v3.3.4...v3.3.5