admanagekit-mcp-server 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,121 @@
1
+ # Release Notes — v4.4.3
2
+
3
+ **Release Date:** 2026-08-15
4
+
5
+ ## Overview
6
+
7
+ v4.4.3 is a bug-fix and dependency release. No API was added, removed or changed. Two of the fixes are silent-failure bugs that cost real money:
8
+
9
+ - **A rewarded load the manager had given up on could sabotage the load that replaced it** — throwing away an ad that had just arrived, and clearing the "loading" flag out from under a request that was still running.
10
+ - **Billing could stop acknowledging purchases for the rest of the process**, which lets Play auto-refund a completed purchase on day 3.
11
+
12
+ It also picks up the Next-Gen GMA SDK **1.3.1**, Yandex Mobile Ads **8.3.0**, and refreshed AndroidX/Firebase/Compose BOMs.
13
+
14
+ Upgrading is a drop-in from 4.4.x.
15
+
16
+ ---
17
+
18
+ ## Fixed
19
+
20
+ ### A timed-out rewarded load could sabotage the one that replaced it
21
+
22
+ `RewardedAdManager.loadRewardedAdWithTimeout(...)` stops waiting for a load once its timeout elapses — but a request handed to the SDK **cannot be cancelled**, so it keeps running and reports back whenever it finishes. Its callbacks then ran the full success/failure path as though they still spoke for the manager, even though a replacement load had started in the meantime.
23
+
24
+ Concretely, a late callback from an abandoned request could:
25
+
26
+ - **Throw away a perfectly good ad.** The failure path ran `rewardedAd = null` unconditionally, so a stale failure discarded an ad a *later* load had just delivered. The next `showAd()` found nothing and skipped the reward.
27
+ - **Clear `isLoading` out from under the load that was still running**, so the manager reported itself idle while a request was in flight — letting a duplicate load start and burning an extra ad request.
28
+ - **Fail callers queued behind a load that had not finished yet**, via `notifyPendingLoadFailure`.
29
+ - **Schedule a retry for a request nobody was waiting on.**
30
+
31
+ Every load path now claims a generation token and checks it before touching anything shared — the same mechanism `RewardedWaterfall` already used internally. A stale callback answers *its own* caller (which is still owed a result and has no other source of one) and otherwise leaves shared state alone.
32
+
33
+ A late ad is **kept rather than dropped**: it is real and showable no matter which request produced it, so it is adopted for the next show whenever nothing better is already in hand. This applies to both the AdMob path and the waterfall path.
34
+
35
+ Two related unconditional writes were tightened at the same time:
36
+
37
+ - The direct load's failure path no longer does `rewardedAd = null` at all. A failed request means *this* request produced nothing — not that an ad obtained elsewhere has stopped being showable.
38
+ - The waterfall failure path now clears `rewardedWaterfall` only when the chain being reported on is still the one it installed (`if (rewardedWaterfall === waterfall)`), so a newer load's chain — or a late chain adopted in the meantime — is not discarded by an older failure.
39
+
40
+ > This is the same class of bug as the v4.4.2 `AdManager` duplicate-callback fix, in the one manager that still resolved in-flight state with plain flags.
41
+
42
+ ### Billing could stop acknowledging purchases for the rest of the process
43
+
44
+ `AppPurchase` gated every re-query on `isServiceConnected`, an `AtomicBoolean` written **only** by `onBillingSetupFinished` and cleared by `onBillingServiceDisconnected`.
45
+
46
+ The library enables `enableAutoServiceReconnection()`, and the SDK restores the connection on its own without necessarily re-firing `onBillingSetupFinished`. So after a single disconnect the flag could stay `false` permanently — while the client itself was perfectly ready — silently disabling:
47
+
48
+ - `verifyPurchased(...)` and `updatePurchaseStatus()` — entitlement re-checks
49
+ - `refreshPurchases(...)` — including **the acknowledgment retry**
50
+ - `consumePurchase(...)`, `queryProductDetails(...)`
51
+ - `connectToGooglePlayBilling()`, which skipped reconnecting because it believed it was still connected
52
+
53
+ That last one matters most: **Play auto-refunds any purchase left unacknowledged for 3 days.** A user who bought while the flag was stuck could be charged, granted the entitlement, and then silently refunded — with the app still treating them as a paying customer.
54
+
55
+ All of these now consult the client's own live state (`billingClient.isReady()`) instead of the latched flag. `onBillingServiceDisconnected` also stops clearing `isBillingAvailable`: the client *was* set up successfully, and `isAvailable()` ANDs that fact with the live readiness check, so it now reports `false` only while the service is actually down rather than latching `false` for the rest of the process.
56
+
57
+ ### Acknowledgment required the purchase to match a configured product id
58
+
59
+ In both `verifyPurchased(...)` and `updatePurchaseStatus()`, `acknowledgePurchaseIfNeeded(purchase)` was called *inside* the loop that matched the purchase against `inAppProductIdList` / `subProductIdList`. A `PURCHASED` order whose id the current build does not list was never acknowledged — and so was auto-refunded on day 3.
60
+
61
+ That is not a hypothetical set: promo-code grants, products dropped from a newer release, a Play Console id typo, and a user who purchased on a build that configured more ids than the one they are running now all land here.
62
+
63
+ Acknowledgment now happens **before** the id match, unconditionally for every `PURCHASED` purchase. Entitlement still requires a configured id — only the acknowledgment was decoupled, since the 3-day clock does not care whether your build recognises the product.
64
+
65
+ ---
66
+
67
+ ## Dependencies
68
+
69
+ | Dependency | 4.4.2 | 4.4.3 |
70
+ | --- | --- | --- |
71
+ | Google Mobile Ads Next-Gen SDK | 1.3.0 | **1.3.1** |
72
+ | Yandex Mobile Ads | 8.2.0 | **8.3.0** |
73
+ | Compose BOM | 2026.06.01 | **2026.08.00** |
74
+ | Firebase BOM | 34.15.0 | **34.17.0** |
75
+ | AndroidX AppCompat | 1.7.1 | **1.8.0** |
76
+ | ConstraintLayout | 2.2.1 | **2.2.2** |
77
+ | org.json (test only) | 20250517 | **20260719** |
78
+
79
+ Google Play Billing stays at **9.1.0** and Kotlin at **2.2.10**.
80
+
81
+ ### Sample app now compiles at JVM 17
82
+
83
+ The `app` sample module was the only module still pinned to `jvmTarget = "1.8"`, while all five published modules use 17. Compose BOM 2026.08.00 ships artifacts compiled at JVM 11+, which cannot be inlined into 1.8 bytecode — so the bump broke `assembleDebug` on the sample with `Cannot inline bytecode built with JVM target 11 into bytecode that is being built with JVM target 1.8`.
84
+
85
+ The sample now uses `VERSION_17` / `jvmTarget = "17"`, matching the library modules. **This does not affect the published artifacts** — their compile options were already 17 and are unchanged. It is noted here only because anyone building the repo from source would otherwise hit it.
86
+
87
+ ---
88
+
89
+ ## Documentation
90
+
91
+ `docs/APP_PURCHASE_GUIDE.md` now documents what pending purchases require from the host app. A pending order (cash, bank transfer, parental approval) can complete hours or days later while the app is closed; `onPurchasesUpdated` only fires if the app happens to be running, so Play requires apps to re-query owned purchases on every foreground. `AppPurchase` queries on billing init, and if the process survives the transition that never runs again — so the guide now shows calling `refreshPurchases()` from the main activity's `onResume()`, and explains that this is what stops a completed pending order from being auto-cancelled on day 3.
92
+
93
+ ---
94
+
95
+ ## Verification
96
+
97
+ `assembleDebug` succeeds and `testDebugUnitTest --rerun-tasks` passes **176 tests, 0 failures** — 173 existing plus 3 new `RewardedAdManagerStaleLoadTest` cases pinning down the stale-load contract:
98
+
99
+ - an abandoned load's failure must not discard an ad another load produced
100
+ - an abandoned load's failure must not clear the replacement's `isLoading`
101
+ - an ad arriving after the timeout is kept for the next show rather than dropped
102
+
103
+ The tests drive the waterfall path, whose providers are fakes the test can complete by hand; the AdMob path runs the same generation checks over a static SDK entry point.
104
+
105
+ The billing changes are **not** covered by automated tests — both depend on `BillingClient` connection-state transitions that the existing `ProductDetailsFactory`-based harness cannot drive. They were verified by reading every call site of `isServiceConnected` and every `acknowledgePurchaseIfNeeded` path; on-device verification against a Play test track is recommended.
106
+
107
+ ---
108
+
109
+ ## Upgrading
110
+
111
+ Drop-in from 4.4.x. No source changes required.
112
+
113
+ If your app relies on pending purchases, add the `onResume()` refresh described under [Documentation](#documentation) — the library cannot do this for you, since it does not own your activity lifecycle.
114
+
115
+ ```groovy
116
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3'
117
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.4.3'
118
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
119
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v4.4.3'
120
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v4.4.3'
121
+ ```
@@ -1,8 +1,8 @@
1
- # Ad Loading Strategies - AdManageKit v2.8.0
1
+ # Ad Loading Strategies - AdManageKit v4.4.3
2
2
 
3
3
  ## Overview
4
4
 
5
- AdManageKit v2.6.0+ introduces three loading strategies that control how ads are fetched and displayed. Choose the right strategy based on your app's needs for user experience vs. ad coverage.
5
+ AdManageKit v2.6.0+ introduces four loading strategies that control how ads are fetched and displayed. Choose the right strategy based on your app's needs for user experience vs. ad coverage.
6
6
 
7
7
  ## Strategy Types
8
8
 
@@ -63,15 +63,33 @@ AdManageKitConfig.interstitialLoadingStrategy = AdLoadingStrategy.HYBRID
63
63
  - Default recommendation
64
64
  - Balanced UX and coverage
65
65
 
66
+ ### 4. FRESH_WITH_CACHE_FALLBACK
67
+
68
+ **Fetch fresh first, fall back to cache on failure**
69
+
70
+ ```kotlin
71
+ AdManageKitConfig.nativeLoadingStrategy = AdLoadingStrategy.FRESH_WITH_CACHE_FALLBACK
72
+ ```
73
+
74
+ | Pros | Cons |
75
+ |------|------|
76
+ | Freshest creative when the network cooperates | Slower than cache-first when the fetch is slow |
77
+ | Cache covers the failure case | Requires a warm cache to help |
78
+ | Successful loads are cached for later | - |
79
+
80
+ **Best for:**
81
+ - RecyclerView / feed scenarios where each item should try for a fresh ad
82
+ - Placements where creative freshness matters more than instant fill
83
+
66
84
  ## Strategy Availability
67
85
 
68
- | Ad Type | ON_DEMAND | ONLY_CACHE | HYBRID |
69
- |---------|-----------|------------|--------|
70
- | Interstitial | ✅ | ✅ | ✅ |
71
- | App Open | ✅ | ✅ | ✅ |
72
- | Native | ✅ | | ✅ |
86
+ | Ad Type | ON_DEMAND | ONLY_CACHE | HYBRID | FRESH_WITH_CACHE_FALLBACK |
87
+ |---------|-----------|------------|--------|---------------------------|
88
+ | Interstitial | ✅ | ✅ | ✅ | ✅ |
89
+ | App Open | ✅ | ✅ | ✅ | ✅ |
90
+ | Native | ✅ | | ✅ | ✅ |
73
91
 
74
- > **Note:** Native ads use shimmer instead of dialog, so ONLY_CACHE hides container if not cached.
92
+ > **Note:** Native ads use shimmer instead of a dialog, so `ONLY_CACHE` hides the container when nothing is cached rather than blocking the UI.
75
93
 
76
94
  ## Configuration
77
95
 
@@ -1,10 +1,10 @@
1
- # App Open Ads - AdManageKit v4.3.5
1
+ # App Open Ads - AdManageKit v4.4.3
2
2
 
3
3
  ## Overview
4
4
 
5
5
  AdManageKit provides lifecycle-aware app open ad management through `AppOpenManager`. App open ads display when users launch or return to your app, with support for loading strategies, ad freshness enforcement, welcome dialogs, activity/screen exclusion, and the multi-provider waterfall.
6
6
 
7
- **Library Version**: v4.3.5
7
+ **Library Version**: v4.4.3
8
8
 
9
9
  ## Features
10
10
 
@@ -23,9 +23,9 @@ AdManageKit provides lifecycle-aware app open ad management through `AppOpenMana
23
23
 
24
24
  ```groovy
25
25
  dependencies {
26
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.3.5'
27
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.3.5'
28
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.3.5'
26
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3'
27
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.4.3'
28
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
29
29
  }
30
30
  ```
31
31
 
@@ -1,10 +1,10 @@
1
- # Banner Ads - AdManageKit v4.3.5
1
+ # Banner Ads - AdManageKit v4.4.3
2
2
 
3
3
  ## Overview
4
4
 
5
5
  AdManageKit provides `BannerAdView` for banner ad integration with every standard AdMob size, adaptive banners, collapsible banners, a size-aware loading shimmer, auto-refresh, and smart retry logic.
6
6
 
7
- **Library Version**: v4.3.5
7
+ **Library Version**: v4.4.3
8
8
 
9
9
  ## Features
10
10
 
@@ -23,8 +23,8 @@ AdManageKit provides `BannerAdView` for banner ad integration with every standar
23
23
 
24
24
  ```groovy
25
25
  dependencies {
26
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.3.5'
27
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.3.5'
26
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3'
27
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
28
28
  }
29
29
  ```
30
30
 
@@ -7,8 +7,8 @@ AdManageKit provides a comprehensive billing integration module (`admanagekit-bi
7
7
  ### 1. Add Dependency
8
8
 
9
9
  ```groovy
10
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.4.0'
11
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.0'
10
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.4.3'
11
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
12
12
  ```
13
13
 
14
14
  ### 2. Define Products
@@ -52,6 +52,24 @@ class MyApp : Application() {
52
52
  > Only `PurchaseState.PURCHASED` grants entitlement (pending purchases do not).
53
53
  > Consumables still require a manual `consumePurchase(productId)` after granting.
54
54
 
55
+ > **Pending purchases need one thing from you (v4.4.3).** A pending order (cash,
56
+ > bank transfer, parental approval) can complete hours or days later, while your
57
+ > app is closed. `onPurchasesUpdated` only fires if the app happens to be
58
+ > running, so Play requires apps to re-query owned purchases on every foreground.
59
+ > `AppPurchase` queries on billing init; if your process stays alive across the
60
+ > transition, that never runs again — so call `refreshPurchases()` from your main
61
+ > activity's `onResume()`:
62
+ >
63
+ > ```kotlin
64
+ > override fun onResume() {
65
+ > super.onResume()
66
+ > AppPurchase.getInstance().refreshPurchases()
67
+ > }
68
+ > ```
69
+ >
70
+ > It acknowledges every unacknowledged `PURCHASED` purchase it finds, which is
71
+ > what stops a completed pending order from being auto-cancelled on day 3.
72
+
55
73
  ### 4. Make Purchases
56
74
 
57
75
  ```kotlin
@@ -1,4 +1,4 @@
1
- # Configuration - AdManageKit v2.8.0
1
+ # Configuration - AdManageKit v4.4.3
2
2
 
3
3
  ## Overview
4
4
 
@@ -32,6 +32,8 @@ class MyApp : Application() {
32
32
  }
33
33
  ```
34
34
 
35
+ > **Since 4.2.0 you must also call `MobileAds.initialize()` yourself**, before any ad request — the Next-Gen SDK removed the legacy SDK's silent lazy-init. `AdManageKitConfig` only configures this library's behavior; it does not initialize the ads SDK. See [[Home]] for the initialization pattern.
36
+
35
37
  ## All Configuration Options
36
38
 
37
39
  ### Performance Settings
@@ -138,6 +140,28 @@ AdManageKitConfig.apply {
138
140
  }
139
141
  ```
140
142
 
143
+ ### Native Ad Settings
144
+
145
+ | Setting | Description | Default |
146
+ |---------|-------------|---------|
147
+ | `nativeLoadingStrategy` | Loading strategy | HYBRID |
148
+ | `nativeCacheExpiry` | Cache expiry for native ads | 1 hour |
149
+ | `defaultNativeMediaAspect` | Media aspect-ratio hint sent with every native request (v4.3.3+) | ANY |
150
+ | `nativeVideoStartMuted` | Start video creatives muted (v4.3.3+) | true |
151
+ | `nativeVideoClickToExpand` | Allow click-to-expand on video creatives (v4.3.3+) | false |
152
+ | `nativeVideoCustomControls` | Request custom video controls (v4.3.3+) | false |
153
+
154
+ `NativeMediaAspect` values: `UNSPECIFIED`, `ANY`, `LANDSCAPE`, `PORTRAIT`, `SQUARE`. `NativeTemplateView.setMediaAspect(...)` overrides the global default per view.
155
+
156
+ ```kotlin
157
+ AdManageKitConfig.apply {
158
+ nativeLoadingStrategy = AdLoadingStrategy.HYBRID
159
+ nativeCacheExpiry = 1.hours
160
+ defaultNativeMediaAspect = NativeMediaAspect.ANY
161
+ nativeVideoStartMuted = true
162
+ }
163
+ ```
164
+
141
165
  ### App Open Settings
142
166
 
143
167
  | Setting | Description | Default |
@@ -1,18 +1,35 @@
1
1
  # AdManageKit
2
2
 
3
3
  [![JitPack](https://jitpack.io/v/i2hammad/AdManageKit.svg)](https://jitpack.io/#i2hammad/AdManageKit)
4
- ![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)
4
+ ![API](https://img.shields.io/badge/API-24%2B-brightgreen.svg?style=flat)
5
5
  ![License](https://img.shields.io/badge/License-MIT-blue.svg)
6
6
 
7
7
  AdManageKit is a comprehensive Android library designed to simplify the integration and management of Google AdMob ads, Google Play Billing, and User Messaging Platform (UMP) consent.
8
8
 
9
- **Latest Version: `2.8.0`**
9
+ **Latest Version: `4.4.3`**
10
10
 
11
- ## What's New in 2.8.0
11
+ ## What's New in 4.4.3
12
12
 
13
- - **Loading Strategy for AdManager**: `forceShowInterstitial()` now respects global loading strategy
14
- - **Global Auto-Reload Config**: New `interstitialAutoReload` setting with per-call override
15
- - **New Method**: `forceShowInterstitialAlways()` for explicit force fetch behavior
13
+ Bug-fix and dependency release, no API changes. Two silent-failure bugs, both of which cost money.
14
+
15
+ - **A timed-out rewarded load could sabotage the one that replaced it** — a request handed to the SDK cannot be cancelled, and when it finally reported back it could discard an ad a *newer* load had just delivered, clear the loading flag out from under a request still in flight, and fail callers waiting on a load that had not finished. Every load path now carries a generation token, and a late ad is kept for the next show instead of dropped
16
+ - **Billing could stop acknowledging purchases for the rest of the process** — the connection flag could latch `false` after one disconnect while the client was actually ready, disabling every purchase re-query including the acknowledgment retry. Play auto-refunds an unacknowledged purchase after 3 days
17
+ - **Acknowledgment no longer requires a configured product id** — a `PURCHASED` order the current build does not list (promo grants, dropped products, a Console typo) was never acknowledged, and so was auto-refunded on day 3
18
+ - **Dependencies** — Next-Gen GMA SDK 1.3.1, Yandex Mobile Ads 8.3.0, Compose BOM 2026.08.00, Firebase BOM 34.17.0, AppCompat 1.8.0
19
+
20
+ > **Pending purchases need one thing from your app:** call `refreshPurchases()` from your main activity's `onResume()`. See [[Billing Integration]].
21
+
22
+ ## Recent Highlights
23
+
24
+ - **4.4.2** — Rewarded callbacks marshalled to the main thread (they could crash the app), a completed purchase could fail to disable ads, blank gaps where banner/native slots should have collapsed, and a `BannerAdView` Activity leak. Behavior changes: an account-hold subscription no longer disables ads, and premium users no longer reserve ad space in Compose
25
+ - **4.4.1** — Google Mobile Ads Next-Gen SDK 1.3.0 (from 1.2.1), plus repairs to API doc generation and the MCP documentation server
26
+ - **4.4.0** — Subscription offers can be **purchased individually** (`subscribe(activity, offer)`), offer lookup by id/base plan/tag, cross-cadence price normalization (`BillingPeriod`, `getSavingsPercent`), trial eligibility, Play Billing 9 one-time product offers, and client-side **account hold** detection. See [[Subscription Offers]]
27
+ - **4.3.x** — All standard banner sizes (`BannerAdSize`), custom native templates, and app-open ad freshness enforcement
28
+ - **4.2.0** — Migrated to the Google Mobile Ads **Next-Gen SDK** and Play Billing 9. `MobileAds.initialize()` must now be called explicitly before any ad request
29
+
30
+ > Upgrading from 3.x or earlier? Read the [Migrating to 4.2.0](https://github.com/i2hammad/AdManageKit#migrating-to-420) notes first — it is the one release in the 4.x line that is not source-compatible.
31
+
32
+ Full details: [Changelog](https://github.com/i2hammad/AdManageKit/blob/main/CHANGELOG.md) · [Release Notes](https://github.com/i2hammad/AdManageKit/tree/main/docs/release-notes)
16
33
 
17
34
  ## Features
18
35
 
@@ -23,14 +40,16 @@ AdManageKit is a comprehensive Android library designed to simplify the integrat
23
40
  - **App Open Ads**: Lifecycle-aware with activity exclusion
24
41
 
25
42
  ### NativeTemplateView (v2.6.0+)
26
- - 17 Template Styles: card_modern, material3, minimal, list_item, magazine, video templates
43
+ - 38 Template Styles: card_modern, material3, minimal, list_item, magazine, app_store, social_feed, spotlight, plus the video_* and flat_* families
27
44
  - XML & Programmatic: Set templates via `app:adTemplate` or `setTemplate()`
45
+ - Custom Templates (v4.3.0+): supply your own layout via `setCustomTemplate()` or `app:customAdLayout`
28
46
  - Material 3 Theming: Automatic dark/light mode support
29
47
 
30
48
  ### Ad Loading Strategies (v2.6.0+)
31
49
  - **ON_DEMAND**: Fetch fresh ads with loading dialog
32
50
  - **ONLY_CACHE**: Instant display from cache
33
51
  - **HYBRID**: Cache-first with fallback fetch (recommended)
52
+ - **FRESH_WITH_CACHE_FALLBACK**: Fetch fresh, fall back to cache on failure
34
53
 
35
54
  ### Centralized Configuration
36
55
  - **AdManageKitConfig**: Single configuration point
@@ -65,27 +84,39 @@ dependencyResolutionManagement {
65
84
  **Step 2:** Add dependencies to your app's `build.gradle`:
66
85
 
67
86
  ```groovy
68
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v2.8.0'
69
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v2.8.0'
70
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v2.8.0'
87
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3'
88
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.4.3'
89
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
71
90
 
72
91
  // For Jetpack Compose support
73
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v2.8.0'
92
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v4.4.3'
93
+
94
+ // For Yandex Ads multi-provider support
95
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v4.4.3'
74
96
  ```
75
97
 
76
- **Step 3:** Sync your project with Gradle.
98
+ **Step 3:** Ensure your app's `compileSdk` is **37 or higher** (required transitively as of 4.2.0).
99
+
100
+ **Step 4:** Sync your project with Gradle.
77
101
 
78
102
  ### Quick Configuration
79
103
 
80
104
  Configure AdManageKit in your Application class:
81
105
 
106
+ > **Since 4.2.0 you must call `MobileAds.initialize()` yourself.** The Next-Gen SDK removed the legacy SDK's silent lazy-init, so an app that skips it never loads ads. AdManageKit does not call it for you, because it does not own your consent flow.
107
+
82
108
  ```kotlin
83
109
  class MyApp : Application() {
84
- private lateinit var appOpenManager: AppOpenManager
110
+ var appOpenManager: AppOpenManager? = null
85
111
 
86
112
  override fun onCreate() {
87
113
  super.onCreate()
88
114
 
115
+ initAds()
116
+
117
+ // Set up billing
118
+ BillingConfig.setPurchaseProvider(BillingPurchaseProvider())
119
+
89
120
  // Configure AdManageKit
90
121
  AdManageKitConfig.apply {
91
122
  debugMode = BuildConfig.DEBUG
@@ -100,16 +131,29 @@ class MyApp : Application() {
100
131
  // Auto-reload interstitial after showing
101
132
  interstitialAutoReload = true // default: true
102
133
  }
134
+ }
103
135
 
104
- // Set up billing
105
- BillingConfig.setPurchaseProvider(BillingPurchaseProvider())
106
-
107
- // Initialize app open ads
108
- appOpenManager = AppOpenManager(this, "your-app-open-ad-unit-id")
136
+ private fun initAds() {
137
+ val config = InitializationConfig.Builder(readApplicationIdFromManifest()).build()
138
+
139
+ // initialize() blocks, so keep it off the main thread or it can ANR.
140
+ Thread {
141
+ MobileAds.initialize(this, config)
142
+
143
+ // Construct AppOpenManager only after initialize() returns. Constructing it
144
+ // arms its ProcessLifecycleOwner observer, and onStart() fires as soon as any
145
+ // activity starts — created earlier, that observer can race ahead of
146
+ // initialization and issue a load the Next-Gen SDK rejects as "not initialized".
147
+ Handler(Looper.getMainLooper()).post {
148
+ appOpenManager = AppOpenManager(this, "your-app-open-ad-unit-id")
149
+ }
150
+ }.start()
109
151
  }
110
152
  }
111
153
  ```
112
154
 
155
+ The Next-Gen SDK no longer reads the application id from the manifest automatically, so `readApplicationIdFromManifest()` pulls `com.google.android.gms.ads.APPLICATION_ID` from your `ApplicationInfo` metadata. See the sample app's [`MyApplication.kt`](https://github.com/i2hammad/AdManageKit/blob/main/app/src/main/java/com/i2hammad/admanagekit/sample/MyApplication.kt) for the full version.
156
+
113
157
  ## Wiki Pages
114
158
 
115
159
  ### Ad Types
@@ -128,6 +172,14 @@ class MyApp : Application() {
128
172
  - [[Multi-Provider Waterfall]] - Load ads from multiple networks with automatic fallback
129
173
  - [[Yandex Integration]] - Yandex Ads SDK provider setup and configuration
130
174
 
175
+ ### Billing
176
+ - [[Billing Integration]] - Play Billing setup, products, and purchase flows
177
+ - [[Purchase Categories]] - Product type classification
178
+ - [[Consumable Products]] - Consumable in-app purchases
179
+ - [[Subscriptions]] - Subscription state, renewal, and account hold
180
+ - [[Subscription Offers]] - Multi-offer paywalls, price comparison, trial eligibility
181
+ - [[Subscription Upgrades]] - Plan changes and proration modes
182
+
131
183
  ## Sample Project
132
184
 
133
185
  The `app` module demonstrates all features. To run:
@@ -1,10 +1,10 @@
1
- # Interstitial Ads - AdManageKit v2.8.0
1
+ # Interstitial Ads - AdManageKit v4.4.3
2
2
 
3
3
  ## Overview
4
4
 
5
5
  AdManageKit provides a complete interstitial ad stack with `AdManager` and the fluent `InterstitialAdBuilder`. Features include loading strategies, automatic retry, frequency controls, splash screen support, and Jetpack Compose utilities.
6
6
 
7
- **Library Version**: v2.8.0
7
+ **Library Version**: v4.4.3
8
8
 
9
9
  ## What's New
10
10
 
@@ -23,11 +23,11 @@ AdManageKit provides a complete interstitial ad stack with `AdManager` and the f
23
23
 
24
24
  ```groovy
25
25
  dependencies {
26
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v2.8.0'
27
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v2.8.0'
28
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v2.8.0'
26
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3'
27
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
28
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v4.4.3'
29
29
  // Optional - Jetpack Compose
30
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v2.8.0'
30
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v4.4.3'
31
31
  }
32
32
  ```
33
33
 
@@ -58,6 +58,8 @@ class MyApp : Application() {
58
58
  }
59
59
  ```
60
60
 
61
+ > **Since 4.2.0 you must also call `MobileAds.initialize()` yourself**, before any ad request — the Next-Gen SDK removed the legacy SDK's silent lazy-init. This snippet covers configuration only. See [[Home]] or the sample app's [`MyApplication.kt`](https://github.com/i2hammad/AdManageKit/blob/main/app/src/main/java/com/i2hammad/admanagekit/sample/MyApplication.kt) for the initialization pattern.
62
+
61
63
  ## Option 1: Direct AdManager
62
64
 
63
65
  ### Basic Usage
@@ -104,6 +106,7 @@ fun showInterstitial(activity: Activity) {
104
106
  | ON_DEMAND | Always fetch fresh ad with dialog |
105
107
  | ONLY_CACHE | Show cached if ready, skip otherwise |
106
108
  | HYBRID | Show cached if ready, fetch fresh otherwise |
109
+ | FRESH_WITH_CACHE_FALLBACK | Fetch fresh, fall back to cache if the load fails |
107
110
 
108
111
  ```kotlin
109
112
  // Set strategy
@@ -1,18 +1,18 @@
1
- # Jetpack Compose Integration - AdManageKit v2.8.0
1
+ # Jetpack Compose Integration - AdManageKit v4.4.3
2
2
 
3
3
  ## Overview
4
4
 
5
5
  AdManageKit provides first-class Jetpack Compose support with composable functions for all ad types, state management helpers, and programmatic native ad loading.
6
6
 
7
- **Library Version**: v2.8.0
7
+ **Library Version**: v4.4.3
8
8
 
9
9
  ## Installation
10
10
 
11
11
  ```groovy
12
12
  dependencies {
13
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v2.8.0'
14
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v2.8.0'
15
- implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v2.8.0'
13
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3'
14
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3'
15
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v4.4.3'
16
16
  }
17
17
  ```
18
18
 
@@ -60,6 +60,27 @@ fun MyScreen() {
60
60
  }
61
61
  ```
62
62
 
63
+ ### Custom Templates & Shimmer (v4.3.0+)
64
+
65
+ If none of the 38 built-in templates fit, pass your own layout instead of a `template`:
66
+
67
+ ```kotlin
68
+ NativeTemplateCompose(
69
+ adUnitId = "ca-app-pub-xxx/yyy",
70
+ customLayoutResId = R.layout.my_native_ad,
71
+ customShimmerResId = R.layout.my_native_ad_shimmer, // recommended, see below
72
+ customSizeHint = NativeAdSize.MEDIUM
73
+ )
74
+ ```
75
+
76
+ `customLayoutResId` takes precedence over `template`. The layout's root must be (or inflate as) a Next-Gen SDK `NativeAdView`, reusing the standard asset ids so the library can bind them: `ad_headline`, `ad_body`, `ad_call_to_action`, `ad_app_icon`, `ad_advertiser`, `ad_media`, `ad_stars`, `ad_choices_view`. Omitted ids are simply not populated, but keep the call-to-action fully visible and tappable — the native ad validator flags clipping as a policy violation.
77
+
78
+ > **`customShimmerResId` is optional, but omitting it is rarely what you want.** The shimmer then falls back to the one belonging to `template` (default `CARD_MODERN`), so a custom layout still shows a placeholder — just one shaped like a different ad, which visibly jumps when the real ad arrives. Either supply a matching shimmer, or set `template` to whichever built-in most resembles your layout so the fallback is the right shape. Passing `0` is the same as omitting it.
79
+
80
+ `customSizeHint` classifies the ad for the cache and gives the Yandex waterfall a fallback size, since a custom layout has no built-in size bucket — `SMALL` (icon + title + CTA), `MEDIUM` (adds body), `LARGE` (adds media). It does not affect how your layout is measured.
81
+
82
+ The XML and programmatic equivalents are covered in [[Native Ads|NativeAdManager]].
83
+
63
84
  ### Traditional Native Composables
64
85
 
65
86
  ```kotlin
@@ -38,11 +38,11 @@ This is fully backward compatible -- if no provider chains are configured, all e
38
38
 
39
39
  ```groovy
40
40
  dependencies {
41
- implementation "com.github.i2hammad.AdManageKit:ad-manage-kit:VERSION"
42
- implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-core:VERSION"
41
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit:v4.4.3"
42
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-core:v4.4.3"
43
43
 
44
44
  // Add Yandex provider
45
- implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:VERSION"
45
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-yandex:v4.4.3"
46
46
  }
47
47
  ```
48
48
 
@@ -161,7 +161,7 @@ if (isRussia) {
161
161
  All existing features continue to work when the waterfall is active:
162
162
 
163
163
  - Time-based and count-based interstitial display
164
- - Loading strategies (ON_DEMAND, ONLY_CACHE, HYBRID)
164
+ - Loading strategies (ON_DEMAND, ONLY_CACHE, HYBRID, FRESH_WITH_CACHE_FALLBACK)
165
165
  - Shimmer loading placeholders
166
166
  - Loading dialogs for interstitials
167
167
  - Welcome back dialog for app open ads