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,623 @@
|
|
|
1
|
+
# Rewarded Ads Guide
|
|
2
|
+
|
|
3
|
+
This guide covers the complete integration of rewarded video ads using `RewardedAdManager`.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Features](#features)
|
|
9
|
+
- [Quick Start](#quick-start)
|
|
10
|
+
- [Callback Interfaces](#callback-interfaces)
|
|
11
|
+
- [Loading Methods](#loading-methods)
|
|
12
|
+
- [Display Methods](#display-methods)
|
|
13
|
+
- [State Management](#state-management)
|
|
14
|
+
- [Preloading Strategy](#preloading-strategy)
|
|
15
|
+
- [Analytics & Debugging](#analytics--debugging)
|
|
16
|
+
- [Automatic Retry](#automatic-retry)
|
|
17
|
+
- [Configuration](#configuration)
|
|
18
|
+
- [Best Practices](#best-practices)
|
|
19
|
+
- [Java Usage](#java-usage)
|
|
20
|
+
- [Troubleshooting](#troubleshooting)
|
|
21
|
+
|
|
22
|
+
## Overview
|
|
23
|
+
|
|
24
|
+
`RewardedAdManager` is a singleton class that simplifies rewarded ad integration with features like:
|
|
25
|
+
|
|
26
|
+
- Automatic retry with exponential backoff
|
|
27
|
+
- Premium user handling (ads disabled for purchased users)
|
|
28
|
+
- Timeout support for splash screens
|
|
29
|
+
- Firebase Analytics integration
|
|
30
|
+
- Full lifecycle callbacks
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
| Feature | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| **Auto-Retry** | Exponential backoff on failures (configurable) |
|
|
37
|
+
| **Premium Handling** | Automatically skips ads for premium users |
|
|
38
|
+
| **Timeout Support** | Load with timeout for time-sensitive scenarios |
|
|
39
|
+
| **Analytics** | Firebase tracking for requests, fills, impressions |
|
|
40
|
+
| **Auto-Reload** | Configurable reload after ad dismissal |
|
|
41
|
+
| **Lifecycle Callbacks** | Full callbacks: reward, show, dismiss, click, fail |
|
|
42
|
+
| **Preloading** | Preload during natural pauses |
|
|
43
|
+
| **Manual Load Cancel** | Manual loads cancel pending retries |
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### 1. Initialize
|
|
48
|
+
|
|
49
|
+
Initialize once in your `Application` class or main `Activity`:
|
|
50
|
+
|
|
51
|
+
```kotlin
|
|
52
|
+
class MyApplication : Application() {
|
|
53
|
+
override fun onCreate() {
|
|
54
|
+
super.onCreate()
|
|
55
|
+
|
|
56
|
+
// Configure AdManageKit (optional)
|
|
57
|
+
AdManageKitConfig.apply {
|
|
58
|
+
autoRetryFailedAds = true
|
|
59
|
+
rewardedAutoReload = true
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Initialize rewarded ads
|
|
63
|
+
RewardedAdManager.initialize(this, "ca-app-pub-xxx/yyy")
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 2. Check and Show
|
|
69
|
+
|
|
70
|
+
```kotlin
|
|
71
|
+
fun onWatchAdClicked() {
|
|
72
|
+
if (RewardedAdManager.isAdLoaded()) {
|
|
73
|
+
RewardedAdManager.showAd(this, object : RewardedAdManager.RewardedAdCallback {
|
|
74
|
+
override fun onRewardEarned(rewardType: String, rewardAmount: Int) {
|
|
75
|
+
// Grant reward
|
|
76
|
+
userCoins += rewardAmount
|
|
77
|
+
saveUserData()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
override fun onAdDismissed() {
|
|
81
|
+
// Continue flow
|
|
82
|
+
updateUI()
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
} else {
|
|
86
|
+
Toast.makeText(this, "Ad not ready", Toast.LENGTH_SHORT).show()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Callback Interfaces
|
|
92
|
+
|
|
93
|
+
### RewardedAdCallback (Recommended)
|
|
94
|
+
|
|
95
|
+
Full lifecycle callback for all ad events:
|
|
96
|
+
|
|
97
|
+
```kotlin
|
|
98
|
+
interface RewardedAdCallback {
|
|
99
|
+
/**
|
|
100
|
+
* Called when user earns a reward.
|
|
101
|
+
* @param rewardType The type of reward (e.g., "coins", "gems")
|
|
102
|
+
* @param rewardAmount The amount of reward earned
|
|
103
|
+
*/
|
|
104
|
+
fun onRewardEarned(rewardType: String, rewardAmount: Int)
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Called when ad is dismissed (user closed it).
|
|
108
|
+
* This is always called after onRewardEarned (if reward was earned).
|
|
109
|
+
*/
|
|
110
|
+
fun onAdDismissed()
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Called when ad is shown successfully.
|
|
114
|
+
* Use this to pause game/music.
|
|
115
|
+
*/
|
|
116
|
+
fun onAdShowed() {}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Called when ad fails to show.
|
|
120
|
+
* @param error The error that occurred
|
|
121
|
+
*/
|
|
122
|
+
fun onAdFailedToShow(error: AdError) {}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Called when user clicks the ad.
|
|
126
|
+
*/
|
|
127
|
+
fun onAdClicked() {}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### OnRewardedAdLoadCallback
|
|
132
|
+
|
|
133
|
+
For load-specific events:
|
|
134
|
+
|
|
135
|
+
```kotlin
|
|
136
|
+
interface OnRewardedAdLoadCallback {
|
|
137
|
+
fun onAdLoaded()
|
|
138
|
+
fun onAdFailedToLoad(error: LoadAdError)
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Full Callback Example
|
|
143
|
+
|
|
144
|
+
```kotlin
|
|
145
|
+
RewardedAdManager.showAd(activity, object : RewardedAdManager.RewardedAdCallback {
|
|
146
|
+
override fun onRewardEarned(rewardType: String, rewardAmount: Int) {
|
|
147
|
+
Log.d("Ads", "Reward: $rewardAmount $rewardType")
|
|
148
|
+
viewModel.addReward(rewardType, rewardAmount)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
override fun onAdDismissed() {
|
|
152
|
+
Log.d("Ads", "Ad dismissed")
|
|
153
|
+
enableGameControls()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
override fun onAdShowed() {
|
|
157
|
+
Log.d("Ads", "Ad showing")
|
|
158
|
+
pauseGame()
|
|
159
|
+
muteBackgroundMusic()
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
override fun onAdFailedToShow(error: AdError) {
|
|
163
|
+
Log.e("Ads", "Failed to show: ${error.message}")
|
|
164
|
+
showErrorToast("Couldn't show ad")
|
|
165
|
+
enableGameControls()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
override fun onAdClicked() {
|
|
169
|
+
Log.d("Ads", "Ad clicked")
|
|
170
|
+
analytics.logAdClick("rewarded")
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Loading Methods
|
|
176
|
+
|
|
177
|
+
### Basic Load
|
|
178
|
+
|
|
179
|
+
```kotlin
|
|
180
|
+
// Simple load - retries automatically on failure
|
|
181
|
+
RewardedAdManager.loadRewardedAd(context)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Load with Callback
|
|
185
|
+
|
|
186
|
+
```kotlin
|
|
187
|
+
RewardedAdManager.loadRewardedAd(context, object : RewardedAdManager.OnRewardedAdLoadCallback {
|
|
188
|
+
override fun onAdLoaded() {
|
|
189
|
+
// Update UI - show "Watch Ad" button
|
|
190
|
+
watchAdButton.isEnabled = true
|
|
191
|
+
watchAdButton.alpha = 1f
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
override fun onAdFailedToLoad(error: LoadAdError) {
|
|
195
|
+
Log.e("Ads", "Load failed: ${error.code} - ${error.message}")
|
|
196
|
+
watchAdButton.isEnabled = false
|
|
197
|
+
watchAdButton.alpha = 0.5f
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Load with Timeout
|
|
203
|
+
|
|
204
|
+
For splash screens or time-sensitive scenarios:
|
|
205
|
+
|
|
206
|
+
```kotlin
|
|
207
|
+
RewardedAdManager.loadRewardedAdWithTimeout(
|
|
208
|
+
context = this,
|
|
209
|
+
timeoutMillis = 5000, // 5 seconds
|
|
210
|
+
callback = object : RewardedAdManager.OnRewardedAdLoadCallback {
|
|
211
|
+
override fun onAdLoaded() {
|
|
212
|
+
// Show optional reward opportunity
|
|
213
|
+
showRewardedOffer()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
override fun onAdFailedToLoad(error: LoadAdError) {
|
|
217
|
+
// Timeout or error - proceed without ad
|
|
218
|
+
if (error.code == -1) {
|
|
219
|
+
Log.d("Ads", "Timed out")
|
|
220
|
+
} else {
|
|
221
|
+
Log.e("Ads", "Failed: ${error.message}")
|
|
222
|
+
}
|
|
223
|
+
navigateToMain()
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Key Behavior**: If the ad loads after timeout, it's saved for later use (not wasted).
|
|
230
|
+
|
|
231
|
+
## Display Methods
|
|
232
|
+
|
|
233
|
+
### Show with Callback
|
|
234
|
+
|
|
235
|
+
```kotlin
|
|
236
|
+
RewardedAdManager.showAd(
|
|
237
|
+
activity = this,
|
|
238
|
+
callback = myCallback,
|
|
239
|
+
autoReload = true // Reload after dismissal (default)
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Control Auto-Reload
|
|
244
|
+
|
|
245
|
+
```kotlin
|
|
246
|
+
// Disable for this show only
|
|
247
|
+
RewardedAdManager.showAd(activity, callback, autoReload = false)
|
|
248
|
+
|
|
249
|
+
// Or configure globally
|
|
250
|
+
AdManageKitConfig.rewardedAutoReload = false
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Show Only If Ready
|
|
254
|
+
|
|
255
|
+
```kotlin
|
|
256
|
+
fun tryShowRewardedAd(): Boolean {
|
|
257
|
+
return if (RewardedAdManager.isAdLoaded()) {
|
|
258
|
+
RewardedAdManager.showAd(activity, callback)
|
|
259
|
+
true
|
|
260
|
+
} else {
|
|
261
|
+
RewardedAdManager.loadRewardedAd(context) // Start loading
|
|
262
|
+
false
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## State Management
|
|
268
|
+
|
|
269
|
+
### State Methods
|
|
270
|
+
|
|
271
|
+
```kotlin
|
|
272
|
+
// Is ad loaded and ready to show?
|
|
273
|
+
val ready = RewardedAdManager.isAdLoaded()
|
|
274
|
+
|
|
275
|
+
// Is ad currently loading?
|
|
276
|
+
val loading = RewardedAdManager.isLoading()
|
|
277
|
+
|
|
278
|
+
// Is ad currently being displayed?
|
|
279
|
+
val showing = RewardedAdManager.isShowingAd()
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### State-Based UI
|
|
283
|
+
|
|
284
|
+
```kotlin
|
|
285
|
+
fun updateWatchAdButton() {
|
|
286
|
+
when {
|
|
287
|
+
RewardedAdManager.isAdLoaded() -> {
|
|
288
|
+
watchAdButton.isEnabled = true
|
|
289
|
+
watchAdButton.text = "Watch Ad for Coins"
|
|
290
|
+
}
|
|
291
|
+
RewardedAdManager.isLoading() -> {
|
|
292
|
+
watchAdButton.isEnabled = false
|
|
293
|
+
watchAdButton.text = "Loading..."
|
|
294
|
+
}
|
|
295
|
+
else -> {
|
|
296
|
+
watchAdButton.isEnabled = false
|
|
297
|
+
watchAdButton.text = "Ad Unavailable"
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Preloading Strategy
|
|
304
|
+
|
|
305
|
+
Preload during natural pauses to maximize show rate:
|
|
306
|
+
|
|
307
|
+
```kotlin
|
|
308
|
+
// In onResume
|
|
309
|
+
override fun onResume() {
|
|
310
|
+
super.onResume()
|
|
311
|
+
RewardedAdManager.preload(this)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// After user actions
|
|
315
|
+
fun onLevelComplete() {
|
|
316
|
+
showResults()
|
|
317
|
+
RewardedAdManager.preload(this) // Ready for next opportunity
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// After showing other ads
|
|
321
|
+
fun onInterstitialDismissed() {
|
|
322
|
+
RewardedAdManager.preload(this)
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Analytics & Debugging
|
|
327
|
+
|
|
328
|
+
### Session Statistics
|
|
329
|
+
|
|
330
|
+
```kotlin
|
|
331
|
+
val stats = RewardedAdManager.getAdStats()
|
|
332
|
+
|
|
333
|
+
// Returns Map<String, Any> with:
|
|
334
|
+
// - session_requests: Int
|
|
335
|
+
// - session_fills: Int
|
|
336
|
+
// - session_impressions: Int
|
|
337
|
+
// - fill_rate_percent: Float
|
|
338
|
+
// - show_rate_percent: Float
|
|
339
|
+
// - is_loaded: Boolean
|
|
340
|
+
// - is_loading: Boolean
|
|
341
|
+
// - retry_attempts: Int
|
|
342
|
+
|
|
343
|
+
// Display stats
|
|
344
|
+
Log.d("Ads", """
|
|
345
|
+
Rewarded Ad Stats:
|
|
346
|
+
- Requests: ${stats["session_requests"]}
|
|
347
|
+
- Fills: ${stats["session_fills"]}
|
|
348
|
+
- Impressions: ${stats["session_impressions"]}
|
|
349
|
+
- Fill Rate: ${stats["fill_rate_percent"]}%
|
|
350
|
+
- Show Rate: ${stats["show_rate_percent"]}%
|
|
351
|
+
""".trimIndent())
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Reset Statistics
|
|
355
|
+
|
|
356
|
+
```kotlin
|
|
357
|
+
// Reset at app launch or session start
|
|
358
|
+
RewardedAdManager.resetAdStats()
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Firebase Events
|
|
362
|
+
|
|
363
|
+
The following events are automatically logged:
|
|
364
|
+
|
|
365
|
+
| Event | When | Parameters |
|
|
366
|
+
|-------|------|------------|
|
|
367
|
+
| `ad_request` | Load requested | ad_unit_name, ad_type, session_requests |
|
|
368
|
+
| `ad_fill` | Load successful | ad_unit_name, fill_rate_percent |
|
|
369
|
+
| `ad_failed_to_load` | Load failed | ad_unit_name, ad_error_code |
|
|
370
|
+
| `ad_impression` | Ad shown | ad_unit_name |
|
|
371
|
+
| `ad_impression_detailed` | Ad shown | show_rate_percent, fill_rate_percent |
|
|
372
|
+
| `ad_dismissed` | User closed ad | ad_unit_name |
|
|
373
|
+
| `ad_failed_to_show` | Show failed | ad_unit_name, error_code |
|
|
374
|
+
| `ad_paid_event` | Revenue event | ad_unit_name, value, currency |
|
|
375
|
+
| `rewarded_ad_reward` | Reward earned | reward_type, reward_amount |
|
|
376
|
+
|
|
377
|
+
## Automatic Retry
|
|
378
|
+
|
|
379
|
+
### How It Works
|
|
380
|
+
|
|
381
|
+
When a load fails, the manager automatically schedules a retry with exponential backoff:
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
Attempt 1: Wait 1 second → retry
|
|
385
|
+
Attempt 2: Wait 2 seconds → retry
|
|
386
|
+
Attempt 3: Wait 4 seconds → retry
|
|
387
|
+
(capped at maxRetryDelay)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Configuration
|
|
391
|
+
|
|
392
|
+
```kotlin
|
|
393
|
+
AdManageKitConfig.apply {
|
|
394
|
+
autoRetryFailedAds = true // Enable auto-retry (default: true)
|
|
395
|
+
maxRetryAttempts = 3 // Max attempts (default: 3)
|
|
396
|
+
baseRetryDelay = 1.seconds // Initial delay
|
|
397
|
+
maxRetryDelay = 30.seconds // Maximum delay cap
|
|
398
|
+
enableExponentialBackoff = true // Use exponential backoff
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Manual Load Behavior
|
|
403
|
+
|
|
404
|
+
When you manually call `loadRewardedAd()`:
|
|
405
|
+
1. Any pending retry is **cancelled**
|
|
406
|
+
2. Retry counter is **reset to 0**
|
|
407
|
+
3. Fresh load starts immediately
|
|
408
|
+
|
|
409
|
+
This ensures manual requests always take priority.
|
|
410
|
+
|
|
411
|
+
## Configuration
|
|
412
|
+
|
|
413
|
+
### Global Settings
|
|
414
|
+
|
|
415
|
+
```kotlin
|
|
416
|
+
AdManageKitConfig.apply {
|
|
417
|
+
// Retry settings
|
|
418
|
+
autoRetryFailedAds = true
|
|
419
|
+
maxRetryAttempts = 3
|
|
420
|
+
|
|
421
|
+
// Auto-reload after showing
|
|
422
|
+
rewardedAutoReload = true
|
|
423
|
+
|
|
424
|
+
// Timeout for load operations
|
|
425
|
+
defaultAdTimeout = 10.seconds
|
|
426
|
+
|
|
427
|
+
// Debug logging
|
|
428
|
+
debugMode = BuildConfig.DEBUG
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Test Mode
|
|
433
|
+
|
|
434
|
+
```kotlin
|
|
435
|
+
AdManageKitConfig.apply {
|
|
436
|
+
testMode = true
|
|
437
|
+
testDeviceId = "YOUR_TEST_DEVICE_ID"
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Best Practices
|
|
442
|
+
|
|
443
|
+
### 1. Initialize Early
|
|
444
|
+
|
|
445
|
+
```kotlin
|
|
446
|
+
// In Application.onCreate() - before any Activity
|
|
447
|
+
RewardedAdManager.initialize(applicationContext, adUnitId)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 2. Don't Block User Flow
|
|
451
|
+
|
|
452
|
+
```kotlin
|
|
453
|
+
// BAD: Blocking while loading
|
|
454
|
+
fun showAd() {
|
|
455
|
+
showLoadingDialog()
|
|
456
|
+
RewardedAdManager.loadRewardedAd(context, callback)
|
|
457
|
+
// User waits...
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// GOOD: Use preloading
|
|
461
|
+
fun showAd() {
|
|
462
|
+
if (RewardedAdManager.isAdLoaded()) {
|
|
463
|
+
RewardedAdManager.showAd(activity, callback)
|
|
464
|
+
} else {
|
|
465
|
+
// Offer alternative or show message
|
|
466
|
+
showNoAdAvailableMessage()
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### 3. Preload Strategically
|
|
472
|
+
|
|
473
|
+
```kotlin
|
|
474
|
+
// After user completes an action (likely to watch ad next)
|
|
475
|
+
fun onTaskComplete() {
|
|
476
|
+
RewardedAdManager.preload(context)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// In natural pauses
|
|
480
|
+
override fun onResume() {
|
|
481
|
+
super.onResume()
|
|
482
|
+
RewardedAdManager.preload(this)
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### 4. Handle All Cases
|
|
487
|
+
|
|
488
|
+
```kotlin
|
|
489
|
+
fun onWatchAdClicked() {
|
|
490
|
+
when {
|
|
491
|
+
RewardedAdManager.isShowingAd() -> {
|
|
492
|
+
// Already showing, ignore
|
|
493
|
+
}
|
|
494
|
+
RewardedAdManager.isAdLoaded() -> {
|
|
495
|
+
RewardedAdManager.showAd(activity, callback)
|
|
496
|
+
}
|
|
497
|
+
RewardedAdManager.isLoading() -> {
|
|
498
|
+
showToast("Ad loading, please wait...")
|
|
499
|
+
}
|
|
500
|
+
else -> {
|
|
501
|
+
showToast("No ad available")
|
|
502
|
+
RewardedAdManager.loadRewardedAd(context)
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### 5. Always Grant Rewards
|
|
509
|
+
|
|
510
|
+
```kotlin
|
|
511
|
+
override fun onRewardEarned(rewardType: String, rewardAmount: Int) {
|
|
512
|
+
// ALWAYS grant the reward - user watched the ad
|
|
513
|
+
grantReward(rewardType, rewardAmount)
|
|
514
|
+
|
|
515
|
+
// Then update UI
|
|
516
|
+
showRewardAnimation()
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
## Java Usage
|
|
521
|
+
|
|
522
|
+
```java
|
|
523
|
+
// Initialize
|
|
524
|
+
RewardedAdManager.INSTANCE.initialize(context, "ca-app-pub-xxx/yyy");
|
|
525
|
+
|
|
526
|
+
// Check and show
|
|
527
|
+
if (RewardedAdManager.INSTANCE.isAdLoaded()) {
|
|
528
|
+
RewardedAdManager.INSTANCE.showAd(activity, new RewardedAdManager.RewardedAdCallback() {
|
|
529
|
+
@Override
|
|
530
|
+
public void onRewardEarned(@NonNull String rewardType, int rewardAmount) {
|
|
531
|
+
grantReward(rewardType, rewardAmount);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
@Override
|
|
535
|
+
public void onAdDismissed() {
|
|
536
|
+
continueFlow();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
@Override
|
|
540
|
+
public void onAdShowed() {
|
|
541
|
+
// Optional
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
@Override
|
|
545
|
+
public void onAdFailedToShow(@NonNull AdError error) {
|
|
546
|
+
// Optional
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
@Override
|
|
550
|
+
public void onAdClicked() {
|
|
551
|
+
// Optional
|
|
552
|
+
}
|
|
553
|
+
}, true);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Load with callback
|
|
557
|
+
RewardedAdManager.INSTANCE.loadRewardedAd(context, new RewardedAdManager.OnRewardedAdLoadCallback() {
|
|
558
|
+
@Override
|
|
559
|
+
public void onAdLoaded() {
|
|
560
|
+
updateButton();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
@Override
|
|
564
|
+
public void onAdFailedToLoad(@NonNull LoadAdError error) {
|
|
565
|
+
handleError(error);
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// Preload
|
|
570
|
+
RewardedAdManager.INSTANCE.preload(context);
|
|
571
|
+
|
|
572
|
+
// Get stats
|
|
573
|
+
Map<String, Object> stats = RewardedAdManager.INSTANCE.getAdStats();
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## Troubleshooting
|
|
577
|
+
|
|
578
|
+
### Ad Not Loading
|
|
579
|
+
|
|
580
|
+
| Issue | Solution |
|
|
581
|
+
|-------|----------|
|
|
582
|
+
| No internet | Check connectivity |
|
|
583
|
+
| Wrong ad unit | Verify ad unit ID in AdMob console |
|
|
584
|
+
| Premium user | Check `BillingConfig.getPurchaseProvider().isPurchased()` |
|
|
585
|
+
| Rate limited | Wait for retry or check `getAdStats()["retry_attempts"]` |
|
|
586
|
+
|
|
587
|
+
### Ad Not Showing
|
|
588
|
+
|
|
589
|
+
| Issue | Solution |
|
|
590
|
+
|-------|----------|
|
|
591
|
+
| Not loaded | Check `isAdLoaded()` before showing |
|
|
592
|
+
| Already showing | Check `isShowingAd()` |
|
|
593
|
+
| Activity finishing | Ensure activity is valid |
|
|
594
|
+
|
|
595
|
+
### Low Fill Rate
|
|
596
|
+
|
|
597
|
+
1. Check stats: `getAdStats()["fill_rate_percent"]`
|
|
598
|
+
2. Use mediation for multiple ad sources
|
|
599
|
+
3. Verify ad unit is set up correctly
|
|
600
|
+
4. Test with test ad units first
|
|
601
|
+
|
|
602
|
+
### Rewards Not Granted
|
|
603
|
+
|
|
604
|
+
```kotlin
|
|
605
|
+
// Ensure you're handling the callback correctly
|
|
606
|
+
override fun onRewardEarned(rewardType: String, rewardAmount: Int) {
|
|
607
|
+
Log.d("Ads", "Reward: $rewardAmount $rewardType") // Debug
|
|
608
|
+
|
|
609
|
+
// Grant reward FIRST
|
|
610
|
+
grantReward(rewardAmount)
|
|
611
|
+
|
|
612
|
+
// Then update UI
|
|
613
|
+
updateUI()
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
## See Also
|
|
618
|
+
|
|
619
|
+
- [API Reference](API_REFERENCE.md#rewardedadmanager)
|
|
620
|
+
- [Interstitial Ads](interstitial-ads.md)
|
|
621
|
+
- [Ad Loading Strategies](AD_LOADING_STRATEGIES.md)
|
|
622
|
+
- [Configuration Guide](CONFIGURATION_USAGE.md)
|
|
623
|
+
- [Wiki: Rewarded Ads](../wiki/Rewarded-Ads.md)
|