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,479 @@
1
+ # Release Notes - v2.9.0
2
+
3
+ ## Highlights
4
+
5
+ - **6 New Native Ad Templates**: APP_STORE, SOCIAL_FEED, GRADIENT_CARD, PILL_BANNER, SPOTLIGHT, MEDIA_CONTENT_SPLIT
6
+ - **AdChoices Placement Control**: Configure AdChoices position in NativeTemplateView
7
+ - **Enhanced Purchase Tracking**: Comprehensive purchase categorization system (Consumable, Lifetime, Remove Ads, Subscription)
8
+ - **Purchase History Listener**: Track purchases and consumption events for your own persistence
9
+ - **Subscription Lifecycle Management**: Active, Cancelled, Expired state detection with upgrade/downgrade support
10
+ - **Improved PurchaseResult**: Full data capture including signature, originalJson, account identifiers
11
+ - **No Auto-Consume**: Developers have full control over when to consume purchases
12
+ - **Dependency Updates**: Google Play Billing 8.1.0, AdMob 24.8.0, Firebase 34.6.0, Lifecycle 2.10.0
13
+
14
+ ---
15
+
16
+ ## New Features
17
+
18
+ ### Native Ad Templates
19
+
20
+ #### 6 New Templates
21
+
22
+ | Template | Description | Best For |
23
+ |----------|-------------|----------|
24
+ | `APP_STORE` | App listing style with large icon and download button | App promotion |
25
+ | `SOCIAL_FEED` | Social media post style | Feed integration |
26
+ | `GRADIENT_CARD` | Modern card with gradient background | Premium feel |
27
+ | `PILL_BANNER` | Compact pill-shaped banner | Inline placement |
28
+ | `SPOTLIGHT` | Hero/spotlight style with emphasis | High visibility |
29
+ | `MEDIA_CONTENT_SPLIT` | Split layout with media and content | Balanced display |
30
+
31
+ ```kotlin
32
+ // Use new templates in XML
33
+ <com.i2hammad.admanagekit.admob.NativeTemplateView
34
+ android:layout_width="match_parent"
35
+ android:layout_height="wrap_content"
36
+ app:adTemplate="app_store" />
37
+
38
+ // Or programmatically
39
+ nativeTemplateView.setTemplate(NativeAdTemplate.SOCIAL_FEED)
40
+ ```
41
+
42
+ #### AdChoices Placement Control
43
+
44
+ Configure AdChoices icon position:
45
+
46
+ ```kotlin
47
+ // Programmatic control
48
+ nativeTemplateView.setAdChoicesPlacement(
49
+ NativeAdOptions.ADCHOICES_TOP_LEFT,
50
+ useSDKPlacement = true // Use SDK auto-placement instead of XML position
51
+ )
52
+
53
+ // Or use template's XML-defined position (default)
54
+ nativeTemplateView.setUseCustomAdChoicesView(true)
55
+ ```
56
+
57
+ **XML attribute:**
58
+ ```xml
59
+ <com.i2hammad.admanagekit.admob.NativeTemplateView
60
+ app:adChoicesPlacement="top_left" />
61
+ ```
62
+
63
+ Options: `top_left`, `top_right` (default), `bottom_left`, `bottom_right`
64
+
65
+ ---
66
+
67
+ ### Billing Module
68
+
69
+ ### 1. Purchase Categories
70
+
71
+ Products can now be categorized for better tracking and ad-disabling logic:
72
+
73
+ ```kotlin
74
+ enum class PurchaseCategory {
75
+ CONSUMABLE, // Coins, gems (can buy multiple times)
76
+ FEATURE_UNLOCK, // Unlock level pack (one-time, doesn't disable ads)
77
+ LIFETIME_PREMIUM, // Permanent premium (disables ads)
78
+ REMOVE_ADS // Remove ads only (disables ads)
79
+ }
80
+
81
+ // Usage
82
+ val items = listOf(
83
+ PurchaseItem("coins_100", TYPE_IAP.PURCHASE, PurchaseCategory.CONSUMABLE),
84
+ PurchaseItem("remove_ads", TYPE_IAP.PURCHASE, PurchaseCategory.REMOVE_ADS),
85
+ PurchaseItem("lifetime_premium", TYPE_IAP.PURCHASE, PurchaseCategory.LIFETIME_PREMIUM),
86
+ PurchaseItem("premium_monthly", "free_trial", TYPE_IAP.SUBSCRIPTION)
87
+ )
88
+ ```
89
+
90
+ ### 2. Purchase History Listener
91
+
92
+ Track all purchase events for your own persistence/analytics:
93
+
94
+ ```kotlin
95
+ AppPurchase.getInstance().setPurchaseHistoryListener(object : PurchaseHistoryListener {
96
+ override fun onNewPurchase(productId: String, purchase: PurchaseResult) {
97
+ // Purchase acknowledged - save to your database
98
+ // Includes: orderId, quantity, purchaseTime, originalJson, signature
99
+ savePurchase(productId, purchase)
100
+
101
+ // For consumables: grant items then consume
102
+ if (productId == "coins_100") {
103
+ userBalance += 100 * purchase.quantity
104
+ AppPurchase.getInstance().consumePurchase(productId)
105
+ }
106
+ }
107
+
108
+ override fun onPurchaseConsumed(productId: String, purchase: PurchaseResult) {
109
+ // Mark as consumed in your tracking system
110
+ markConsumed(productId, purchase.orderId)
111
+ }
112
+ })
113
+ ```
114
+
115
+ ### 3. Subscription State Management
116
+
117
+ Detect subscription lifecycle states:
118
+
119
+ ```kotlin
120
+ // Check subscription state
121
+ val state = AppPurchase.getInstance().getSubscriptionState("premium_monthly")
122
+ when (state) {
123
+ SubscriptionState.ACTIVE -> showPremiumUI()
124
+ SubscriptionState.CANCELLED -> showCancelledWarning() // Still has access
125
+ SubscriptionState.EXPIRED -> showSubscribeButton()
126
+ }
127
+
128
+ // Helper methods
129
+ AppPurchase.getInstance().isSubscribed() // Any active subscription
130
+ AppPurchase.getInstance().hasSubscriptionCancelled() // User cancelled
131
+ AppPurchase.getInstance().willSubscriptionsRenew() // All will renew
132
+ ```
133
+
134
+ ### 4. Subscription Upgrade/Downgrade
135
+
136
+ Full support for subscription changes with proration modes:
137
+
138
+ ```kotlin
139
+ // Simple upgrade (charges price difference immediately)
140
+ AppPurchase.getInstance().upgradeSubscription(activity, "premium_yearly")
141
+
142
+ // Simple downgrade (takes effect at next renewal)
143
+ AppPurchase.getInstance().downgradeSubscription(activity, "premium_basic")
144
+
145
+ // Full control with custom proration
146
+ AppPurchase.getInstance().changeSubscription(
147
+ activity,
148
+ "premium_monthly", // Current subscription
149
+ "premium_yearly", // New subscription
150
+ SubscriptionReplacementMode.CHARGE_PRORATED_PRICE
151
+ )
152
+ ```
153
+
154
+ **Replacement Modes:**
155
+
156
+ | Mode | Use Case | Effect |
157
+ |------|----------|--------|
158
+ | `CHARGE_PRORATED_PRICE` | Upgrades | User pays price difference now |
159
+ | `DEFERRED` | Downgrades | Change at next renewal |
160
+ | `WITH_TIME_PRORATION` | Either | Immediate, remaining value credited |
161
+ | `CHARGE_FULL_PRICE` | Either | Immediate, full price charged |
162
+ | `WITHOUT_PRORATION` | Either | Immediate, no price adjustment |
163
+
164
+ ### 5. Enhanced PurchaseResult
165
+
166
+ Comprehensive purchase data from Billing Library v8:
167
+
168
+ ```kotlin
169
+ val result = PurchaseResult.fromPurchase(purchase)
170
+
171
+ // New fields
172
+ result.originalJson // For server-side verification
173
+ result.signature // For signature verification
174
+ result.obfuscatedAccountId // Account identifier
175
+ result.obfuscatedProfileId // Profile identifier
176
+ result.productType // "inapp" or "subs"
177
+ result.isConsumed // Consumption tracking
178
+ result.consumedTime // When consumed
179
+
180
+ // Helper methods
181
+ result.isPurchased() // PURCHASED state
182
+ result.isPending() // PENDING state
183
+ result.getFirstProductId() // Primary product ID
184
+ result.getPurchaseTimeFormatted() // "2024-01-15 14:30:00"
185
+ result.hasVerificationData() // Has json + signature
186
+ result.isSubscriptionActive() // Has access (active or cancelled)
187
+ result.willSubscriptionRenew() // Will auto-renew
188
+ result.getSubscriptionStateString() // "Active", "Cancelled", etc.
189
+ ```
190
+
191
+ ### 6. Smart `isPurchased()` Logic
192
+
193
+ Only ad-disabling purchases affect `isPurchased()`:
194
+
195
+ ```kotlin
196
+ // Returns true for:
197
+ // - Active subscriptions
198
+ // - LIFETIME_PREMIUM purchases
199
+ // - REMOVE_ADS purchases
200
+
201
+ // Returns false for:
202
+ // - Consumable purchases (coins, gems)
203
+ // - Feature unlocks (unless configured to disable ads)
204
+ // - No purchases
205
+ ```
206
+
207
+ ---
208
+
209
+ ## API Changes
210
+
211
+ ### NativeAdTemplate - New Templates
212
+
213
+ | Template | Layout | Shimmer |
214
+ |----------|--------|---------|
215
+ | `APP_STORE` | `layout_native_app_store` | `layout_shimmer_app_store` |
216
+ | `SOCIAL_FEED` | `layout_native_social_feed` | `layout_shimmer_social_feed` |
217
+ | `GRADIENT_CARD` | `layout_native_gradient_card` | `layout_shimmer_gradient_card` |
218
+ | `PILL_BANNER` | `layout_native_pill_banner` | `layout_shimmer_pill_banner` |
219
+ | `SPOTLIGHT` | `layout_native_spotlight` | `layout_shimmer_spotlight` |
220
+ | `MEDIA_CONTENT_SPLIT` | `layout_native_media_content_split` | `layout_shimmer_media_content_split` |
221
+
222
+ ### NativeTemplateView - New Methods
223
+
224
+ | Method | Description |
225
+ |--------|-------------|
226
+ | `setAdChoicesPlacement(placement, useSDKPlacement)` | Set AdChoices icon position |
227
+ | `getAdChoicesPlacement()` | Get current AdChoices placement |
228
+ | `setUseCustomAdChoicesView(useCustomView)` | Toggle between template XML and SDK positioning |
229
+
230
+ ### NativeTemplateView - New XML Attributes
231
+
232
+ | Attribute | Values | Default |
233
+ |-----------|--------|---------|
234
+ | `app:adChoicesPlacement` | `top_left`, `top_right`, `bottom_left`, `bottom_right` | `top_right` |
235
+
236
+ ### AppPurchase - New Methods
237
+
238
+ | Method | Description |
239
+ |--------|-------------|
240
+ | `setPurchaseHistoryListener()` | Set listener for purchase events |
241
+ | `consumePurchase(productId)` | Manually consume a purchased product |
242
+ | `refreshPurchases()` | Refresh purchase state from Google |
243
+ | `isSubscribed(subscriptionId)` | Check specific subscription |
244
+ | `getSubscriptionState(subscriptionId)` | Get subscription lifecycle state |
245
+ | `getActiveSubscriptions()` | Get all active subscriptions |
246
+ | `hasSubscriptionCancelled()` | Check if any subscription cancelled |
247
+ | `willSubscriptionsRenew()` | Check if all subscriptions will renew |
248
+ | `getSubscription(subscriptionId)` | Get subscription PurchaseResult |
249
+ | `hasLifetimePurchase()` | Check for lifetime purchases |
250
+ | `hasLifetimePremium()` | Check for LIFETIME_PREMIUM category |
251
+ | `hasRemoveAdsPurchase()` | Check for REMOVE_ADS category |
252
+ | `getActivePurchaseType()` | Get type disabling ads |
253
+ | `getPurchaseCategory(productId)` | Get product's category |
254
+ | `isProductOwned(productId)` | Check if product is owned |
255
+ | `upgradeSubscription()` | Simple upgrade with default proration |
256
+ | `downgradeSubscription()` | Simple downgrade with deferred mode |
257
+ | `changeSubscription()` | Full upgrade/downgrade control |
258
+ | `updateSubscription()` | Low-level subscription update |
259
+
260
+ ### AppPurchase - Deprecated Methods
261
+
262
+ | Method | Replacement |
263
+ |--------|-------------|
264
+ | `setConsumePurchase(boolean)` | Use `PurchaseItem.isConsumable` per-product |
265
+
266
+ ### PurchaseItem - New Properties
267
+
268
+ | Property | Description |
269
+ |----------|-------------|
270
+ | `category` | PurchaseCategory enum |
271
+ | `isConsumable` | Whether product is consumable |
272
+
273
+ ### PurchaseItem - New Methods
274
+
275
+ | Method | Description |
276
+ |--------|-------------|
277
+ | `shouldDisableAds()` | Check if purchase should disable ads |
278
+ | `isLifetimePurchase()` | Check if lifetime (not subscription) |
279
+
280
+ ### PurchaseResult - New Fields
281
+
282
+ | Field | Description |
283
+ |-------|-------------|
284
+ | `originalJson` | Raw JSON for server verification |
285
+ | `signature` | Purchase signature |
286
+ | `obfuscatedAccountId` | Account identifier |
287
+ | `obfuscatedProfileId` | Profile identifier |
288
+ | `productType` | "inapp" or "subs" |
289
+ | `isConsumed` | Consumption status |
290
+ | `consumedTime` | Time of consumption |
291
+
292
+ ### PurchaseResult - New Methods
293
+
294
+ | Method | Description |
295
+ |--------|-------------|
296
+ | `fromPurchase(Purchase)` | Factory method from Google Purchase |
297
+ | `isPurchased()` | Check if PURCHASED state |
298
+ | `isPending()` | Check if PENDING state |
299
+ | `getFirstProductId()` | Get primary product ID |
300
+ | `containsProduct(productId)` | Check if contains product |
301
+ | `getPurchaseTimeFormatted()` | Get formatted date string |
302
+ | `getPurchaseDate()` | Get Date object |
303
+ | `markAsConsumed()` | Mark as consumed |
304
+ | `hasVerificationData()` | Check for json + signature |
305
+ | `isSubscription()` | Check if subscription type |
306
+ | `isInApp()` | Check if in-app type |
307
+ | `getSubscriptionState()` | Get SubscriptionState enum |
308
+ | `isSubscriptionActive()` | Check if has access |
309
+ | `willSubscriptionRenew()` | Check if will renew |
310
+ | `isSubscriptionCancelled()` | Check if cancelled |
311
+ | `getSubscriptionStateString()` | Get human-readable state |
312
+
313
+ ### New Enums
314
+
315
+ ```kotlin
316
+ // Purchase type for ad-disabling detection
317
+ enum class PurchaseType {
318
+ NONE, SUBSCRIPTION, LIFETIME_PREMIUM, REMOVE_ADS, LIFETIME, CONSUMABLE, UNKNOWN
319
+ }
320
+
321
+ // Subscription lifecycle states
322
+ enum class SubscriptionState {
323
+ ACTIVE, CANCELLED, GRACE_PERIOD, ON_HOLD, PAUSED, EXPIRED, NOT_SUBSCRIPTION
324
+ }
325
+
326
+ // Subscription upgrade/downgrade modes
327
+ enum class SubscriptionReplacementMode {
328
+ WITH_TIME_PRORATION, CHARGE_PRORATED_PRICE, CHARGE_FULL_PRICE, DEFERRED, WITHOUT_PRORATION
329
+ }
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Breaking Changes
335
+
336
+ ### No Auto-Consume
337
+
338
+ Products are **no longer auto-consumed**. You must call `consumePurchase(productId)` manually after granting items to the user:
339
+
340
+ ```kotlin
341
+ // Before v2.9.0: Products could be auto-consumed
342
+ AppPurchase.getInstance().setConsumePurchase(true) // Deprecated
343
+
344
+ // After v2.9.0: Manual consumption required
345
+ AppPurchase.getInstance().setPurchaseHistoryListener(object : PurchaseHistoryListener {
346
+ override fun onNewPurchase(productId: String, purchase: PurchaseResult) {
347
+ grantItems(productId, purchase.quantity)
348
+ AppPurchase.getInstance().consumePurchase(productId) // Manual!
349
+ }
350
+ override fun onPurchaseConsumed(productId: String, purchase: PurchaseResult) {}
351
+ })
352
+ ```
353
+
354
+ ### Default Category Change
355
+
356
+ `PurchaseItem` default category changed from `FEATURE_UNLOCK` to `LIFETIME_PREMIUM`:
357
+
358
+ ```kotlin
359
+ // If you were relying on default category, explicitly set it
360
+ PurchaseItem("product_id", TYPE_IAP.PURCHASE, PurchaseCategory.FEATURE_UNLOCK)
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Migration Guide
366
+
367
+ ### From 2.8.0 to 2.9.0
368
+
369
+ #### 1. Update Consumable Product Handling
370
+
371
+ ```kotlin
372
+ // Old approach (auto-consume)
373
+ AppPurchase.getInstance().setConsumePurchase(true)
374
+
375
+ // New approach (manual consume)
376
+ AppPurchase.getInstance().setPurchaseHistoryListener(object : PurchaseHistoryListener {
377
+ override fun onNewPurchase(productId: String, purchase: PurchaseResult) {
378
+ when (productId) {
379
+ "coins_100" -> {
380
+ addCoins(100 * purchase.quantity)
381
+ AppPurchase.getInstance().consumePurchase(productId)
382
+ }
383
+ }
384
+ }
385
+ override fun onPurchaseConsumed(productId: String, purchase: PurchaseResult) {
386
+ Log.d("Billing", "Consumed: $productId")
387
+ }
388
+ })
389
+ ```
390
+
391
+ #### 2. Use Purchase Categories
392
+
393
+ ```kotlin
394
+ // Old approach
395
+ val items = listOf(
396
+ PurchaseItem("coins_100", TYPE_IAP.PURCHASE, true), // isConsumable
397
+ PurchaseItem("remove_ads", TYPE_IAP.PURCHASE)
398
+ )
399
+
400
+ // New approach (explicit categories)
401
+ val items = listOf(
402
+ PurchaseItem("coins_100", TYPE_IAP.PURCHASE, PurchaseCategory.CONSUMABLE),
403
+ PurchaseItem("remove_ads", TYPE_IAP.PURCHASE, PurchaseCategory.REMOVE_ADS),
404
+ PurchaseItem("lifetime", TYPE_IAP.PURCHASE, PurchaseCategory.LIFETIME_PREMIUM)
405
+ )
406
+ ```
407
+
408
+ #### 3. Check Purchase Type for UI
409
+
410
+ ```kotlin
411
+ // Show appropriate UI based on purchase type
412
+ when (AppPurchase.getInstance().getActivePurchaseType()) {
413
+ PurchaseType.SUBSCRIPTION -> showSubscriberBadge()
414
+ PurchaseType.LIFETIME_PREMIUM -> showLifetimeBadge()
415
+ PurchaseType.REMOVE_ADS -> hideAds()
416
+ PurchaseType.NONE -> showPurchaseOptions()
417
+ else -> {}
418
+ }
419
+ ```
420
+
421
+ ---
422
+
423
+ ## Installation
424
+
425
+ ```groovy
426
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v2.9.0'
427
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v2.9.0'
428
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v2.9.0'
429
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v2.9.0'
430
+ ```
431
+
432
+ ---
433
+
434
+ ## Full Changelog
435
+
436
+ ### Native Ad Module
437
+
438
+ - Added 6 new native ad templates: APP_STORE, SOCIAL_FEED, GRADIENT_CARD, PILL_BANNER, SPOTLIGHT, MEDIA_CONTENT_SPLIT
439
+ - Added shimmer loading layouts for all new templates
440
+ - Added AdChoices placement control in NativeTemplateView (`setAdChoicesPlacement()`)
441
+ - Added `adChoicesPlacement` XML attribute for declarative configuration
442
+ - Added `setUseCustomAdChoicesView()` for SDK vs template positioning control
443
+ - Added coroutine support in NativeTemplateView for async operations
444
+ - Updated screen type classification for new templates in NativeAdIntegrationManager
445
+ - Improved layout consistency across all native templates
446
+
447
+ ### Billing Module Enhancements
448
+
449
+ - Added `PurchaseCategory` enum for product classification (CONSUMABLE, FEATURE_UNLOCK, LIFETIME_PREMIUM, REMOVE_ADS)
450
+ - Added `PurchaseHistoryListener` interface for tracking purchases and consumption
451
+ - Added `PurchaseResult.fromPurchase()` factory method with full data capture
452
+ - Added subscription state tracking (ACTIVE, CANCELLED, EXPIRED)
453
+ - Added subscription upgrade/downgrade with `SubscriptionReplacementMode`
454
+ - Added `refreshPurchases()` for manual purchase state refresh
455
+ - Enhanced `isPurchased()` to only consider ad-disabling purchases
456
+ - Enhanced `PurchaseResult` with originalJson, signature, account identifiers, consumption tracking
457
+ - Added helper methods: `hasLifetimePremium()`, `hasRemoveAdsPurchase()`, `getActivePurchaseType()`
458
+ - Added subscription methods: `getSubscriptionState()`, `hasSubscriptionCancelled()`, `willSubscriptionsRenew()`
459
+ - Removed auto-consume behavior - developers must call `consumePurchase()` manually
460
+ - Deprecated `setConsumePurchase()` in favor of per-product `isConsumable` flag
461
+
462
+ ### Dependency Updates
463
+
464
+ | Dependency | Old Version | New Version |
465
+ |------------|-------------|-------------|
466
+ | Google Play Billing | 8.0.0 | 8.1.0 |
467
+ | Google Mobile Ads | 24.7.0 | 24.8.0 |
468
+ | Firebase BOM | 34.5.0 | 34.6.0 |
469
+ | Lifecycle (Process, ViewModel, Runtime) | 2.9.4 | 2.10.0 |
470
+ | Activity / Activity Compose | 1.11.0 | 1.12.0 |
471
+ | Compose BOM | 2025.10.01 | 2025.11.01 |
472
+
473
+ ### Bug Fixes
474
+
475
+ - Fixed double callback issue in splash interstitial loading with timeout
476
+ - Fixed ad loading timeout now saves ad for next use instead of discarding
477
+ - Improved screen type detection for new native templates
478
+ - Fixed `IllegalArgumentException: View not attached to window manager` crash when dismissing dialogs after activity is destroyed (AppOpenManager, AdManager)
479
+ - Fixed welcome back dialog crash on activities without Material theme by wrapping context with `ContextThemeWrapper`