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.
- package/content/README.md +851 -0
- package/content/docs/AD_FREQUENCY_CONTROL.md +450 -0
- package/content/docs/AD_LOADING_STRATEGIES.md +369 -0
- package/content/docs/API_REFERENCE.md +734 -0
- package/content/docs/APP_PURCHASE_GUIDE.md +704 -0
- package/content/docs/BANNER_AD_IMPROVEMENTS.md +325 -0
- package/content/docs/COMPOSE_INTEGRATION.md +477 -0
- package/content/docs/CONFIGURATION_USAGE.md +168 -0
- package/content/docs/INTERSTITIAL_BUILDER_GUIDE.md +518 -0
- package/content/docs/JAVA_USAGE_GUIDE.md +785 -0
- package/content/docs/LOADING_STRATEGY_EXAMPLES.md +463 -0
- package/content/docs/NATIVE_AD_MANAGER_ENHANCEMENTS.md +347 -0
- package/content/docs/NATIVE_AD_PRELOADING.md +467 -0
- package/content/docs/NATIVE_TEMPLATE_VIEW.md +413 -0
- package/content/docs/app-open-ads.md +412 -0
- package/content/docs/interstitial-ads.md +269 -0
- package/content/docs/native-ads-caching.md +182 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.1.0.md +156 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.2.0.md +248 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.3.0.md +280 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.5.0.md +73 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.6.0.md +265 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.7.0.md +168 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.8.0.md +153 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.9.0.md +479 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.0.0.md +343 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.1.0.md +131 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.0.md +252 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.2.md +215 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.3.md +116 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.4.md +142 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.5.md +94 -0
- package/content/docs/rewarded-ads.md +623 -0
- package/content/wiki/Ad-Loading-Strategies.md +209 -0
- package/content/wiki/App-Open-Ads.md +189 -0
- package/content/wiki/Banner-Ads.md +133 -0
- package/content/wiki/Billing-Integration.md +69 -0
- package/content/wiki/Configuration.md +252 -0
- package/content/wiki/Consumable-Products.md +166 -0
- package/content/wiki/Home.md +144 -0
- package/content/wiki/Interstitial-Ads.md +313 -0
- package/content/wiki/Jetpack-Compose.md +270 -0
- package/content/wiki/NativeAdManager.md +220 -0
- package/content/wiki/Purchase-Categories.md +94 -0
- package/content/wiki/Rewarded-Ads.md +420 -0
- package/content/wiki/Subscription-Upgrades.md +278 -0
- package/content/wiki/Subscriptions.md +368 -0
- package/content/wiki/_Footer.md +3 -0
- package/content/wiki/_Sidebar.md +18 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +18 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/code-generation.d.ts +2 -0
- package/dist/tools/code-generation.js +264 -0
- package/dist/tools/code-generation.js.map +1 -0
- package/dist/tools/documentation.d.ts +2 -0
- package/dist/tools/documentation.js +202 -0
- package/dist/tools/documentation.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +83 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/doc-loader.d.ts +17 -0
- package/dist/utils/doc-loader.js +245 -0
- package/dist/utils/doc-loader.js.map +1 -0
- package/dist/utils/search.d.ts +2 -0
- package/dist/utils/search.js +62 -0
- package/dist/utils/search.js.map +1 -0
- package/dist/utils/templates.d.ts +60 -0
- package/dist/utils/templates.js +793 -0
- package/dist/utils/templates.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# Native Ad Preloading (Force Caching) Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide explains how to **forcefully cache native ads** before they're needed. This is essential for:
|
|
6
|
+
- **ONLY_CACHE** strategy: Ads must be preloaded to display
|
|
7
|
+
- **HYBRID** strategy: Faster initial display (instant from cache)
|
|
8
|
+
- **App initialization**: Preload ads during splash screens
|
|
9
|
+
- **Background loading**: Prepare ads while user is doing other tasks
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Methods for Force Caching Native Ads
|
|
14
|
+
|
|
15
|
+
### 1. **preloadNativeAd()** - Single Ad Preload
|
|
16
|
+
|
|
17
|
+
Load and cache a single native ad without displaying it.
|
|
18
|
+
|
|
19
|
+
```kotlin
|
|
20
|
+
NativeAdManager.preloadNativeAd(
|
|
21
|
+
activity = this,
|
|
22
|
+
adUnitId = "ca-app-pub-XXXXX/YYYYY",
|
|
23
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.LARGE,
|
|
24
|
+
onSuccess = {
|
|
25
|
+
Log.d("Preload", "Native ad cached successfully")
|
|
26
|
+
// Ad is now in cache, ready to display instantly
|
|
27
|
+
},
|
|
28
|
+
onFailure = { error ->
|
|
29
|
+
Log.e("Preload", "Failed to cache: $error")
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Available Sizes:**
|
|
35
|
+
- `NativeAdSize.SMALL` - NativeBannerSmall equivalent
|
|
36
|
+
- `NativeAdSize.MEDIUM` - NativeBannerMedium equivalent
|
|
37
|
+
- `NativeAdSize.LARGE` - NativeLarge equivalent
|
|
38
|
+
|
|
39
|
+
**When to use:**
|
|
40
|
+
- Preload one ad for immediate display
|
|
41
|
+
- During app initialization or splash screen
|
|
42
|
+
- Between navigation transitions
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### 2. **preloadMultipleNativeAds()** - Batch Preload
|
|
47
|
+
|
|
48
|
+
Load multiple ads for the same ad unit to build up cache.
|
|
49
|
+
|
|
50
|
+
```kotlin
|
|
51
|
+
NativeAdManager.preloadMultipleNativeAds(
|
|
52
|
+
activity = this,
|
|
53
|
+
adUnitId = "ca-app-pub-XXXXX/YYYYY",
|
|
54
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.LARGE,
|
|
55
|
+
count = 3, // Preload 3 ads
|
|
56
|
+
onComplete = { successCount, failureCount ->
|
|
57
|
+
Log.d("Preload", "Cached $successCount/$count ads")
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Features:**
|
|
63
|
+
- Automatic request staggering (200ms between requests)
|
|
64
|
+
- Prevents AdMob rate limiting
|
|
65
|
+
- Tracks success/failure counts
|
|
66
|
+
- Ideal for list views with multiple ads
|
|
67
|
+
|
|
68
|
+
**When to use:**
|
|
69
|
+
- Building cache for RecyclerView/ListView with multiple native ads
|
|
70
|
+
- Warming up cache for high-traffic screens
|
|
71
|
+
- Preparing for ONLY_CACHE strategy testing
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### 3. **Programmatic Loading** - Load & Display or Just Cache
|
|
76
|
+
|
|
77
|
+
Use programmatic loading methods to load ads with full control.
|
|
78
|
+
|
|
79
|
+
#### Load without displaying (just cache):
|
|
80
|
+
|
|
81
|
+
```kotlin
|
|
82
|
+
NativeAdManager.loadNativeAdProgrammatically(
|
|
83
|
+
activity = this,
|
|
84
|
+
adUnitId = "ca-app-pub-XXXXX/YYYYY",
|
|
85
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.MEDIUM,
|
|
86
|
+
useCachedAd = false, // Force fresh load
|
|
87
|
+
callback = object : ProgrammaticNativeAdLoader.ProgrammaticAdCallback {
|
|
88
|
+
override fun onAdLoaded(nativeAdView: NativeAdView, nativeAd: NativeAd) {
|
|
89
|
+
// Ad loaded and cached, but not displayed
|
|
90
|
+
// Don't add nativeAdView to layout if you just want to cache
|
|
91
|
+
Log.d("Cache", "Ad loaded and cached")
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
override fun onAdFailedToLoad(error: AdError) {
|
|
95
|
+
Log.e("Cache", "Failed: ${error.message}")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Other callbacks...
|
|
99
|
+
override fun onAdClicked() {}
|
|
100
|
+
override fun onAdImpression() {}
|
|
101
|
+
override fun onAdOpened() {}
|
|
102
|
+
override fun onAdClosed() {}
|
|
103
|
+
override fun onPaidEvent(adValue: AdValue) {}
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### Convenience methods:
|
|
109
|
+
|
|
110
|
+
```kotlin
|
|
111
|
+
// Small native banner
|
|
112
|
+
NativeAdManager.loadSmallNativeAd(this, adUnitId, useCachedAd = false, callback)
|
|
113
|
+
|
|
114
|
+
// Medium native banner
|
|
115
|
+
NativeAdManager.loadMediumNativeAd(this, adUnitId, useCachedAd = false, callback)
|
|
116
|
+
|
|
117
|
+
// Large native ad
|
|
118
|
+
NativeAdManager.loadLargeNativeAd(this, adUnitId, useCachedAd = false, callback)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Real-World Usage Examples
|
|
124
|
+
|
|
125
|
+
### Example 1: Splash Screen Preload
|
|
126
|
+
|
|
127
|
+
```kotlin
|
|
128
|
+
class SplashActivity : AppCompatActivity() {
|
|
129
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
130
|
+
super.onCreate(savedInstanceState)
|
|
131
|
+
|
|
132
|
+
// Preload ads during splash screen
|
|
133
|
+
preloadAdsForApp()
|
|
134
|
+
|
|
135
|
+
// Navigate to main after 3 seconds
|
|
136
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
137
|
+
startActivity(Intent(this, MainActivity::class.java))
|
|
138
|
+
finish()
|
|
139
|
+
}, 3000)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private fun preloadAdsForApp() {
|
|
143
|
+
// Preload native ads for main screen
|
|
144
|
+
NativeAdManager.preloadMultipleNativeAds(
|
|
145
|
+
activity = this,
|
|
146
|
+
adUnitId = getString(R.string.native_ad_unit_id),
|
|
147
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.LARGE,
|
|
148
|
+
count = 2, // Cache 2 ads
|
|
149
|
+
onComplete = { success, failure ->
|
|
150
|
+
Log.d("Splash", "Preloaded $success native ads")
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### Example 2: Application.onCreate() Preload
|
|
160
|
+
|
|
161
|
+
```kotlin
|
|
162
|
+
class MyApplication : Application() {
|
|
163
|
+
override fun onCreate() {
|
|
164
|
+
super.onCreate()
|
|
165
|
+
|
|
166
|
+
// Initialize AdManageKit
|
|
167
|
+
AdManageKitConfig.initialize(this)
|
|
168
|
+
|
|
169
|
+
// Enable caching
|
|
170
|
+
NativeAdManager.enableCachingNativeAds = true
|
|
171
|
+
|
|
172
|
+
// Preload ads in background
|
|
173
|
+
lifecycleScope.launch {
|
|
174
|
+
delay(2000) // Wait 2 seconds after app start
|
|
175
|
+
preloadAdsInBackground()
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private fun preloadAdsInBackground() {
|
|
180
|
+
// Get current activity
|
|
181
|
+
val activity = (this as? Application)?.let { /* get current activity */ }
|
|
182
|
+
activity?.let {
|
|
183
|
+
NativeAdManager.preloadNativeAd(
|
|
184
|
+
activity = it,
|
|
185
|
+
adUnitId = "ca-app-pub-XXXXX/YYYYY",
|
|
186
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.LARGE
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Example 3: ONLY_CACHE Strategy Setup
|
|
196
|
+
|
|
197
|
+
```kotlin
|
|
198
|
+
class MainActivity : AppCompatActivity() {
|
|
199
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
200
|
+
super.onCreate(savedInstanceState)
|
|
201
|
+
|
|
202
|
+
// Configure ONLY_CACHE strategy
|
|
203
|
+
AdManageKitConfig.apply {
|
|
204
|
+
interstitialLoadingStrategy = AdLoadingStrategy.ONLY_CACHE
|
|
205
|
+
nativeLoadingStrategy = AdLoadingStrategy.HYBRID // Auto-converted from ONLY_CACHE
|
|
206
|
+
enableSmartPreloading = true
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// MUST preload before displaying with ONLY_CACHE
|
|
210
|
+
preloadAdsToCache()
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private fun preloadAdsToCache() {
|
|
214
|
+
// Preload interstitial
|
|
215
|
+
InterstitialAdBuilder.with(this)
|
|
216
|
+
.adUnit(interstitialAdUnitId)
|
|
217
|
+
.preload()
|
|
218
|
+
|
|
219
|
+
// Preload native ads (all sizes)
|
|
220
|
+
listOf(
|
|
221
|
+
ProgrammaticNativeAdLoader.NativeAdSize.SMALL,
|
|
222
|
+
ProgrammaticNativeAdLoader.NativeAdSize.MEDIUM,
|
|
223
|
+
ProgrammaticNativeAdLoader.NativeAdSize.LARGE
|
|
224
|
+
).forEach { size ->
|
|
225
|
+
NativeAdManager.preloadNativeAd(
|
|
226
|
+
activity = this,
|
|
227
|
+
adUnitId = nativeAdUnitId,
|
|
228
|
+
size = size,
|
|
229
|
+
onSuccess = {
|
|
230
|
+
Log.d("Cache", "Preloaded ${size.name}")
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### Example 4: RecyclerView with Multiple Native Ads
|
|
241
|
+
|
|
242
|
+
```kotlin
|
|
243
|
+
class NewsActivity : AppCompatActivity() {
|
|
244
|
+
private val nativeAdUnitId = "ca-app-pub-XXXXX/YYYYY"
|
|
245
|
+
|
|
246
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
247
|
+
super.onCreate(savedInstanceState)
|
|
248
|
+
|
|
249
|
+
// Preload 5 native ads for RecyclerView
|
|
250
|
+
NativeAdManager.preloadMultipleNativeAds(
|
|
251
|
+
activity = this,
|
|
252
|
+
adUnitId = nativeAdUnitId,
|
|
253
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.MEDIUM,
|
|
254
|
+
count = 5,
|
|
255
|
+
onComplete = { success, failure ->
|
|
256
|
+
Toast.makeText(this, "Preloaded $success ads", Toast.LENGTH_SHORT).show()
|
|
257
|
+
setupRecyclerView()
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private fun setupRecyclerView() {
|
|
263
|
+
// RecyclerView will now use cached ads for instant display
|
|
264
|
+
val adapter = NewsAdapter(nativeAdUnitId)
|
|
265
|
+
recyclerView.adapter = adapter
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Cache Management
|
|
273
|
+
|
|
274
|
+
### Check Cache Status
|
|
275
|
+
|
|
276
|
+
```kotlin
|
|
277
|
+
// Check if ads are cached for an ad unit
|
|
278
|
+
val hasCachedAds = NativeAdManager.hasCachedAds(adUnitId)
|
|
279
|
+
Log.d("Cache", "Has cached ads: $hasCachedAds")
|
|
280
|
+
|
|
281
|
+
// Get cache size for specific ad unit
|
|
282
|
+
val cacheSize = NativeAdManager.getCacheSize(adUnitId)
|
|
283
|
+
Log.d("Cache", "Cache size: $cacheSize")
|
|
284
|
+
|
|
285
|
+
// Get total cached ads across all units
|
|
286
|
+
val totalCached = NativeAdManager.getTotalCacheSize()
|
|
287
|
+
Log.d("Cache", "Total cached: $totalCached")
|
|
288
|
+
|
|
289
|
+
// Get detailed cache statistics
|
|
290
|
+
val stats = NativeAdManager.getCacheStatistics()
|
|
291
|
+
stats.forEach { (adUnitId, stats) ->
|
|
292
|
+
Log.d("Cache", "$adUnitId: $stats")
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Clear Cache
|
|
297
|
+
|
|
298
|
+
```kotlin
|
|
299
|
+
// Clear cache for specific ad unit
|
|
300
|
+
NativeAdManager.clearCachedAd(adUnitId)
|
|
301
|
+
|
|
302
|
+
// Clear all cached ads
|
|
303
|
+
NativeAdManager.clearAllCachedAds()
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Performance Monitoring
|
|
307
|
+
|
|
308
|
+
```kotlin
|
|
309
|
+
// Get performance statistics
|
|
310
|
+
val perfStats = NativeAdManager.getPerformanceStats()
|
|
311
|
+
val hitRate = perfStats["hit_rate_percent"] as Int
|
|
312
|
+
Log.d("Performance", "Cache hit rate: $hitRate%")
|
|
313
|
+
|
|
314
|
+
// Reset performance counters
|
|
315
|
+
NativeAdManager.resetPerformanceStats()
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Configuration
|
|
321
|
+
|
|
322
|
+
### Enable/Disable Caching
|
|
323
|
+
|
|
324
|
+
```kotlin
|
|
325
|
+
// Enable native ad caching (default: true)
|
|
326
|
+
NativeAdManager.enableCachingNativeAds = true
|
|
327
|
+
|
|
328
|
+
// Disable caching (all preload methods will skip)
|
|
329
|
+
NativeAdManager.enableCachingNativeAds = false
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Cache Settings
|
|
333
|
+
|
|
334
|
+
```kotlin
|
|
335
|
+
AdManageKitConfig.apply {
|
|
336
|
+
// Cache expiry time (default: 1 hour)
|
|
337
|
+
nativeCacheExpiry = 60.minutes
|
|
338
|
+
|
|
339
|
+
// Max ads per ad unit (default: 3)
|
|
340
|
+
maxCachedAdsPerUnit = 5
|
|
341
|
+
|
|
342
|
+
// Enable automatic cache cleanup (default: true)
|
|
343
|
+
enableAutoCacheCleanup = true
|
|
344
|
+
|
|
345
|
+
// Cleanup interval (default: 30 minutes)
|
|
346
|
+
cacheCleanupInterval = 30.minutes
|
|
347
|
+
|
|
348
|
+
// Enable performance metrics (default: true)
|
|
349
|
+
enablePerformanceMetrics = true
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Best Practices
|
|
356
|
+
|
|
357
|
+
### ✅ DO:
|
|
358
|
+
|
|
359
|
+
1. **Preload during idle time** - Splash screens, loading screens, background tasks
|
|
360
|
+
2. **Use appropriate sizes** - Match preload size with display size
|
|
361
|
+
3. **Check cache status** - Verify ads are cached before ONLY_CACHE strategy
|
|
362
|
+
4. **Stagger requests** - Use `preloadMultipleNativeAds()` which auto-staggers
|
|
363
|
+
5. **Monitor performance** - Track hit rates and adjust preloading strategy
|
|
364
|
+
|
|
365
|
+
### ❌ DON'T:
|
|
366
|
+
|
|
367
|
+
1. **Don't preload too many ads** - Respect AdMob rate limits (max 5 concurrent)
|
|
368
|
+
2. **Don't use ONLY_CACHE without preloading** - Ads won't display
|
|
369
|
+
3. **Don't forget to clear cache** - Old ads consume memory
|
|
370
|
+
4. **Don't preload on metered connections** - Consider user's data plan
|
|
371
|
+
5. **Don't block UI thread** - Preloading is async, but don't wait for it
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Loading Strategy Recommendations
|
|
376
|
+
|
|
377
|
+
| Strategy | Preload Required? | When to Use |
|
|
378
|
+
|----------|------------------|-------------|
|
|
379
|
+
| **ON_DEMAND** | No | Maximum ad coverage, fresh ads always |
|
|
380
|
+
| **ONLY_CACHE** | **YES** | Best UX, instant display (must preload) |
|
|
381
|
+
| **HYBRID** | Recommended | Balanced approach, preload for faster display |
|
|
382
|
+
|
|
383
|
+
**Note:** ONLY_CACHE for native ads is automatically converted to HYBRID because native ads use shimmer effects, not dialogs. Native ads work best with HYBRID or ON_DEMAND.
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Testing
|
|
388
|
+
|
|
389
|
+
See `LoadingStrategyTestActivity.kt` for comprehensive testing of:
|
|
390
|
+
- All three loading strategies
|
|
391
|
+
- Preload functionality
|
|
392
|
+
- Cache management
|
|
393
|
+
- Real-time cache status monitoring
|
|
394
|
+
|
|
395
|
+
**Test Scenario: ONLY_CACHE**
|
|
396
|
+
1. Click "Preload Cache" button
|
|
397
|
+
2. Wait 3-5 seconds for ads to cache
|
|
398
|
+
3. Select ONLY_CACHE strategy
|
|
399
|
+
4. Click "Test Interstitial" → Instant display!
|
|
400
|
+
5. Click "Test Native Large" → Instant from cache!
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## API Reference
|
|
405
|
+
|
|
406
|
+
### NativeAdManager Methods
|
|
407
|
+
|
|
408
|
+
| Method | Description | Since |
|
|
409
|
+
|--------|-------------|-------|
|
|
410
|
+
| `preloadNativeAd()` | Preload single native ad | v2.2.0 |
|
|
411
|
+
| `preloadMultipleNativeAds()` | Preload multiple native ads | v2.2.0 |
|
|
412
|
+
| `loadNativeAdProgrammatically()` | Programmatic loading with full control | v2.1.0 |
|
|
413
|
+
| `loadSmallNativeAd()` | Convenience for small banner | v2.1.0 |
|
|
414
|
+
| `loadMediumNativeAd()` | Convenience for medium banner | v2.1.0 |
|
|
415
|
+
| `loadLargeNativeAd()` | Convenience for large native | v2.1.0 |
|
|
416
|
+
| `getCacheSize()` | Get cache size for ad unit | v1.0.0 |
|
|
417
|
+
| `hasCachedAds()` | Check if ads are cached | v1.0.0 |
|
|
418
|
+
| `clearCachedAd()` | Clear specific ad unit cache | v1.0.0 |
|
|
419
|
+
| `clearAllCachedAds()` | Clear all cached ads | v1.0.0 |
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Summary
|
|
424
|
+
|
|
425
|
+
**Quick Answer: How to force cache native ads?**
|
|
426
|
+
|
|
427
|
+
```kotlin
|
|
428
|
+
// Simplest way - preload a single ad
|
|
429
|
+
NativeAdManager.preloadNativeAd(
|
|
430
|
+
activity = this,
|
|
431
|
+
adUnitId = "ca-app-pub-XXXXX/YYYYY",
|
|
432
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.LARGE
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
// Or preload multiple ads
|
|
436
|
+
NativeAdManager.preloadMultipleNativeAds(
|
|
437
|
+
activity = this,
|
|
438
|
+
adUnitId = "ca-app-pub-XXXXX/YYYYY",
|
|
439
|
+
size = ProgrammaticNativeAdLoader.NativeAdSize.LARGE,
|
|
440
|
+
count = 3
|
|
441
|
+
)
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
That's it! The ads are now in cache and will display instantly when needed.
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Troubleshooting
|
|
449
|
+
|
|
450
|
+
### Issue: InflateException with `<merge>` layouts
|
|
451
|
+
|
|
452
|
+
**Error:**
|
|
453
|
+
```
|
|
454
|
+
android.view.InflateException: <merge /> can be used only with a valid ViewGroup root and attachToRoot=true
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Cause:** The `layout_native_large.xml` uses `<merge>` as the root tag, which requires a parent ViewGroup when inflating.
|
|
458
|
+
|
|
459
|
+
**Solution:** This has been fixed in `ProgrammaticNativeAdLoader.createNativeAdView()` (lines 171-182):
|
|
460
|
+
- For LARGE size: Creates a temporary FrameLayout parent, inflates with merge support, then extracts the NativeAdView
|
|
461
|
+
- For SMALL/MEDIUM: Direct inflation (no merge tag)
|
|
462
|
+
|
|
463
|
+
This fix is already applied, so you shouldn't encounter this error.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
**Need Help?** Check `LoadingStrategyTestActivity.kt` for working examples!
|