Skip to content

Releases: i2hammad/AdManageKit

v3.4.4

13 Mar 08:04

Choose a tag to compare

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.root now reset in loadAd() and displayAd()
  • NativeBannerMedium: binding.adContainer now reset in loadAd(), displayAd(), displayCachedAdSafely(), and waterfall success path
  • NativeLarge: binding.adUnit now reset in loadAd() and binding.root in displayAd()
  • NativeTemplateView: binding.root now reset in loadAd() and displayAd()

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() deferred setNativeAd() via post {} — changed to synchronous call for reliable impression registration
  • Fixed: Shimmer overlay on cached/waterfall ads in NativeBannerMedium.displayCachedAdSafely()
  • Fixed: RewardedAdManager crash when methods called before initialize()lateinit var adUnitId changed to empty string default with guards
  • Fixed: NativeBannerSmall, NativeLarge, NativeTemplateView crash when adUnitId accessed before assignment — lateinit changed to empty string default
  • Added: Empty adUnitId validation with warning logs and appropriate callback responses across all native views and RewardedAdManager

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

05 Mar 22:05

Choose a tag to compare

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 pendingFetchCallback with 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 onStartshowAdIfAvailable() 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 onStart preload and splash fetchAd run concurrently (both waterfall and non-waterfall)
  • Fixed: Splash auto-navigation caused by orphaned pendingFetchTimeoutRunnable firing stale onFailedToLoad callbacks
  • 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 (explicit fetchAd/forceShow handles it)
  • Fixed: Hot-start duplicate loads when returning to SplashActivity
  • Added: pendingFetchCallback mechanism to attach splash callbacks to in-progress background preloads
  • Added: hasBeenBackgrounded flag to distinguish cold start from resume for ON_DEMAND strategy
  • Added: loading log event to all ad load start paths (background preload, dialog fetch, fresh fetch, timeout fetch)
  • Added: showCachedAd log event when cached ads are shown (regular and forced paths)
  • Added: AdDebugUtils.logEvent calls to all previously missing load/failure paths in AppOpenManager

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

05 Mar 19:25

Choose a tag to compare

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: AppOpenManager now respects AdManageKitConfig.autoRetryFailedAds (was always retrying with hardcoded values)
  • Fixed: AppOpenManager now uses AdManageKitConfig.maxRetryAttempts instead of hardcoded retry limit
  • Fixed: AppOpenManager retry now uses AdRetryManager for 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() — use AdManageKitConfig properties 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

25 Feb 10:38

Choose a tag to compare

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" = quarterly

Returns 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) — Raw ProductDetails object 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

17 Feb 08:28

Choose a tag to compare

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):

  1. showAdIfAvailable() now guards against isFetchingWithDialog — prevents onStart()'s automatic path from starting a competing dialog fetch when forceShowAdIfAvailable() has already started one.

  2. Added dialogFetchCallback field — 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.

  3. forceShowAdIfAvailable() takes over an in-progress fetch — when called while isFetchingWithDialog is true, it replaces dialogFetchCallback with 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: AppOpenManager splash ad show rate — forceShowAdIfAvailable() now correctly takes over an in-progress dialog fetch instead of firing onNextAction() prematurely
  • Fix: showAdIfAvailable() skips early when a dialog-based fetch is already in progress (isFetchingWithDialog guard)
  • Fix: dialogFetchCallback field ensures the most recent forceShowAdIfAvailable() caller always receives the ad result
  • Fix: layout_native_large.xml (sw600dp) container changed from LinearLayout to FrameLayout for 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-yandex module with full Yandex Mobile Ads SDK integration
  • New: Multi-provider waterfall for interstitial, app open, banner, native, and rewarded ad types
  • Change: AdMobBannerProvider default ad size is now adaptive full-width (was AdSize.BANNER)
  • Change: AdMobProviderRegistration.create() default banner size is now adaptive

Full Changelog: v3.3.9...v3.4.0

v3.3.9

11 Feb 17:43

Choose a tag to compare

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:

  1. Dialog dismisses (animated)
  2. onFailedToLoad(error) fires
  3. onNextAction() fires

Callback order on timeout:

  1. Dialog dismisses (animated)
  2. onAdTimedOut() fires
  3. onNextAction() 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 from AdSize.BANNER (320x50dp fixed) to adaptive full-width, calculated from the Activity context at load time
  • AdMobProviderRegistration.create(): Default bannerAdSize parameter changed from AdSize.BANNER to null (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.enableCollapsibleBannersByDefault at load time
  • BannerAdView passes per-call collapsible settings through the waterfall to AdMob providers
  • New collapsible and collapsiblePlacement properties on AdMobBannerProvider

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/onNextAction callbacks
  • 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: AdMobBannerProvider default ad size is now adaptive (was AdSize.BANNER)
  • Change: AdMobProviderRegistration.create() default banner size is now adaptive

Full Changelog: v3.3.8...v3.3.9

v3.3.8

09 Feb 17:19

Choose a tag to compare

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 network
  • AppOpenAdProvider - Load and show app open ads from any network
  • BannerAdProvider - Load banner ads from any network
  • NativeAdProvider - Load native ads from any network
  • RewardedAdProvider - 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 integration
  • AppOpenWaterfall - App open ad waterfall with lifecycle awareness
  • BannerWaterfall - Banner ad waterfall
  • NativeWaterfall - Native ad waterfall
  • RewardedWaterfall - 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:

  • YandexInterstitialProvider
  • YandexAppOpenProvider
  • YandexBannerProvider
  • YandexNativeProvider
  • YandexRewardedProvider
// 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:

  • AdMobInterstitialProvider
  • AdMobAppOpenProvider
  • AdMobBannerProvider
  • AdMobNativeProvider
  • AdMobRewardedProvider

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-yandex module for Yandex Mobile Ads SDK integration
  • AdMob provider wrappers for waterfall compatibility
  • AdProviderConfig for registering providers and configuring waterfall chains
  • AdUnitMapping for 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

06 Feb 13:39

Choose a tag to compare

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 = true

Auto-Retry Disabled by Default

AdManageKitConfig.autoRetryFailedAds now defaults to false (was true).

If your app relies on automatic retry, explicitly enable it:

AdManageKitConfig.autoRetryFailedAds = true

Configuration 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
  • appOpenFetchFreshAd un-deprecated and repurposed for background prefetch control
  • App open ads prefetch on background (onStop) when appOpenFetchFreshAd = false
  • NativeAdManager.enableCachingNativeAds default changed to false
  • AdManageKitConfig.autoRetryFailedAds default changed to false

Full Changelog: v3.3.6...v3.3.7

v3.3.6

29 Jan 14:07

Choose a tag to compare

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_overlay
  • ad_dialog_card_background
  • ad_dialog_title_color
  • ad_dialog_message_color
  • ad_dialog_progress_color
  • ad_dialog_progress_track

New String Resources

Added to values/strings.xml with translations in 42 values-{locale}/strings.xml files:

  • ad_loading_title
  • ad_loading_message
  • welcome_back_title
  • welcome_back_subtitle
  • welcome_back_footer
  • app_icon_description

loadInterstitialAdForSplash Improvements

  • Now tracks loading state with loadingAdUnits set (consistent with loadInterstitialAd)
  • Checks mInterstitialAd and adPool before 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 loadInterstitialAdForSplash to skip loading when ad is ready
  • Fixed duplicate load requests during splash screen
  • Added proper loadingAdUnits tracking 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

22 Jan 06:26

Choose a tag to compare

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: true

Bug Fixes

  • Fixed auto-reload after ad dismissal: Previously, fetchAd() was not being called after ad dismissal. Now properly reloads based on appOpenAutoReload setting.
  • 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 of appOpenLoadingStrategy
    • appOpenFetchFreshAd = trueappOpenLoadingStrategy = AdLoadingStrategy.ON_DEMAND
    • appOpenFetchFreshAd = falseappOpenLoadingStrategy = AdLoadingStrategy.HYBRID

Migration

If you were using appOpenFetchFreshAd:

// Before (deprecated)
AdManageKitConfig.appOpenFetchFreshAd = true

// After
AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.ON_DEMAND

API 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 AdLoadingStrategy support for AppOpenManager
  • Ad freshness tracking with adLoadTime and appOpenAdFreshnessThreshold
  • Auto-reload configuration with appOpenAutoReload
  • Deprecated appOpenFetchFreshAd in favor of appOpenLoadingStrategy
  • 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