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,851 @@
1
+ # AdManageKit
2
+ [![JitPack](https://jitpack.io/v/i2hammad/AdManageKit.svg)](https://jitpack.io/#i2hammad/AdManageKit)
3
+ ![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)
4
+ ![License](https://img.shields.io/badge/License-MIT-blue.svg)
5
+
6
+ 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.
7
+
8
+ **Latest Version `3.3.5`** adds **App Open Loading Strategies** - proper loading strategy support (ON_DEMAND, ONLY_CACHE, HYBRID) with ad freshness tracking and auto-reload configuration.
9
+
10
+ ---
11
+
12
+ ## Next-Gen GMA SDK Version
13
+
14
+ > **Beta Notice:** The Next-Gen GMA SDK (`com.google.android.libraries.ads.mobile.sdk`) is currently in **beta by Google**, and AdManageKit's nextgen branch is also in **beta**. The underlying Google SDK may receive breaking changes until it reaches stable release. For production use, the **main branch** is the stable option.
15
+
16
+ AdManageKit offers a **Next-Gen GMA SDK** version on the `nextgen` branch, featuring Google's modern preloader-based ad loading system.
17
+
18
+ ### Why Next-Gen?
19
+
20
+ | Feature | Main Branch (GMS SDK) | Next-Gen Branch |
21
+ |---------|----------------------|-----------------|
22
+ | SDK | `play-services-ads` (stable) | `ads-mobile-sdk` (beta) |
23
+ | Ad Loading | Traditional load/show | Preloader-based with auto-refill |
24
+ | Threading | Manual main thread dispatch | Automatic background thread safety |
25
+ | Buffer System | N/A | Configurable ad buffers per type |
26
+ | Background Handling | Basic | Smart pending ad queue |
27
+
28
+ ### Next-Gen Features
29
+
30
+ - **Preloader System**: SDK automatically loads next ad after one is consumed
31
+ - **Background-Aware Ads**: App open ads won't show when app is in background
32
+ - **Pending Ad Queue**: Ads that load while backgrounded are saved for return
33
+ - **Configurable Buffers**: Set how many ads to keep ready per type
34
+
35
+ ```kotlin
36
+ // Next-Gen preloader configuration
37
+ AdManageKitConfig.apply {
38
+ enableInterstitialPreloader = true
39
+ enableAppOpenPreloader = true
40
+ interstitialPreloaderBufferSize = 2
41
+ }
42
+ ```
43
+
44
+ ### Migration Compatibility
45
+
46
+ Both branches use the same callback signatures via type aliases:
47
+ - `AdKitError` → resolves to appropriate SDK error type
48
+ - `AdKitLoadError` → resolves to appropriate SDK load error type
49
+ - `AdKitValue` → resolves to appropriate SDK value type
50
+
51
+ Your callback implementations work on both branches without changes.
52
+
53
+ ### Which Version Should I Use?
54
+
55
+ | Use Case | Recommended |
56
+ |----------|-------------|
57
+ | Production apps (stable) | **Main branch** (v3.3.5) |
58
+ | New projects wanting latest features | **Nextgen branch** (v4.1.1) |
59
+ | Testing preloader system | **Nextgen branch** |
60
+ | Risk-averse production | **Main branch** |
61
+
62
+ ---
63
+
64
+ ## What's New in 3.3.5
65
+
66
+ ### App Open Loading Strategies
67
+ - **Proper Loading Strategy Support**: AppOpenManager now fully supports `AdLoadingStrategy` (ON_DEMAND, ONLY_CACHE, HYBRID)
68
+ - **Ad Freshness Tracking**: Cached ads track load time to prevent showing stale ads
69
+ - **Smart Cache Usage**: ON_DEMAND strategy uses cached ads if still fresh (within `appOpenAdFreshnessThreshold`)
70
+ - **Auto-Reload Config**: New `appOpenAutoReload` setting to control automatic reloading after ad dismissal
71
+ - **Deprecated**: `appOpenFetchFreshAd` - migrate to `appOpenLoadingStrategy`
72
+
73
+ ```kotlin
74
+ AdManageKitConfig.apply {
75
+ // Loading strategy (ON_DEMAND, ONLY_CACHE, HYBRID)
76
+ appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
77
+
78
+ // Freshness threshold for cached ads (default: 4 hours)
79
+ appOpenAdFreshnessThreshold = 4.hours
80
+
81
+ // Auto-reload after ad dismissal (default: true)
82
+ appOpenAutoReload = true
83
+ }
84
+ ```
85
+
86
+ ## What's New in 3.3.4
87
+
88
+ ### Subscription Expiry Verification
89
+ - **Server-Side Verification**: New API to verify subscriptions and get accurate expiry dates from your backend
90
+ - **Expiry Methods**: `getExpiryTimeFormatted()`, `getRemainingDays()`, `isExpired()` on PurchaseResult
91
+ - **AppPurchase Helpers**: `getSubscriptionExpiryTime()`, `getSubscriptionRemainingDays()`, `isSubscriptionExpired()`
92
+
93
+ ```kotlin
94
+ // Set up verification callback
95
+ AppPurchase.getInstance().setSubscriptionVerificationCallback { packageName, subscriptionId, purchaseToken, listener ->
96
+ yourApi.verifySubscription(purchaseToken) { expiryMillis ->
97
+ val details = SubscriptionVerificationCallback.SubscriptionDetails.Builder()
98
+ .setExpiryTimeMillis(expiryMillis)
99
+ .build()
100
+ listener.onVerified(details)
101
+ }
102
+ }
103
+
104
+ // Verify and get expiry
105
+ AppPurchase.getInstance().verifySubscription("premium_monthly",
106
+ object : AppPurchase.SubscriptionVerificationListener {
107
+ override fun onVerified(subscription: PurchaseResult) {
108
+ val expiryDate = subscription.getExpiryTimeFormatted("dd MMM yyyy")
109
+ val daysLeft = subscription.getRemainingDays()
110
+ }
111
+ override fun onVerificationFailed(error: String?) { }
112
+ }
113
+ )
114
+ ```
115
+
116
+ ## What's New in 3.3.3
117
+
118
+ ### SDK-Agnostic Type Aliases
119
+ - **Migration Compatibility**: Callbacks use `AdKitError`, `AdKitLoadError`, `AdKitValue` type aliases
120
+ - **Same Signatures**: Your callback implementations work across both SDK versions
121
+ - **Easy Migration**: Switch between main (GMS SDK) and nextgen (Next-Gen SDK) branches without code changes
122
+
123
+ ```kotlin
124
+ // Callbacks now use type aliases that resolve to the appropriate SDK types
125
+ object : AdLoadCallback() {
126
+ override fun onFailedToLoad(error: AdKitError?) { // Works on both branches
127
+ Log.e("Ads", "Failed: ${error?.message}")
128
+ }
129
+ override fun onPaidEvent(adValue: AdKitValue) { // Works on both branches
130
+ trackRevenue(adValue.valueMicros)
131
+ }
132
+ }
133
+ ```
134
+
135
+ ## What's New in 3.3.2
136
+
137
+ ### InterstitialAdBuilder Fixes
138
+ - **Ad Unit Assignment**: Fixed ad unit not being assigned to AdManager on first HYBRID fetch
139
+ - **Immediate Availability**: `adUnit()` now sets AdManager.adUnitId immediately for first-call reliability
140
+
141
+ ### everyNthTime Feature Fix
142
+ - **Counter Persistence**: Call counter now persists across builder instances in AdManager
143
+ - **Counter API**: New methods to manage counters: `getCallCount()`, `resetCallCount()`, `resetAllCallCounts()`
144
+
145
+ ```kotlin
146
+ // everyNthTime now works correctly
147
+ InterstitialAdBuilder.with(activity)
148
+ .adUnit(adUnitId)
149
+ .everyNthTime(3) // Shows on 3rd, 6th, 9th calls, etc.
150
+ .show { navigateNext() }
151
+
152
+ // Reset counters when user upgrades
153
+ AdManager.getInstance().resetAllCallCounts()
154
+ ```
155
+
156
+ ### New Native Templates
157
+ - **flexible**: Adaptive layout that adjusts to available space
158
+ - **icon_left**: Icon on left side with MediaView at top for GridView display
159
+ - **top_icon_media**: Icon at top, MediaView in middle, CTA at bottom
160
+
161
+ ```kotlin
162
+ nativeTemplateView.setTemplate(NativeAdTemplate.FLEXIBLE)
163
+ nativeTemplateView.setTemplate(NativeAdTemplate.ICON_LEFT)
164
+ nativeTemplateView.setTemplate(NativeAdTemplate.TOP_ICON_MEDIA)
165
+ ```
166
+
167
+ ## What's New in 3.1.0
168
+
169
+ ### FRESH_WITH_CACHE_FALLBACK Strategy Fix
170
+ - **Auto-Caching**: Successfully loaded ads are now properly cached for future fallback
171
+ - **RecyclerView Optimized**: Fresh ads build up the cache over time for better fallback availability
172
+ - **Complete Implementation**: Strategy now works as documented
173
+
174
+ ### New Native Template
175
+ - **MEDIUM_HORIZONTAL**: 55% media (left) / 45% content (right) horizontal split layout
176
+ - **27 Total Templates**: 21 standard + 6 video templates
177
+
178
+ ## What's New in 3.0.0
179
+
180
+ ### Ad Pool System
181
+ - **Multiple Ad Units**: Load multiple interstitial ad units into a pool for maximum show rate
182
+ - **Auto-Selection**: Shows ANY available ad from the pool when requested
183
+ - **Duplicate Prevention**: Automatically skips duplicate load requests
184
+
185
+ ### Smart Splash Ads
186
+ - **showOrWaitForAd()**: Single method handles all splash scenarios automatically
187
+ - **Intelligent Behavior**: Shows cached ad immediately, waits if loading, or fetches fresh
188
+
189
+ ### App Open Ad Prefetching
190
+ - **prefetchNextAd()**: Prefetch ads before external intents for instant display on return
191
+ - **isAdLoading()**: Check if ad is currently being fetched
192
+
193
+ ### Enhanced Analytics
194
+ - **Session Tracking**: Fill rate, show rate, and impression tracking
195
+ - **getAdStats()**: Access session-level ad performance metrics
196
+
197
+ ### Technical Improvements
198
+ - Modern `WindowInsetsController` API (replaces deprecated systemUiVisibility)
199
+ - Thread-safe ad pool with `ConcurrentHashMap`
200
+ - Cross-ad-unit fallback for native ads
201
+
202
+ ## Screenshots
203
+
204
+ | NativeBannerSmall Ad | Interstitial Ad | App Open Ad | UMP Consent Form |
205
+ |----------------------|-----------------|-----------------|------------------|
206
+ | ![NativeBannerSmall ad displayed in app](docs/assets/native_ad_small_screenshot.png) | ![Interstitial ad with loading dialog](docs/assets/interstitial_ad_screenshot.png) | ![App open ad on app launch](docs/assets/app_open_ad_screenshot.png) | ![UMP consent form](docs/assets/ump_consent_screenshot.png) |
207
+
208
+ ## Demo Video
209
+
210
+ Watch a short demo of `AdManageKit` in action:
211
+
212
+ [Watch on YouTube](https://youtube.com/shorts/h_872tOARpU)
213
+
214
+ ## Getting Started
215
+
216
+ ### Installation
217
+
218
+ **Step 1:** Add JitPack to your root `build.gradle`:
219
+
220
+ ```groovy
221
+ dependencyResolutionManagement {
222
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
223
+ repositories {
224
+ mavenCentral()
225
+ maven { url 'https://jitpack.io' }
226
+ }
227
+ }
228
+ ```
229
+
230
+ **Step 2:** Add dependencies to your app's `build.gradle`:
231
+
232
+ <table>
233
+ <tr>
234
+ <th>Main Branch (Stable GMS SDK)</th>
235
+ <th>Next-Gen Branch (Beta GMA SDK)</th>
236
+ </tr>
237
+ <tr>
238
+ <td>
239
+
240
+ ```groovy
241
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.3.5'
242
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.3.5'
243
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.3.5'
244
+
245
+ // For Jetpack Compose support
246
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.3.5'
247
+ ```
248
+
249
+ </td>
250
+ <td>
251
+
252
+ ```groovy
253
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-nextgen:v4.1.1'
254
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing-nextgen:v4.1.1'
255
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core-nextgen:v4.1.1'
256
+
257
+ // For Jetpack Compose support
258
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose-nextgen:v4.1.1'
259
+ ```
260
+
261
+ </td>
262
+ </tr>
263
+ </table>
264
+
265
+ **Step 3:** Sync your project with Gradle.
266
+
267
+ ## Features
268
+
269
+ ### NativeTemplateView (v2.6.0+)
270
+ - **27 Template Styles**: card_modern, material3, app_store, social_feed, gradient_card, pill_banner, medium_horizontal, flexible, icon_left, top_icon_media, spotlight, and more
271
+ - **XML & Programmatic**: Set templates via `app:adTemplate` or `setTemplate()`
272
+ - **Material 3 Theming**: Automatic dark/light mode support
273
+ - **AdChoices Control**: Configure placement position (v2.9.0+)
274
+ - **Video-Ready**: All templates support video ads (120dp+ MediaView)
275
+ - [View Documentation](docs/NATIVE_TEMPLATE_VIEW.md)
276
+
277
+ ### Ad Loading Strategies (v2.6.0+)
278
+ - **ON_DEMAND**: Fetch fresh ads with loading dialog
279
+ - **ONLY_CACHE**: Instant display from cache
280
+ - **HYBRID**: Cache-first with fallback fetch (recommended)
281
+ - [View Documentation](docs/AD_LOADING_STRATEGIES.md)
282
+
283
+ ### Jetpack Compose Integration
284
+ - BannerAdCompose, NativeAdCompose, InterstitialAdCompose
285
+ - Programmatic native ads without predefined layouts
286
+ - ConditionalAd, CacheWarmingEffect utilities
287
+
288
+ ### AdMob Ads Management
289
+ - **Banner Ads**: Auto-refresh, collapsible banners, smart retry
290
+ - **Native Ads**: Small, Medium, Large formats with caching
291
+ - **Interstitial Ads**: Time/count-based triggers, dialog support
292
+ - **App Open Ads**: Lifecycle-aware with activity exclusion
293
+
294
+ ### Centralized Configuration
295
+ - **AdManageKitConfig**: Single configuration point
296
+ - Environment-specific settings (debug vs production)
297
+ - Runtime configuration changes
298
+
299
+ ### Intelligent Native Ad Caching
300
+ - Screen-aware caching prevents collisions
301
+ - Smart preloading with usage patterns
302
+ - LRU cache with configurable expiration
303
+
304
+ ### Reliability & Performance
305
+ - Smart retry with exponential backoff
306
+ - Circuit breaker for failing ad units
307
+ - Memory leak prevention with WeakReference
308
+
309
+ ### Privacy & Compliance
310
+ - UMP consent management (GDPR/CCPA)
311
+ - Automatic ad hiding for purchased users
312
+
313
+ ### Multi-Module Architecture
314
+ - **Core Module**: Shared interfaces and configuration
315
+ - **Compose Module**: Jetpack Compose integration
316
+ - **Billing Module**: Google Play Billing Library v8
317
+
318
+ ---
319
+
320
+ ## Usage Guide
321
+
322
+ ### Quick Configuration
323
+
324
+ Configure AdManageKit in your Application class:
325
+
326
+ ```kotlin
327
+ class MyApp : Application() {
328
+ private lateinit var appOpenManager: AppOpenManager
329
+
330
+ override fun onCreate() {
331
+ super.onCreate()
332
+
333
+ // Configure AdManageKit
334
+ AdManageKitConfig.apply {
335
+ debugMode = BuildConfig.DEBUG
336
+ enableSmartPreloading = true
337
+ autoRetryFailedAds = true
338
+
339
+ // Ad Loading Strategies (v2.6.0+)
340
+ interstitialLoadingStrategy = AdLoadingStrategy.HYBRID
341
+ appOpenLoadingStrategy = AdLoadingStrategy.HYBRID
342
+ nativeLoadingStrategy = AdLoadingStrategy.HYBRID
343
+
344
+ // Auto-reload ads after showing (v2.7.0+)
345
+ interstitialAutoReload = true // default: true
346
+ appOpenAutoReload = true // default: true
347
+ rewardedAutoReload = true // default: true
348
+ }
349
+
350
+ // Set up billing
351
+ BillingConfig.setPurchaseProvider(BillingPurchaseProvider())
352
+
353
+ // Initialize app open ads
354
+ appOpenManager = AppOpenManager(this, "your-app-open-ad-unit-id")
355
+ }
356
+ }
357
+ ```
358
+
359
+ ### NativeTemplateView (v2.6.0+)
360
+
361
+ #### XML Usage
362
+
363
+ ```xml
364
+ <com.i2hammad.admanagekit.admob.NativeTemplateView
365
+ android:id="@+id/nativeTemplateView"
366
+ android:layout_width="match_parent"
367
+ android:layout_height="wrap_content"
368
+ app:adTemplate="material3" />
369
+ ```
370
+
371
+ #### Available Templates
372
+
373
+ | Template | Best For |
374
+ |----------|----------|
375
+ | `card_modern` | General use |
376
+ | `material3` | M3 apps |
377
+ | `minimal` | Content-focused |
378
+ | `compact_horizontal` | Lists |
379
+ | `list_item` | RecyclerView items |
380
+ | `magazine` | News/blog apps |
381
+ | `app_store` | App promotion (v2.9.0+) |
382
+ | `social_feed` | Feed integration (v2.9.0+) |
383
+ | `gradient_card` | Premium feel (v2.9.0+) |
384
+ | `pill_banner` | Inline placement (v2.9.0+) |
385
+ | `medium_horizontal` | 55/45 media-content split (v3.0.0+) |
386
+ | `spotlight` | High visibility (v2.9.0+) |
387
+ | `media_content_split` | Balanced display (v2.9.0+) |
388
+ | `flexible` | Adaptive layout (v3.3.2+) |
389
+ | `icon_left` | Icon on left, GridView optimized (v3.3.2+) |
390
+ | `top_icon_media` | Icon at top, MediaView center (v3.3.2+) |
391
+ | `video_small/medium/large` | Video content |
392
+ | `video_square/vertical/fullscreen` | Social feeds |
393
+
394
+ #### Programmatic Usage
395
+
396
+ ```kotlin
397
+ // Load with default template
398
+ nativeTemplateView.loadNativeAd(activity, "ca-app-pub-xxx/yyy")
399
+
400
+ // Change template
401
+ nativeTemplateView.setTemplate(NativeAdTemplate.MAGAZINE)
402
+ nativeTemplateView.loadNativeAd(activity, "ca-app-pub-xxx/yyy")
403
+
404
+ // With callback
405
+ nativeTemplateView.loadNativeAd(activity, adUnitId, object : AdLoadCallback() {
406
+ override fun onAdLoaded() { /* success */ }
407
+ override fun onFailedToLoad(error: AdError?) { /* error */ }
408
+ })
409
+
410
+ // With strategy override
411
+ nativeTemplateView.loadNativeAd(activity, adUnitId, callback, AdLoadingStrategy.ONLY_CACHE)
412
+ ```
413
+
414
+ ### Banner Ads
415
+
416
+ ```xml
417
+ <com.i2hammad.admanagekit.admob.BannerAdView
418
+ android:id="@+id/bannerAdView"
419
+ android:layout_width="match_parent"
420
+ android:layout_height="wrap_content" />
421
+ ```
422
+
423
+ ```kotlin
424
+ bannerAdView.loadBanner(this, "ca-app-pub-xxx/yyy")
425
+ // Collapsible banner
426
+ bannerAdView.loadCollapsibleBanner(this, "ca-app-pub-xxx/yyy", true)
427
+ ```
428
+
429
+ ### Native Ads (Traditional Views)
430
+
431
+ ```xml
432
+ <com.i2hammad.admanagekit.admob.NativeBannerSmall
433
+ android:id="@+id/nativeBannerSmall"
434
+ android:layout_width="match_parent"
435
+ android:layout_height="wrap_content" />
436
+ ```
437
+
438
+ ```kotlin
439
+ nativeBannerSmall.loadNativeBannerAd(this, "ca-app-pub-xxx/yyy")
440
+ // With caching
441
+ nativeBannerSmall.loadNativeBannerAd(activity, adUnitId, useCachedAd = true)
442
+ ```
443
+
444
+ ### Interstitial Ads
445
+
446
+ ```kotlin
447
+ // Load
448
+ AdManager.getInstance().loadInterstitialAd(this, "ca-app-pub-xxx/yyy")
449
+
450
+ // Show immediately
451
+ AdManager.getInstance().forceShowInterstitial(this, object : AdManagerCallback() {
452
+ override fun onNextAction() { navigateNext() }
453
+ })
454
+
455
+ // Show with dialog
456
+ AdManager.getInstance().forceShowInterstitialWithDialog(this, callback)
457
+
458
+ // Time-based (every 15 seconds)
459
+ AdManager.getInstance().showInterstitialAdByTime(this, callback)
460
+
461
+ // Count-based
462
+ AdManager.getInstance().showInterstitialAdByCount(this, callback, maxDisplayCount = 3)
463
+ ```
464
+
465
+ #### Auto-Reload Configuration (v2.7.0+)
466
+
467
+ Control whether interstitial ads automatically reload after being shown:
468
+
469
+ ```kotlin
470
+ // Global config (applies to all AdManager methods)
471
+ AdManageKitConfig.interstitialAutoReload = false // Disable auto-reload
472
+
473
+ // Per-call override via InterstitialAdBuilder
474
+ InterstitialAdBuilder.with(activity)
475
+ .adUnit(adUnitId)
476
+ .autoReload(true) // Override global setting for this call
477
+ .show { navigateNext() }
478
+
479
+ // Per-call override via AdManager
480
+ AdManager.getInstance().showInterstitialIfReady(activity, callback, reloadAd = false)
481
+ ```
482
+
483
+ **Priority:** `InterstitialAdBuilder.autoReload()` > `AdManageKitConfig.interstitialAutoReload`
484
+
485
+ ### Rewarded Ads
486
+
487
+ ```kotlin
488
+ // Initialize once (e.g., in Application.onCreate())
489
+ RewardedAdManager.initialize(context, "ca-app-pub-xxx/yyy")
490
+
491
+ // Show when ready
492
+ if (RewardedAdManager.isAdLoaded()) {
493
+ RewardedAdManager.showAd(activity, object : RewardedAdManager.RewardedAdCallback {
494
+ override fun onRewardEarned(rewardType: String, rewardAmount: Int) {
495
+ grantReward(rewardType, rewardAmount)
496
+ }
497
+ override fun onAdDismissed() {
498
+ continueGameFlow()
499
+ }
500
+ })
501
+ }
502
+
503
+ // Load with timeout (splash screens)
504
+ RewardedAdManager.loadRewardedAdWithTimeout(context, 5000, callback)
505
+
506
+ // Preload during natural pauses
507
+ RewardedAdManager.preload(context)
508
+
509
+ // Control auto-reload
510
+ AdManageKitConfig.rewardedAutoReload = false // Disable globally
511
+ RewardedAdManager.showAd(activity, callback, autoReload = false) // Per-call override
512
+ ```
513
+
514
+ ### App Open Ads
515
+
516
+ ```kotlin
517
+ // In Application class
518
+ appOpenManager = AppOpenManager(this, "ca-app-pub-xxx/yyy")
519
+
520
+ // Exclude activities
521
+ appOpenManager.disableAppOpenWithActivity(MainActivity::class.java)
522
+
523
+ // Force show
524
+ appOpenManager.forceShowAdIfAvailable(activity, callback)
525
+
526
+ // Skip next ad
527
+ appOpenManager.skipNextAd()
528
+ ```
529
+
530
+ #### Single-Activity App Support (v3.2.0+)
531
+
532
+ For apps with one activity and multiple fragments:
533
+
534
+ ```kotlin
535
+ // Set current screen when navigating
536
+ navController.addOnDestinationChangedListener { _, destination, _ ->
537
+ appOpenManager.setCurrentScreenTag(destination.label?.toString())
538
+ }
539
+
540
+ // Exclude specific screens
541
+ appOpenManager.excludeScreenTags("Payment", "Onboarding", "Checkout")
542
+
543
+ // Or use fragment tag provider
544
+ appOpenManager.setFragmentTagProvider {
545
+ supportFragmentManager.fragments.lastOrNull()?.tag
546
+ }
547
+ appOpenManager.excludeFragmentTags("PaymentFragment", "OnboardingFragment")
548
+
549
+ // Temporarily disable during critical flows
550
+ appOpenManager.disableAppOpenAdsTemporarily()
551
+ // ... perform operation ...
552
+ appOpenManager.enableAppOpenAds()
553
+ ```
554
+
555
+ ### Jetpack Compose
556
+
557
+ ```kotlin
558
+ @Composable
559
+ fun MyScreen() {
560
+ // Banner
561
+ BannerAdCompose(adUnitId = "ca-app-pub-xxx/yyy")
562
+
563
+ // NativeTemplateView with any template (v2.6.0+)
564
+ NativeTemplateCompose(
565
+ adUnitId = "ca-app-pub-xxx/yyy",
566
+ template = NativeAdTemplate.MATERIAL3,
567
+ loadingStrategy = AdLoadingStrategy.HYBRID
568
+ )
569
+
570
+ // Native with loading strategy (ON_DEMAND or HYBRID only)
571
+ NativeBannerMediumCompose(
572
+ adUnitId = "ca-app-pub-xxx/yyy",
573
+ loadingStrategy = AdLoadingStrategy.HYBRID
574
+ )
575
+
576
+ // Interstitial
577
+ val showInterstitial = rememberInterstitialAd(
578
+ adUnitId = "ca-app-pub-xxx/yyy",
579
+ preloadAd = true
580
+ )
581
+ Button(onClick = { showInterstitial() }) {
582
+ Text("Show Ad")
583
+ }
584
+
585
+ // Conditional (hides for purchased users)
586
+ ConditionalAd {
587
+ ProgrammaticNativeBannerMediumCompose(adUnitId = "ca-app-pub-xxx/yyy")
588
+ }
589
+ }
590
+ ```
591
+
592
+ ### UMP Consent
593
+
594
+ ```kotlin
595
+ AdsConsentManager.getInstance(this).requestUMP(
596
+ activity = this,
597
+ isDebug = true,
598
+ testDeviceId = "TEST_DEVICE_ID",
599
+ resetConsent = false,
600
+ listener = object : UMPResultListener {
601
+ override fun onCheckUMPSuccess(isConsentGiven: Boolean) {
602
+ if (isConsentGiven) {
603
+ // Initialize and load ads here
604
+ AdManager.getInstance().loadInterstitialAd(activity, adUnitId)
605
+ }
606
+ }
607
+ }
608
+ )
609
+ ```
610
+
611
+ ### In-App Purchases (v2.9.0+)
612
+
613
+ ```kotlin
614
+ // Define products with categories
615
+ val products = listOf(
616
+ PurchaseItem("coins_100", TYPE_IAP.PURCHASE, PurchaseCategory.CONSUMABLE),
617
+ PurchaseItem("remove_ads", TYPE_IAP.PURCHASE, PurchaseCategory.REMOVE_ADS),
618
+ PurchaseItem("lifetime", TYPE_IAP.PURCHASE, PurchaseCategory.LIFETIME_PREMIUM),
619
+ PurchaseItem("premium_monthly", "free_trial", TYPE_IAP.SUBSCRIPTION)
620
+ )
621
+
622
+ // Initialize
623
+ AppPurchase.getInstance().initBilling(application, products)
624
+
625
+ // Purchase
626
+ AppPurchase.getInstance().purchase(activity, "remove_ads")
627
+
628
+ // Subscribe
629
+ AppPurchase.getInstance().subscribe(activity, "premium_monthly")
630
+
631
+ // Check status
632
+ if (AppPurchase.getInstance().isPurchased()) {
633
+ // User has premium (subscription, lifetime, or remove_ads)
634
+ }
635
+
636
+ // Track purchases and handle consumables
637
+ AppPurchase.getInstance().setPurchaseHistoryListener(object : PurchaseHistoryListener {
638
+ override fun onNewPurchase(productId: String, purchase: PurchaseResult) {
639
+ if (productId == "coins_100") {
640
+ addCoins(100 * purchase.quantity)
641
+ AppPurchase.getInstance().consumePurchase(productId) // Manual consume
642
+ }
643
+ }
644
+ override fun onPurchaseConsumed(productId: String, purchase: PurchaseResult) { }
645
+ })
646
+ ```
647
+
648
+ #### Subscription Management (v2.9.0+)
649
+
650
+ ```kotlin
651
+ // Check subscription state
652
+ val state = AppPurchase.getInstance().getSubscriptionState("premium_monthly")
653
+ when (state) {
654
+ SubscriptionState.ACTIVE -> showPremiumUI()
655
+ SubscriptionState.CANCELLED -> showRenewalPrompt() // Still has access
656
+ SubscriptionState.EXPIRED -> showSubscribeButton()
657
+ }
658
+
659
+ // Upgrade subscription
660
+ AppPurchase.getInstance().upgradeSubscription(activity, "premium_yearly")
661
+
662
+ // Downgrade subscription
663
+ AppPurchase.getInstance().downgradeSubscription(activity, "premium_basic")
664
+
665
+ // Full control with proration mode
666
+ AppPurchase.getInstance().changeSubscription(
667
+ activity,
668
+ "premium_monthly",
669
+ "premium_yearly",
670
+ SubscriptionReplacementMode.CHARGE_PRORATED_PRICE
671
+ )
672
+ ```
673
+
674
+ ---
675
+
676
+ ## Documentation
677
+
678
+ - [NativeTemplateView Guide](docs/NATIVE_TEMPLATE_VIEW.md)
679
+ - [Ad Loading Strategies](docs/AD_LOADING_STRATEGIES.md)
680
+ - [Jetpack Compose Integration](docs/COMPOSE_INTEGRATION.md)
681
+ - [Native Ads Caching](docs/native-ads-caching.md)
682
+ - [Interstitial Ads](docs/interstitial-ads.md)
683
+ - [Rewarded Ads](docs/rewarded-ads.md)
684
+ - [App Open Ads](docs/app-open-ads.md)
685
+ - [Billing Integration Guide](docs/APP_PURCHASE_GUIDE.md)
686
+ - [Release Notes v3.3.5](docs/release-notes/RELEASE_NOTES_v3.3.5.md)
687
+ - [Release Notes v3.3.4](docs/release-notes/RELEASE_NOTES_v3.3.4.md)
688
+ - [Release Notes v3.3.3](docs/release-notes/RELEASE_NOTES_v3.3.3.md)
689
+ - [Release Notes v3.3.2](docs/release-notes/RELEASE_NOTES_v3.3.2.md)
690
+ - [Release Notes v3.3.0](docs/release-notes/RELEASE_NOTES_v3.3.0.md)
691
+ - [Release Notes v3.1.0](docs/release-notes/RELEASE_NOTES_v3.1.0.md)
692
+ - [Release Notes v3.0.0](docs/release-notes/RELEASE_NOTES_v3.0.0.md)
693
+ - [API Reference](docs/API_REFERENCE.md)
694
+
695
+ ### Wiki
696
+ - [Rewarded Ads](wiki/Rewarded-Ads.md)
697
+ - [Billing Integration](wiki/Billing-Integration.md)
698
+ - [Purchase Categories](wiki/Purchase-Categories.md)
699
+ - [Consumable Products](wiki/Consumable-Products.md)
700
+ - [Subscriptions](wiki/Subscriptions.md)
701
+ - [Subscription Upgrades](wiki/Subscription-Upgrades.md)
702
+
703
+ ### API Documentation (Dokka)
704
+
705
+ **Online:** [https://i2hammad.github.io/AdManageKit/](https://i2hammad.github.io/AdManageKit/)
706
+
707
+ Generate locally:
708
+
709
+ ```bash
710
+ ./gradlew dokkaHtmlMultiModule
711
+ ```
712
+
713
+ Output: `build/dokka/htmlMultiModule/index.html`
714
+
715
+ ---
716
+
717
+ ## Migration Guide
718
+
719
+ ### Migrating to 3.0.0
720
+
721
+ Version 3.0.0 is **fully backward compatible**. Optionally adopt new features:
722
+
723
+ #### Smart Splash Ads (Recommended)
724
+
725
+ Replace separate load + show calls with single `showOrWaitForAd()`:
726
+
727
+ ```kotlin
728
+ // Before (v2.9.0) - Two-step approach
729
+ AdManager.getInstance().loadInterstitialAdForSplash(this, adUnitId, 10_000, object : AdManagerCallback() {
730
+ override fun onNextAction() {
731
+ AdManager.getInstance().forceShowInterstitial(this@SplashActivity, callback)
732
+ }
733
+ })
734
+
735
+ // After (v3.0.0) - Single smart call
736
+ AdManager.getInstance().showOrWaitForAd(
737
+ activity = this,
738
+ callback = object : AdManagerCallback() {
739
+ override fun onNextAction() { navigateNext() }
740
+ },
741
+ timeoutMillis = 10_000
742
+ )
743
+ ```
744
+
745
+ #### Ad Pool for Higher Show Rate
746
+
747
+ ```kotlin
748
+ // Before (single ad unit)
749
+ AdManager.getInstance().loadInterstitialAd(context, "single_unit")
750
+
751
+ // After (multiple ad units for redundancy)
752
+ AdManager.getInstance().loadMultipleAdUnits(context, "high_ecpm", "medium_ecpm", "fallback")
753
+ ```
754
+
755
+ #### App Open Ad Prefetching
756
+
757
+ ```kotlin
758
+ // Prefetch before external intents
759
+ appOpenManager.prefetchNextAd()
760
+ startActivityForResult(cameraIntent, REQUEST_CODE)
761
+ ```
762
+
763
+ ### Migrating to 2.9.0
764
+
765
+ Version 2.9.0 has **one breaking change** for consumable products:
766
+
767
+ **Consumables are no longer auto-consumed.** You must manually call `consumePurchase()`:
768
+
769
+ ```kotlin
770
+ // Before v2.9.0 (auto-consume)
771
+ AppPurchase.getInstance().setConsumePurchase(true) // Deprecated
772
+
773
+ // After v2.9.0 (manual consume)
774
+ AppPurchase.getInstance().setPurchaseHistoryListener(object : PurchaseHistoryListener {
775
+ override fun onNewPurchase(productId: String, purchase: PurchaseResult) {
776
+ grantItems(productId, purchase.quantity)
777
+ AppPurchase.getInstance().consumePurchase(productId) // Manual!
778
+ }
779
+ override fun onPurchaseConsumed(productId: String, purchase: PurchaseResult) { }
780
+ })
781
+ ```
782
+
783
+ **Use Purchase Categories** for better product classification:
784
+
785
+ ```kotlin
786
+ // Before
787
+ PurchaseItem("coins", TYPE_IAP.PURCHASE, true) // isConsumable
788
+
789
+ // After (explicit categories)
790
+ PurchaseItem("coins", TYPE_IAP.PURCHASE, PurchaseCategory.CONSUMABLE)
791
+ PurchaseItem("remove_ads", TYPE_IAP.PURCHASE, PurchaseCategory.REMOVE_ADS)
792
+ ```
793
+
794
+ ### Migrating to 2.8.0
795
+
796
+ Version 2.8.0 is **fully backward compatible** with one behavioral change:
797
+
798
+ **`forceShowInterstitial()` now respects loading strategy:**
799
+ ```kotlin
800
+ // If you need old behavior (always force fetch), use:
801
+ AdManager.getInstance().forceShowInterstitialAlways(activity, callback)
802
+
803
+ // Or set strategy to ON_DEMAND globally:
804
+ AdManageKitConfig.interstitialLoadingStrategy = AdLoadingStrategy.ON_DEMAND
805
+ ```
806
+
807
+ ### Migrating to 2.7.0
808
+
809
+ Version 2.7.0 is **fully backward compatible**. Optionally adopt new features:
810
+
811
+ ```kotlin
812
+ // Old way (still works)
813
+ val nativeBannerMedium = NativeBannerMedium(context)
814
+ nativeBannerMedium.loadNativeBannerAd(activity, adUnitId)
815
+
816
+ // New unified approach
817
+ val nativeTemplateView = NativeTemplateView(context)
818
+ nativeTemplateView.setTemplate(NativeAdTemplate.CARD_MODERN)
819
+ nativeTemplateView.loadNativeAd(activity, adUnitId)
820
+ ```
821
+
822
+ ---
823
+
824
+ ## Sample Project
825
+
826
+ The `app` module demonstrates all features. To run:
827
+
828
+ 1. Clone: `git clone https://github.com/i2hammad/AdManageKit.git`
829
+ 2. Open in Android Studio
830
+ 3. Replace placeholder AdMob IDs
831
+ 4. Run on device or emulator
832
+
833
+ ---
834
+
835
+ ## Contributing
836
+
837
+ 1. Fork the repository
838
+ 2. Create a branch (`git checkout -b feature/YourFeature`)
839
+ 3. Commit changes (`git commit -m 'Add YourFeature'`)
840
+ 4. Push (`git push origin feature/YourFeature`)
841
+ 5. Open a Pull Request
842
+
843
+ ## License
844
+
845
+ Licensed under the MIT License. See [LICENSE](LICENSE).
846
+
847
+ ## Support
848
+
849
+ [Buy me a coffee](https://buymeacoffee.com/i2hammad)
850
+
851
+ For issues: [GitHub Issues](https://github.com/i2hammad/AdManageKit/issues) or [hammadmughal0001@gmail.com](mailto:hammadmughal0001@gmail.com)