admanagekit-mcp-server 1.0.0

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.
Files changed (74) hide show
  1. package/content/README.md +851 -0
  2. package/content/docs/AD_FREQUENCY_CONTROL.md +450 -0
  3. package/content/docs/AD_LOADING_STRATEGIES.md +369 -0
  4. package/content/docs/API_REFERENCE.md +734 -0
  5. package/content/docs/APP_PURCHASE_GUIDE.md +704 -0
  6. package/content/docs/BANNER_AD_IMPROVEMENTS.md +325 -0
  7. package/content/docs/COMPOSE_INTEGRATION.md +477 -0
  8. package/content/docs/CONFIGURATION_USAGE.md +168 -0
  9. package/content/docs/INTERSTITIAL_BUILDER_GUIDE.md +518 -0
  10. package/content/docs/JAVA_USAGE_GUIDE.md +785 -0
  11. package/content/docs/LOADING_STRATEGY_EXAMPLES.md +463 -0
  12. package/content/docs/NATIVE_AD_MANAGER_ENHANCEMENTS.md +347 -0
  13. package/content/docs/NATIVE_AD_PRELOADING.md +467 -0
  14. package/content/docs/NATIVE_TEMPLATE_VIEW.md +413 -0
  15. package/content/docs/app-open-ads.md +412 -0
  16. package/content/docs/interstitial-ads.md +269 -0
  17. package/content/docs/native-ads-caching.md +182 -0
  18. package/content/docs/release-notes/RELEASE_NOTES_v2.1.0.md +156 -0
  19. package/content/docs/release-notes/RELEASE_NOTES_v2.2.0.md +248 -0
  20. package/content/docs/release-notes/RELEASE_NOTES_v2.3.0.md +280 -0
  21. package/content/docs/release-notes/RELEASE_NOTES_v2.5.0.md +73 -0
  22. package/content/docs/release-notes/RELEASE_NOTES_v2.6.0.md +265 -0
  23. package/content/docs/release-notes/RELEASE_NOTES_v2.7.0.md +168 -0
  24. package/content/docs/release-notes/RELEASE_NOTES_v2.8.0.md +153 -0
  25. package/content/docs/release-notes/RELEASE_NOTES_v2.9.0.md +479 -0
  26. package/content/docs/release-notes/RELEASE_NOTES_v3.0.0.md +343 -0
  27. package/content/docs/release-notes/RELEASE_NOTES_v3.1.0.md +131 -0
  28. package/content/docs/release-notes/RELEASE_NOTES_v3.3.0.md +252 -0
  29. package/content/docs/release-notes/RELEASE_NOTES_v3.3.2.md +215 -0
  30. package/content/docs/release-notes/RELEASE_NOTES_v3.3.3.md +116 -0
  31. package/content/docs/release-notes/RELEASE_NOTES_v3.3.4.md +142 -0
  32. package/content/docs/release-notes/RELEASE_NOTES_v3.3.5.md +94 -0
  33. package/content/docs/rewarded-ads.md +623 -0
  34. package/content/wiki/Ad-Loading-Strategies.md +209 -0
  35. package/content/wiki/App-Open-Ads.md +189 -0
  36. package/content/wiki/Banner-Ads.md +133 -0
  37. package/content/wiki/Billing-Integration.md +69 -0
  38. package/content/wiki/Configuration.md +252 -0
  39. package/content/wiki/Consumable-Products.md +166 -0
  40. package/content/wiki/Home.md +144 -0
  41. package/content/wiki/Interstitial-Ads.md +313 -0
  42. package/content/wiki/Jetpack-Compose.md +270 -0
  43. package/content/wiki/NativeAdManager.md +220 -0
  44. package/content/wiki/Purchase-Categories.md +94 -0
  45. package/content/wiki/Rewarded-Ads.md +420 -0
  46. package/content/wiki/Subscription-Upgrades.md +278 -0
  47. package/content/wiki/Subscriptions.md +368 -0
  48. package/content/wiki/_Footer.md +3 -0
  49. package/content/wiki/_Sidebar.md +18 -0
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.js +6 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/server.d.ts +1 -0
  54. package/dist/server.js +18 -0
  55. package/dist/server.js.map +1 -0
  56. package/dist/tools/code-generation.d.ts +2 -0
  57. package/dist/tools/code-generation.js +264 -0
  58. package/dist/tools/code-generation.js.map +1 -0
  59. package/dist/tools/documentation.d.ts +2 -0
  60. package/dist/tools/documentation.js +202 -0
  61. package/dist/tools/documentation.js.map +1 -0
  62. package/dist/types.d.ts +18 -0
  63. package/dist/types.js +83 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/utils/doc-loader.d.ts +17 -0
  66. package/dist/utils/doc-loader.js +245 -0
  67. package/dist/utils/doc-loader.js.map +1 -0
  68. package/dist/utils/search.d.ts +2 -0
  69. package/dist/utils/search.js +62 -0
  70. package/dist/utils/search.js.map +1 -0
  71. package/dist/utils/templates.d.ts +60 -0
  72. package/dist/utils/templates.js +793 -0
  73. package/dist/utils/templates.js.map +1 -0
  74. package/package.json +51 -0
@@ -0,0 +1,412 @@
1
+ # App Open Ads - AdManageKit v3.3.5
2
+
3
+ ## Overview
4
+
5
+ AdManageKit provides lifecycle-aware app open ad management through the `AppOpenManager` class. App open ads display when users launch or return to your app, with full support for loading strategies, welcome dialogs, activity exclusion, and single-activity architecture.
6
+
7
+ **Library Version**: v3.3.5
8
+ **Last Updated**: January 2025
9
+
10
+ ## What's New in v3.3.5
11
+
12
+ ### Loading Strategy Support
13
+ - **Full AdLoadingStrategy Integration**: AppOpenManager now properly uses `appOpenLoadingStrategy` config
14
+ - **ON_DEMAND**: Fetches fresh ads with welcome dialog, uses cached if still fresh
15
+ - **ONLY_CACHE**: Only shows cached ads instantly, silently loads new if unavailable
16
+ - **HYBRID**: Shows cached if available, fetches with dialog otherwise (recommended)
17
+
18
+ ### Ad Freshness Tracking
19
+ - **Load Time Tracking**: Cached ads now track when they were loaded
20
+ - **Freshness Threshold**: Configurable `appOpenAdFreshnessThreshold` (default: 4 hours)
21
+ - **Smart Cache Usage**: Prevents wasting pre-loaded ads while ensuring freshness
22
+
23
+ ### Auto-Reload Configuration
24
+ - **New Setting**: `appOpenAutoReload` controls automatic reloading after dismissal
25
+ - **Default**: `true` - automatically loads next ad after current one is dismissed
26
+
27
+ ### Deprecations
28
+ - **`appOpenFetchFreshAd`**: Deprecated in favor of `appOpenLoadingStrategy`
29
+ - `appOpenFetchFreshAd = true` → `appOpenLoadingStrategy = AdLoadingStrategy.ON_DEMAND`
30
+ - `appOpenFetchFreshAd = false` → `appOpenLoadingStrategy = AdLoadingStrategy.HYBRID`
31
+
32
+ ---
33
+
34
+ ## Quick Start
35
+
36
+ ### Basic Setup
37
+
38
+ ```kotlin
39
+ class MyApp : Application() {
40
+ private lateinit var appOpenManager: AppOpenManager
41
+
42
+ override fun onCreate() {
43
+ super.onCreate()
44
+
45
+ // Configure loading strategy
46
+ AdManageKitConfig.apply {
47
+ appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
48
+ appOpenAutoReload = true
49
+ }
50
+
51
+ // Set up billing
52
+ BillingConfig.setPurchaseProvider(BillingPurchaseProvider())
53
+
54
+ // Initialize app open manager
55
+ appOpenManager = AppOpenManager(this, "ca-app-pub-xxx/yyy")
56
+ }
57
+ }
58
+ ```
59
+
60
+ That's it! Ads will **automatically load and show** when users open or return to your app.
61
+
62
+ ---
63
+
64
+ ## Loading Strategies
65
+
66
+ Configure via `AdManageKitConfig.appOpenLoadingStrategy`:
67
+
68
+ | Strategy | Behavior | Best For |
69
+ |----------|----------|----------|
70
+ | `ON_DEMAND` | Uses cached if fresh, otherwise fetches with welcome dialog | Maximum coverage |
71
+ | `ONLY_CACHE` | Only shows cached ads instantly, no waiting | Seamless UX |
72
+ | `HYBRID` | Shows cached if available, fetches with dialog if not | Balanced (recommended) |
73
+
74
+ ### ON_DEMAND Strategy
75
+
76
+ ```kotlin
77
+ AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.ON_DEMAND
78
+ ```
79
+
80
+ **Behavior:**
81
+ 1. If cached ad exists and is fresh (within `appOpenAdFreshnessThreshold`), shows it immediately
82
+ 2. If cached ad is stale or doesn't exist, shows welcome dialog and fetches fresh ad
83
+ 3. Shows ad when loaded, or continues without ad on timeout/failure
84
+
85
+ ### ONLY_CACHE Strategy
86
+
87
+ ```kotlin
88
+ AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.ONLY_CACHE
89
+ ```
90
+
91
+ **Behavior:**
92
+ 1. If cached ad exists, shows it immediately
93
+ 2. If no cached ad, continues without showing (no waiting)
94
+ 3. Silently loads new ad in background for next time
95
+
96
+ ### HYBRID Strategy (Recommended)
97
+
98
+ ```kotlin
99
+ AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
100
+ ```
101
+
102
+ **Behavior:**
103
+ 1. If cached ad exists, shows it immediately
104
+ 2. If no cached ad, shows welcome dialog and fetches
105
+ 3. Best balance of coverage and user experience
106
+
107
+ ---
108
+
109
+ ## Configuration
110
+
111
+ ### All App Open Settings
112
+
113
+ ```kotlin
114
+ AdManageKitConfig.apply {
115
+ // Loading strategy (ON_DEMAND, ONLY_CACHE, HYBRID)
116
+ appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
117
+
118
+ // Freshness threshold - cached ads older than this trigger fresh fetch
119
+ appOpenAdFreshnessThreshold = 4.hours // Google recommends max 4 hours
120
+
121
+ // Auto-reload after ad dismissal
122
+ appOpenAutoReload = true // default: true
123
+
124
+ // Timeout for ad loading
125
+ appOpenAdTimeout = 4.seconds
126
+
127
+ // Welcome dialog customization
128
+ welcomeDialogAppIcon = R.mipmap.ic_launcher
129
+ welcomeDialogTitle = "Welcome Back!"
130
+ welcomeDialogSubtitle = "Loading your content..."
131
+ welcomeDialogFooter = "Just a moment..."
132
+ welcomeDialogDismissDelay = 0.8.seconds
133
+
134
+ // Dialog colors
135
+ dialogOverlayColor = 0x80000000.toInt() // 50% black
136
+ dialogCardBackgroundColor = Color.WHITE
137
+ }
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Usage
143
+
144
+ ### Automatic Display
145
+
146
+ App open ads show automatically when the app comes to foreground:
147
+
148
+ ```kotlin
149
+ // Initialize in Application.onCreate()
150
+ appOpenManager = AppOpenManager(this, "ca-app-pub-xxx/yyy")
151
+ // That's it! Ads show automatically
152
+ ```
153
+
154
+ ### Force Show
155
+
156
+ ```kotlin
157
+ appOpenManager.forceShowAdIfAvailable(activity, object : AdManagerCallback() {
158
+ override fun onNextAction() {
159
+ // Ad dismissed or failed - continue with your flow
160
+ navigateToMain()
161
+ }
162
+ override fun onAdLoaded() {
163
+ // Ad was displayed
164
+ }
165
+ })
166
+ ```
167
+
168
+ ### Preload Ad
169
+
170
+ ```kotlin
171
+ // Optional: Preload for faster first show
172
+ appOpenManager.fetchAd()
173
+
174
+ // With callback
175
+ appOpenManager.fetchAd(object : AdLoadCallback() {
176
+ override fun onAdLoaded() {
177
+ Log.d("AppOpen", "Ad preloaded and ready")
178
+ }
179
+ override fun onFailedToLoad(error: AdError?) {
180
+ Log.e("AppOpen", "Preload failed: ${error?.message}")
181
+ }
182
+ })
183
+ ```
184
+
185
+ ### Prefetch Before External Intent
186
+
187
+ ```kotlin
188
+ // Prefetch before launching external activity (camera, share, etc.)
189
+ appOpenManager.prefetchNextAd()
190
+ startActivityForResult(cameraIntent, REQUEST_CODE)
191
+ // Ad will be ready when user returns
192
+ ```
193
+
194
+ ### Check Status
195
+
196
+ ```kotlin
197
+ // Check if ad is loaded and ready
198
+ if (appOpenManager.isAdAvailable()) {
199
+ // Ad is ready to show
200
+ }
201
+
202
+ // Check if ad is currently loading
203
+ if (appOpenManager.isAdLoading()) {
204
+ // Ad is being fetched
205
+ }
206
+
207
+ // Get cached ad age
208
+ val ageMs = appOpenManager.getCachedAdAgeMs()
209
+ if (ageMs > 0) {
210
+ Log.d("AppOpen", "Cached ad is ${ageMs / 1000}s old")
211
+ }
212
+ ```
213
+
214
+ ### Skip Next Ad
215
+
216
+ ```kotlin
217
+ // Skip the next automatic ad (e.g., after purchase or important action)
218
+ appOpenManager.skipNextAd()
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Activity/Screen Exclusion
224
+
225
+ ### Exclude Activities
226
+
227
+ ```kotlin
228
+ // Exclude specific activities from showing ads
229
+ appOpenManager.disableAppOpenWithActivity(SplashActivity::class.java)
230
+ appOpenManager.disableAppOpenWithActivity(PaymentActivity::class.java)
231
+
232
+ // Re-enable later if needed
233
+ appOpenManager.includeAppOpenActivityForAds(SplashActivity::class.java)
234
+ ```
235
+
236
+ ### Single-Activity Architecture (Fragments/Compose)
237
+
238
+ For apps with one activity and multiple screens:
239
+
240
+ ```kotlin
241
+ // Set current screen tag when navigating
242
+ navController.addOnDestinationChangedListener { _, destination, _ ->
243
+ appOpenManager.setCurrentScreenTag(destination.label?.toString())
244
+ }
245
+
246
+ // Exclude specific screens by tag
247
+ appOpenManager.excludeScreenTags("Payment", "Onboarding", "Checkout")
248
+
249
+ // Or use fragment tag provider
250
+ appOpenManager.setFragmentTagProvider {
251
+ supportFragmentManager.fragments.lastOrNull()?.tag
252
+ }
253
+ appOpenManager.excludeFragmentTags("PaymentFragment", "OnboardingFragment")
254
+ ```
255
+
256
+ ### Temporary Disable
257
+
258
+ ```kotlin
259
+ // Temporarily disable during critical flows
260
+ appOpenManager.disableAppOpenAdsTemporarily()
261
+ // ... perform operation ...
262
+ appOpenManager.enableAppOpenAds()
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Migration from appOpenFetchFreshAd
268
+
269
+ If you were using `appOpenFetchFreshAd`, migrate to `appOpenLoadingStrategy`:
270
+
271
+ ```kotlin
272
+ // Before (deprecated)
273
+ AdManageKitConfig.appOpenFetchFreshAd = true // Always fetch fresh
274
+
275
+ // After
276
+ AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.ON_DEMAND
277
+ ```
278
+
279
+ ```kotlin
280
+ // Before (deprecated)
281
+ AdManageKitConfig.appOpenFetchFreshAd = false // Use cached when available
282
+
283
+ // After
284
+ AdManageKitConfig.appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
285
+ ```
286
+
287
+ ---
288
+
289
+ ## API Reference
290
+
291
+ ### AppOpenManager Methods
292
+
293
+ | Method | Description |
294
+ |--------|-------------|
295
+ | `fetchAd()` | Preload ad in background |
296
+ | `fetchAd(callback, timeout, customAdUnitId)` | Preload with options |
297
+ | `showAdIfAvailable()` | Show if cached (lifecycle triggered) |
298
+ | `forceShowAdIfAvailable(activity, callback)` | Force show with callback |
299
+ | `isAdAvailable()` | Check if ad is cached |
300
+ | `isAdLoading()` | Check if ad is being fetched |
301
+ | `getCachedAdAgeMs()` | Get age of cached ad in milliseconds |
302
+ | `prefetchNextAd()` | Prefetch before external intent |
303
+ | `skipNextAd()` | Skip next automatic ad |
304
+ | `disableAppOpenWithActivity(class)` | Exclude activity |
305
+ | `includeAppOpenActivityForAds(class)` | Re-include activity |
306
+ | `setCurrentScreenTag(tag)` | Set current screen for single-activity apps |
307
+ | `excludeScreenTags(vararg tags)` | Exclude screens by tag |
308
+ | `disableAppOpenAdsTemporarily()` | Temporarily disable |
309
+ | `enableAppOpenAds()` | Re-enable after temporary disable |
310
+
311
+ ### AdManageKitConfig Settings
312
+
313
+ | Setting | Description | Default |
314
+ |---------|-------------|---------|
315
+ | `appOpenLoadingStrategy` | Loading strategy | `HYBRID` |
316
+ | `appOpenAdFreshnessThreshold` | Max age for "fresh" cached ad | 4 hours |
317
+ | `appOpenAutoReload` | Auto-reload after dismissal | `true` |
318
+ | `appOpenAdTimeout` | Load timeout | 4 seconds |
319
+ | `welcomeDialogAppIcon` | App icon resource | 0 |
320
+ | `welcomeDialogTitle` | Dialog title | "Welcome Back!" |
321
+ | `welcomeDialogSubtitle` | Dialog subtitle | "Loading..." |
322
+ | `welcomeDialogFooter` | Dialog footer | "Just a moment..." |
323
+ | `welcomeDialogDismissDelay` | Delay before dismiss | 0.8 seconds |
324
+ | `dialogOverlayColor` | Overlay color | 50% black |
325
+ | `dialogCardBackgroundColor` | Card background | Theme default |
326
+
327
+ ---
328
+
329
+ ## Best Practices
330
+
331
+ 1. **Initialize in Application** - Set up `AppOpenManager` in `Application.onCreate()`
332
+ 2. **Use HYBRID Strategy** - Best balance of coverage and UX
333
+ 3. **Set App Icon** - Configure `welcomeDialogAppIcon` for branded welcome dialog
334
+ 4. **Exclude Sensitive Screens** - Payment, onboarding, splash screens
335
+ 5. **Skip After Important Actions** - Call `skipNextAd()` after purchases
336
+ 6. **Prefetch Before External Intents** - Use `prefetchNextAd()` before camera/share
337
+ 7. **Wire Billing** - Ensure premium users don't see ads
338
+
339
+ ---
340
+
341
+ ## Troubleshooting
342
+
343
+ ### Ad Not Showing
344
+
345
+ 1. **Check availability**: `appOpenManager.isAdAvailable()`
346
+ 2. **Check exclusion list**: Is current activity/screen excluded?
347
+ 3. **Check purchase status**: `BillingConfig.getPurchaseProvider().isPurchased()`
348
+ 4. **Check loading**: `appOpenManager.isAdLoading()`
349
+
350
+ ### Stale Ads Showing
351
+
352
+ Reduce the freshness threshold:
353
+ ```kotlin
354
+ AdManageKitConfig.appOpenAdFreshnessThreshold = 2.hours
355
+ ```
356
+
357
+ ### Ad Not Reloading
358
+
359
+ Check auto-reload setting:
360
+ ```kotlin
361
+ AdManageKitConfig.appOpenAutoReload = true
362
+ ```
363
+
364
+ ### Strategy Not Working
365
+
366
+ Ensure you're on v3.3.5+ and using `appOpenLoadingStrategy` (not deprecated `appOpenFetchFreshAd`).
367
+
368
+ ---
369
+
370
+ ## Firebase Analytics Events
371
+
372
+ AppOpenManager automatically logs these events:
373
+
374
+ | Event | Description |
375
+ |-------|-------------|
376
+ | `ad_impression` | Ad was shown |
377
+ | `ad_paid_event` | Revenue tracking |
378
+ | `ad_failed_to_load` | Load failure with error code |
379
+ | `ad_request` | Ad request initiated |
380
+ | `ad_fill` | Ad successfully loaded |
381
+
382
+ ---
383
+
384
+ ## Changelog
385
+
386
+ ### v3.3.5 (January 2025)
387
+ - Full `AdLoadingStrategy` support (ON_DEMAND, ONLY_CACHE, HYBRID)
388
+ - Ad freshness tracking with `appOpenAdFreshnessThreshold`
389
+ - Auto-reload configuration with `appOpenAutoReload`
390
+ - Deprecated `appOpenFetchFreshAd` in favor of `appOpenLoadingStrategy`
391
+ - Fixed auto-reload after ad dismissal
392
+
393
+ ### v3.2.0
394
+ - Single-activity architecture support
395
+ - Screen/fragment tag exclusion
396
+ - Temporary disable/enable
397
+
398
+ ### v3.0.0
399
+ - Ad prefetching with `prefetchNextAd()`
400
+ - `isAdLoading()` status check
401
+
402
+ ### v2.8.0
403
+ - Welcome dialog with customization
404
+ - Loading strategy configuration
405
+
406
+ ---
407
+
408
+ ## References
409
+
410
+ - [AdMob App Open Ads](https://developers.google.com/admob/android/app-open-ads)
411
+ - [GitHub Repository](https://github.com/i2hammad/AdManageKit)
412
+ - [API Documentation](https://i2hammad.github.io/AdManageKit/)
@@ -0,0 +1,269 @@
1
+ # Interstitial Ads · AdManageKit v2.8.0
2
+
3
+ ## Overview
4
+ `AdManageKit` 2.8.0 ships a complete interstitial stack that spans `AdManager`, the fluent `InterstitialAdBuilder`, and brand-new Jetpack Compose utilities. The stack now includes automatic retry with exponential backoff, lifecycle-safe splash loading, fallback ad units, activity-aware purchase gating, and Compose state helpers. Everything is fully backward compatible with the traditional view-based APIs while enabling declarative use in Compose apps.
5
+
6
+ **What's new in v2.8.0**
7
+ - `forceShowInterstitial()` now respects global loading strategy
8
+ - New `forceShowInterstitialAlways()` for explicit force fetch
9
+ - Global `interstitialAutoReload` config with per-call override
10
+ - All AdManager methods use global auto-reload config as default
11
+
12
+ **What's new in v2.7.0**
13
+ - Smart splash screen with `waitForLoading()` in InterstitialAdBuilder
14
+ - New `isLoading()` and `showOrWaitForAd()` methods
15
+ - Frequency controls: `everyNthTime`, `maxShows`, `minInterval`
16
+
17
+ **What's new since v1.x**
18
+ - Jetpack Compose helpers: `rememberInterstitialAd`, `InterstitialAdEffect`, `rememberInterstitialAdState`
19
+ - Fluent builder with frequency controls (`everyNthTime`, `maxShows`, `minInterval`, `.force()`) and fallback chains
20
+ - Automatic retry via `AdRetryManager` (circuit breaker removed to maximize show rate)
21
+ - Splash-friendly `loadInterstitialAdForSplash(...)` with timeouts and callbacks
22
+ - Debug overlays, aggressive pre-loading helpers, and test-mode overrides wired through `AdManageKitConfig`
23
+
24
+ ---
25
+
26
+ ## Installation
27
+ Add the v2.8.0 artifacts plus Compose (if needed):
28
+
29
+ ```groovy
30
+ dependencies {
31
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit:v2.8.0"
32
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-core:v2.8.0"
33
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v2.8.0"
34
+ // Optional – Jetpack Compose helpers:
35
+ implementation "com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v2.8.0"
36
+ }
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Configure Once
42
+ Set the new centralized config inside `Application.onCreate()`:
43
+
44
+ ```kotlin
45
+ class MyApp : Application() {
46
+ override fun onCreate() {
47
+ super.onCreate()
48
+
49
+ BillingConfig.setPurchaseProvider(BillingPurchaseProvider())
50
+
51
+ AdManageKitConfig.apply {
52
+ debugMode = BuildConfig.DEBUG
53
+ defaultInterstitialInterval = 20.seconds
54
+ autoRetryFailedAds = true
55
+ maxRetryAttempts = 3
56
+ enableAdaptiveIntervals = true
57
+ enablePerformanceMetrics = BuildConfig.DEBUG
58
+
59
+ // Loading strategy (v2.6.0+)
60
+ interstitialLoadingStrategy = AdLoadingStrategy.HYBRID
61
+
62
+ // Auto-reload after showing (v2.8.0+)
63
+ interstitialAutoReload = true // default: true
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ `AdManageKitConfig` now drives retry timing, adaptive intervals, loading strategy, auto-reload, analytics, and debug overlays for every interstitial entry-point.
70
+
71
+ ---
72
+
73
+ ## Option 1 · Direct `AdManager`
74
+
75
+ `AdManager` lives in `com.i2hammad.admanagekit.admob` and exposes imperative control with smart defaults.
76
+
77
+ ```kotlin
78
+ private val adManager = AdManager.getInstance()
79
+
80
+ fun preloadInterstitial(activity: Activity) {
81
+ adManager.loadInterstitialAd(activity, AD_UNIT_INTERSTITIAL)
82
+ }
83
+
84
+ fun showInterstitial(activity: Activity) {
85
+ adManager.showInterstitialAdByTime(activity, object : AdManagerCallback() {
86
+ override fun onNextAction() {
87
+ navigateNext()
88
+ }
89
+ })
90
+ }
91
+ ```
92
+
93
+ ### Key APIs
94
+ - `loadInterstitialAdForSplash(context, unit, timeoutMs, callback)` – timeouts + callback chain for splash flows
95
+ - `forceShowInterstitial(activity, callback)` – respects loading strategy (v2.8.0+)
96
+ - `forceShowInterstitialAlways(activity, callback)` – always force fetch (bypasses strategy, v2.8.0+)
97
+ - `showInterstitialIfReady(activity, callback, reloadAd)` – show only if cached
98
+ - `showInterstitialAdByTime(...)` & `showInterstitialAdByCount(...)` – throttle via interval or count
99
+ - `forceShowInterstitialWithDialog(...)` – built-in loading dialog for smoother UX
100
+ - `showOrWaitForAd(activity, callback, timeout, showDialog)` – smart splash screen method (v2.7.0+)
101
+ - `isLoading()` – check if ad is currently loading (v2.7.0+)
102
+ - `preloadAd(context, adUnitId)` – kicks off background loading for next screen
103
+ - `enableAggressiveAdLoading()` / `resetAdThrottling()` – quick helpers for tuning show rate
104
+
105
+ ### Advanced Behavior
106
+ - **Purchase-aware**: `BillingConfig` short-circuits loading/showing when a user owns the IAP/subscription.
107
+ - **Auto retry**: Failed loads automatically use `AdRetryManager` with exponential backoff based on `AdManageKitConfig`.
108
+ - **Analytics**: All impressions, failures, dismissals, and paid events are logged through Firebase Analytics when configured.
109
+
110
+ ### Splash Screen Example
111
+ ```kotlin
112
+ AdManager.getInstance().loadInterstitialAdForSplash(
113
+ context = this,
114
+ adUnitId = getString(R.string.interstitial_splash),
115
+ timeoutMillis = 7_000,
116
+ callback = object : AdManagerCallback() {
117
+ override fun onAdLoaded() { startMainFlow() }
118
+ override fun onFailedToLoad(error: AdError?) { startMainFlow() }
119
+ override fun onNextAction() { startMainFlow() }
120
+ }
121
+ )
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Option 2 · `InterstitialAdBuilder`
127
+
128
+ The builder (also under `admob`) wraps `AdManager` with a fluent API, fallback chains, loading dialogs, and frequency controls.
129
+
130
+ ```kotlin
131
+ InterstitialAdBuilder.with(this)
132
+ .adUnit(getString(R.string.interstitial_home))
133
+ .fallbacks(
134
+ getString(R.string.interstitial_backup_a),
135
+ getString(R.string.interstitial_backup_b)
136
+ )
137
+ .everyNthTime(2) // show every 2nd invocation
138
+ .maxShows(12) // cap session exposure
139
+ .minIntervalSeconds(45) // respect UX
140
+ .withLoadingDialog()
141
+ .onAdShown { analytics.logEvent("interstitial_shown", null) }
142
+ .onFailed { error -> Log.w("Ads", "Failed: ${error.message}") }
143
+ .show { continueToNextScreen() }
144
+ ```
145
+
146
+ ### Highlights
147
+ - `.everyNthTime(n)` – enforce cadence per trigger point
148
+ - `.maxShows(count)` – share the global `AdManager` counter to cap exposure
149
+ - `.minInterval(millis)` / `.minIntervalSeconds(seconds)` – override global interval without touching config
150
+ - `.force()` or `.respectInterval(false)` – bypass timers when needed (e.g., exit flows)
151
+ - `.fallback()` / `.fallbacks()` – try multiple ad units automatically
152
+ - `.preload()` – warm up future screens without showing
153
+
154
+ Builder callbacks have Java-friendly interfaces (`OnAdCompleteListener`, `OnAdShownListener`, etc.), so the same API works across Kotlin and Java modules.
155
+
156
+ ---
157
+
158
+ ## Option 3 · Jetpack Compose
159
+
160
+ The Compose module brings stateful helpers that wrap the same business logic.
161
+
162
+ ```kotlin
163
+ @Composable
164
+ fun ContentWithInterstitial() {
165
+ val showAd = rememberInterstitialAd(
166
+ adUnitId = stringResource(R.string.interstitial_feed),
167
+ preloadAd = true,
168
+ onAdShown = { analytics.logEvent("feed_interstitial_shown", null) },
169
+ onAdDismissed = { navigateNext() },
170
+ onAdFailedToLoad = { reason -> Log.w("Ads", reason) }
171
+ )
172
+
173
+ Button(onClick = showAd) {
174
+ Text("Open next article")
175
+ }
176
+ }
177
+ ```
178
+
179
+ Additional helpers:
180
+
181
+ | Helper | Purpose |
182
+ |--------|---------|
183
+ | `InterstitialAdEffect(adUnitId, showMode, maxDisplayCount)` | Declarative effect that respects TIME / COUNT / FORCE modes. |
184
+ | `rememberInterstitialAdState(adUnitId)` | Mutable state holder exposing `isLoaded`, `loadAd()`, `showAdByTime()`, `forceShowAd()` for custom UI flows. |
185
+ | `AdManageKitInitEffect()` | Initializes NativeAdManager/FirebaseAnalytics inside Compose entry points so cache stats stay accurate. |
186
+
187
+ Compose helpers automatically reload on lifecycle events and integrate with `BillingConfig` purchase checks.
188
+
189
+ ---
190
+
191
+ ## Advanced Controls
192
+
193
+ - **Retry Tuning** – `AdManageKitConfig.autoRetryFailedAds`, `maxRetryAttempts`, `baseRetryDelay`, `maxRetryDelay`, and `enableExponentialBackoff` control how `AdRetryManager` behaves per ad unit.
194
+ - **Aggressive Mode** – call `AdManager.enableAggressiveAdLoading()` during experiments to drop the interval to 5 seconds, then `resetAdThrottling()` before going live.
195
+ - **Debug Overlay** – enable via `AdManageKitConfig.debugMode = true` and `AdDebugUtils.enableDebugOverlay(activity, true)` to inspect attempts, cache hits, and paid events in-app.
196
+ - **Testing** – set `AdManageKitConfig.testMode = true` or map production IDs to test IDs with `AdDebugUtils.setTestAdUnits(mapOf(prodId to testId))`.
197
+
198
+ ---
199
+
200
+ ## API Cheat Sheet
201
+
202
+ | API | Description |
203
+ |-----|-------------|
204
+ | `AdManager.loadInterstitialAd(context, adUnitId)` | Preloads and caches one interstitial per unit. |
205
+ | `AdManager.loadInterstitialAd(context, unit, callback)` | Same as above but surfaces `InterstitialAdLoadCallback`. |
206
+ | `AdManager.loadInterstitialAdForSplash(...)` | Splash-friendly load with timeout + callback. |
207
+ | `AdManager.forceShowInterstitial(activity, callback)` | Respects loading strategy (v2.8.0+). |
208
+ | `AdManager.forceShowInterstitialAlways(activity, callback)` | Always force fetch, bypasses strategy (v2.8.0+). |
209
+ | `AdManager.showInterstitialIfReady(activity, callback, reloadAd)` | Show only if cached. |
210
+ | `AdManager.showInterstitialAdByTime` / `showInterstitialAdByCount` | Throttle via time interval or count. |
211
+ | `AdManager.forceShowInterstitialWithDialog` | Uses built-in dialog, respects strategy. |
212
+ | `AdManager.showOrWaitForAd(...)` | Smart splash screen method (v2.7.0+). |
213
+ | `AdManager.isLoading()` | Check if ad is currently loading (v2.7.0+). |
214
+ | `AdManager.preloadAd` / `resetAdThrottling` / `enableAggressiveAdLoading` | Utility helpers for show-rate tuning. |
215
+ | `InterstitialAdBuilder.with(activity)` | Entry point for the fluent API (Kotlin + Java). |
216
+ | `InterstitialAdBuilder.autoReload(Boolean)` | Override global auto-reload setting (v2.8.0+). |
217
+ | `InterstitialAdBuilder.waitForLoading()` | Smart splash screen behavior (v2.7.0+). |
218
+ | `rememberInterstitialAd`, `InterstitialAdEffect`, `rememberInterstitialAdState` | Compose-first APIs for declarative UI. |
219
+
220
+ ---
221
+
222
+ ## Best Practices
223
+
224
+ - **Configure once** in `Application` and rely on builder/Compose APIs per screen—don’t sprinkle config logic in activities.
225
+ - **Always preload** on the previous screen (builder `.preload()` or `AdManager.preloadAd`) for maximum fill rate.
226
+ - **Use frequency controls** (`everyNthTime`, `maxShows`, `minInterval`) plus `AdManageKitConfig.defaultInterstitialInterval` to protect UX.
227
+ - **Respect purchases** by always wiring a `BillingPurchaseProvider` before loading—`AdManager` skips ads automatically.
228
+ - **Enable debug overlay** in QA builds to verify retries, cache state, and paid events before shipping.
229
+
230
+ With these updates, interstitial integration stays identical for legacy XML screens, gains new fluent APIs for Java/Kotlin, and becomes fully declarative in Compose-heavy codebases—all powered by the same resilient core.
231
+
232
+ ## Best Practices
233
+ - **Purchase Integration**: Ensure `BillingConfig.setPurchaseProvider` is called in your `Application` class to respect in-app purchases.
234
+ - **Ad Frequency**: Use `setAdInterval` or `showInterstitialAdByCount` to avoid overwhelming users with frequent ads.
235
+ - **Dialog Usage**: Use `forceShowInterstitialWithDialog` for smoother transitions in critical flows (e.g., activity changes).
236
+ - **Error Handling**: Implement `AdManagerCallback` and `InterstitialAdLoadCallback` to handle load/display failures gracefully.
237
+ - **Testing**:
238
+ - Test with AdMob test IDs (e.g., `ca-app-pub-3940256099942544/1033173712`).
239
+ - Verify time-based and count-based triggers.
240
+ - Test purchase scenarios to ensure ads are skipped for premium users.
241
+ - **Analytics**: Review Firebase Analytics logs to monitor ad performance and errors.
242
+
243
+ ## Limitations
244
+ - **Single Ad Cache**: Only one interstitial ad is cached at a time per `AdManager` instance.
245
+ - **Manual Frequency Control**: Time and count limits are managed manually; adjust `adIntervalMillis` or `maxDisplayCount` as needed.
246
+ - **Dialog Dependency**: The loading dialog requires Material Components; ensure it’s included in your app.
247
+
248
+ ## Dependencies
249
+ - **Google AdMob SDK**: For ad loading and display.
250
+ - **Firebase Analytics**: For logging ad events.
251
+ - **Material Components**: For loading dialogs.
252
+ - **Project Resources**: `BillingConfig` for purchase checks.
253
+
254
+ ## Troubleshooting
255
+ - **Ad Not Loading**: Verify `adUnitId`, network connectivity, and AdMob configuration.
256
+ - **Ad Not Displaying**: Check `isReady()` and ensure the user hasn’t purchased the app.
257
+ - **Dialog Issues**: Ensure Material Components are included and the activity isn’t finishing.
258
+ - **Analytics Missing**: Confirm Firebase is initialized and configured.
259
+
260
+ ## Future Improvements
261
+ - Support for preloading multiple interstitial ads.
262
+ - Configurable dialog duration and styling.
263
+ - Automatic frequency optimization based on user engagement.
264
+
265
+ ## References
266
+ - [AdMob Interstitial Ads Documentation](https://developers.google.com/admob/android/interstitial)
267
+ - [Firebase Analytics Documentation](https://firebase.google.com/docs/analytics)
268
+ - [AdManageKit v2.5.0 Release Notes](../RELEASE_NOTES_v2.5.0.md)
269
+ - [Native Ads Caching Wiki](native-ads-caching.md)