@bigcrunch/react-native-ads 0.3.1 → 0.5.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 (64) hide show
  1. package/README.md +5 -5
  2. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchAds.kt +434 -0
  3. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchBannerView.kt +484 -0
  4. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchInterstitial.kt +403 -0
  5. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchRewarded.kt +409 -0
  6. package/android/bigcrunch-ads/com/bigcrunch/ads/adapters/GoogleAdsAdapter.kt +592 -0
  7. package/android/bigcrunch-ads/com/bigcrunch/ads/core/AdOrchestrator.kt +623 -0
  8. package/android/bigcrunch-ads/com/bigcrunch/ads/core/AnalyticsClient.kt +719 -0
  9. package/android/bigcrunch-ads/com/bigcrunch/ads/core/BidRequestClient.kt +364 -0
  10. package/android/bigcrunch-ads/com/bigcrunch/ads/core/ConfigManager.kt +301 -0
  11. package/android/bigcrunch-ads/com/bigcrunch/ads/core/DeviceContext.kt +385 -0
  12. package/android/bigcrunch-ads/com/bigcrunch/ads/core/RewardedCallback.kt +42 -0
  13. package/android/bigcrunch-ads/com/bigcrunch/ads/core/SessionManager.kt +330 -0
  14. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/DeviceHelper.kt +60 -0
  15. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/HttpClient.kt +114 -0
  16. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/Logger.kt +71 -0
  17. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/PrivacyStore.kt +125 -0
  18. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/Storage.kt +88 -0
  19. package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/BannerAdListener.kt +55 -0
  20. package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/InterstitialAdListener.kt +55 -0
  21. package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/RewardedAdListener.kt +58 -0
  22. package/android/bigcrunch-ads/com/bigcrunch/ads/models/AdEvent.kt +880 -0
  23. package/android/bigcrunch-ads/com/bigcrunch/ads/models/AppConfig.kt +90 -0
  24. package/android/bigcrunch-ads/com/bigcrunch/ads/models/DeviceData.kt +18 -0
  25. package/android/bigcrunch-ads/com/bigcrunch/ads/models/PlacementConfig.kt +70 -0
  26. package/android/bigcrunch-ads/com/bigcrunch/ads/models/SessionInfo.kt +21 -0
  27. package/android/build.gradle +22 -10
  28. package/android/settings.gradle +2 -6
  29. package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsModule.kt +0 -23
  30. package/ios/BigCrunchAds/Sources/Adapters/GoogleAdsAdapter.swift +512 -0
  31. package/ios/BigCrunchAds/Sources/BigCrunchAds.swift +387 -0
  32. package/ios/BigCrunchAds/Sources/BigCrunchBannerView.swift +448 -0
  33. package/ios/BigCrunchAds/Sources/BigCrunchInterstitial.swift +412 -0
  34. package/ios/BigCrunchAds/Sources/BigCrunchRewarded.swift +523 -0
  35. package/ios/BigCrunchAds/Sources/Core/AdOrchestrator.swift +514 -0
  36. package/ios/BigCrunchAds/Sources/Core/AnalyticsClient.swift +874 -0
  37. package/ios/BigCrunchAds/Sources/Core/BidRequestClient.swift +344 -0
  38. package/ios/BigCrunchAds/Sources/Core/ConfigManager.swift +306 -0
  39. package/ios/BigCrunchAds/Sources/Core/DeviceContext.swift +284 -0
  40. package/ios/BigCrunchAds/Sources/Core/SessionManager.swift +392 -0
  41. package/ios/BigCrunchAds/Sources/Internal/HTTPClient.swift +146 -0
  42. package/ios/BigCrunchAds/Sources/Internal/Logger.swift +62 -0
  43. package/ios/BigCrunchAds/Sources/Internal/PrivacyStore.swift +129 -0
  44. package/ios/BigCrunchAds/Sources/Internal/Storage.swift +73 -0
  45. package/ios/BigCrunchAds/Sources/Models/AdEvent.swift +784 -0
  46. package/ios/BigCrunchAds/Sources/Models/AppConfig.swift +100 -0
  47. package/ios/BigCrunchAds/Sources/Models/DeviceData.swift +68 -0
  48. package/ios/BigCrunchAds/Sources/Models/PlacementConfig.swift +137 -0
  49. package/ios/BigCrunchAds/Sources/Models/SessionInfo.swift +48 -0
  50. package/ios/BigCrunchAdsModule.swift +5 -14
  51. package/ios/BigCrunchBannerViewManager.swift +0 -1
  52. package/lib/index.d.ts +1 -1
  53. package/lib/index.d.ts.map +1 -1
  54. package/lib/index.js +3 -2
  55. package/lib/types/config.d.ts +22 -9
  56. package/lib/types/config.d.ts.map +1 -1
  57. package/lib/types/events.d.ts +4 -4
  58. package/lib/types/events.d.ts.map +1 -1
  59. package/package.json +11 -4
  60. package/react-native-bigcrunch-ads.podspec +1 -3
  61. package/scripts/inject-version.js +55 -0
  62. package/src/index.ts +3 -2
  63. package/src/types/config.ts +23 -9
  64. package/src/types/events.ts +4 -4
@@ -0,0 +1,403 @@
1
+ package com.bigcrunch.ads
2
+
3
+ import android.app.Activity
4
+ import android.content.Context
5
+ import com.bigcrunch.ads.adapters.GoogleAdsAdapter
6
+ import com.bigcrunch.ads.core.AdOrchestrator
7
+ import com.bigcrunch.ads.core.InterstitialCallback
8
+ import com.bigcrunch.ads.internal.BCLogger
9
+
10
+ /**
11
+ * BigCrunch Interstitial Ads - Static API for full-screen interstitial ads
12
+ *
13
+ * Interstitial ads are full-screen ads that cover the interface of an app until
14
+ * closed by the user. They're best used at natural transition points in the app.
15
+ *
16
+ * Usage:
17
+ * ```kotlin
18
+ * // 1. Preload the ad (do this early, e.g., when entering a screen)
19
+ * BigCrunchInterstitial.preload(
20
+ * context = applicationContext,
21
+ * placementId = "article_interstitial",
22
+ * callback = object : BigCrunchInterstitial.PreloadCallback {
23
+ * override fun onAdLoaded() { /* ad ready to show */ }
24
+ * override fun onAdFailedToLoad(error: String) { /* handle error */ }
25
+ * }
26
+ * )
27
+ *
28
+ * // 2. Check if ready (optional)
29
+ * if (BigCrunchInterstitial.isReady("article_interstitial")) {
30
+ * // Ad is ready to show
31
+ * }
32
+ *
33
+ * // 3. Show when appropriate (e.g., after completing an action)
34
+ * BigCrunchInterstitial.show(
35
+ * activity = this,
36
+ * placementId = "article_interstitial",
37
+ * callback = object : BigCrunchInterstitial.ShowCallback {
38
+ * override fun onAdShowed() { /* ad displayed */ }
39
+ * override fun onAdDismissed() { /* ad closed, resume app */ }
40
+ * override fun onAdClicked() { /* ad clicked */ }
41
+ * override fun onAdFailedToShow(error: String) { /* handle error */ }
42
+ * }
43
+ * )
44
+ * ```
45
+ */
46
+ object BigCrunchInterstitial {
47
+
48
+ private const val TAG = "BigCrunchInterstitial"
49
+ private var adOrchestrator: AdOrchestrator? = null
50
+ private val orchestratorLock = Any()
51
+
52
+ /**
53
+ * Safely execute a block, catching exceptions to prevent SDK crashes from affecting the host app.
54
+ */
55
+ private inline fun <T> safeExecute(default: T, block: () -> T): T {
56
+ return try {
57
+ block()
58
+ } catch (e: Exception) {
59
+ BCLogger.e(TAG, "Exception caught in interstitial - SDK will not propagate to prevent app crash", e)
60
+ default
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Safely execute a Unit-returning block.
66
+ */
67
+ private inline fun safeExecute(block: () -> Unit) {
68
+ try {
69
+ block()
70
+ } catch (e: Exception) {
71
+ BCLogger.e(TAG, "Exception caught in interstitial - SDK will not propagate to prevent app crash", e)
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Callback interface for preload events
77
+ */
78
+ interface PreloadCallback {
79
+ /**
80
+ * Called when the ad has been successfully preloaded and is ready to show
81
+ */
82
+ fun onAdLoaded()
83
+
84
+ /**
85
+ * Called when the ad fails to load
86
+ * @param error Description of the error
87
+ */
88
+ fun onAdFailedToLoad(error: String)
89
+ }
90
+
91
+ /**
92
+ * Callback interface for show events
93
+ */
94
+ interface ShowCallback {
95
+ /**
96
+ * Called when the ad is displayed on screen
97
+ */
98
+ fun onAdShowed()
99
+
100
+ /**
101
+ * Called when the ad is dismissed by the user
102
+ */
103
+ fun onAdDismissed()
104
+
105
+ /**
106
+ * Called when the user clicks on the ad
107
+ */
108
+ fun onAdClicked()
109
+
110
+ /**
111
+ * Called when the ad fails to show
112
+ * @param error Description of the error
113
+ */
114
+ fun onAdFailedToShow(error: String)
115
+ }
116
+
117
+ /**
118
+ * Legacy callback interface (for backwards compatibility)
119
+ */
120
+ interface Callback {
121
+ fun onAdShown()
122
+ fun onAdDismissed()
123
+ fun onAdFailed(error: String)
124
+ }
125
+
126
+ /**
127
+ * Preload an interstitial ad for the given placement
128
+ *
129
+ * Call this early (e.g., when entering a screen) to give the ad time to load.
130
+ * When the ad is ready, the callback's onAdLoaded() will be called.
131
+ *
132
+ * @param context Application context
133
+ * @param placementId The placement ID from BigCrunch dashboard
134
+ * @param callback Optional callback for load events
135
+ */
136
+ fun preload(
137
+ context: Context,
138
+ placementId: String,
139
+ callback: PreloadCallback? = null
140
+ ) = safeExecute {
141
+ BCLogger.d(TAG, "Preloading interstitial: $placementId")
142
+
143
+ if (!BigCrunchAds.isInitialized()) {
144
+ BCLogger.e(TAG, "SDK not initialized")
145
+ callback?.onAdFailedToLoad("SDK not initialized. Call BigCrunchAds.initialize() first.")
146
+ return@safeExecute
147
+ }
148
+
149
+ if (placementId.isBlank()) {
150
+ BCLogger.e(TAG, "Invalid placementId: cannot be blank")
151
+ callback?.onAdFailedToLoad("Invalid placementId: cannot be blank")
152
+ return@safeExecute
153
+ }
154
+
155
+ val orchestrator = getOrCreateOrchestrator(context)
156
+
157
+ val internalCallback = object : InterstitialCallback {
158
+ override fun onAdLoaded() {
159
+ BCLogger.d(TAG, "Interstitial preloaded: $placementId")
160
+ callback?.onAdLoaded()
161
+ }
162
+
163
+ override fun onAdFailedToLoad(error: String) {
164
+ BCLogger.w(TAG, "Interstitial failed to preload: $placementId - $error")
165
+ callback?.onAdFailedToLoad(error)
166
+ }
167
+
168
+ override fun onAdShowed() {
169
+ // Not used during preload
170
+ }
171
+
172
+ override fun onAdDismissed() {
173
+ // Not used during preload
174
+ }
175
+
176
+ override fun onAdClicked() {
177
+ // Not used during preload
178
+ }
179
+ }
180
+
181
+ orchestrator.preloadInterstitialAd(placementId, internalCallback)
182
+ }
183
+
184
+ /**
185
+ * Preload an interstitial ad (simplified version without callback)
186
+ *
187
+ * @param placementId The placement ID from BigCrunch dashboard
188
+ */
189
+ fun preload(placementId: String) = safeExecute {
190
+ if (!BigCrunchAds.isInitialized()) {
191
+ BCLogger.e(TAG, "SDK not initialized")
192
+ return@safeExecute
193
+ }
194
+ // Use application context from BigCrunchAds
195
+ val orchestrator = getOrCreateOrchestrator(null)
196
+ orchestrator.preloadInterstitialAd(placementId, object : InterstitialCallback {
197
+ override fun onAdLoaded() {
198
+ BCLogger.d(TAG, "Interstitial preloaded: $placementId")
199
+ }
200
+
201
+ override fun onAdFailedToLoad(error: String) {
202
+ BCLogger.w(TAG, "Interstitial failed to preload: $placementId - $error")
203
+ }
204
+
205
+ override fun onAdShowed() {}
206
+ override fun onAdDismissed() {}
207
+ override fun onAdClicked() {}
208
+ })
209
+ }
210
+
211
+ /**
212
+ * Show a preloaded interstitial ad
213
+ *
214
+ * The ad must be preloaded first using [preload]. Check [isReady] before calling
215
+ * this to ensure an ad is available.
216
+ *
217
+ * @param activity The activity to show the ad from
218
+ * @param placementId The placement ID
219
+ * @param callback Optional callback for show events
220
+ * @return true if an ad was available and will be shown, false otherwise
221
+ */
222
+ fun show(
223
+ activity: Activity,
224
+ placementId: String,
225
+ callback: ShowCallback? = null
226
+ ): Boolean = safeExecute(false) {
227
+ BCLogger.d(TAG, "Showing interstitial: $placementId")
228
+
229
+ if (!BigCrunchAds.isInitialized()) {
230
+ BCLogger.e(TAG, "SDK not initialized")
231
+ callback?.onAdFailedToShow("SDK not initialized. Call BigCrunchAds.initialize() first.")
232
+ return@safeExecute false
233
+ }
234
+
235
+ if (placementId.isBlank()) {
236
+ BCLogger.e(TAG, "Invalid placementId: cannot be blank")
237
+ callback?.onAdFailedToShow("Invalid placementId: cannot be blank")
238
+ return@safeExecute false
239
+ }
240
+
241
+ val orchestrator = getOrCreateOrchestrator(activity)
242
+
243
+ val internalCallback = object : InterstitialCallback {
244
+ override fun onAdLoaded() {
245
+ // Not used during show
246
+ }
247
+
248
+ override fun onAdFailedToLoad(error: String) {
249
+ BCLogger.w(TAG, "Interstitial failed to show: $placementId - $error")
250
+ callback?.onAdFailedToShow(error)
251
+ }
252
+
253
+ override fun onAdShowed() {
254
+ BCLogger.d(TAG, "Interstitial showed: $placementId")
255
+ callback?.onAdShowed()
256
+ }
257
+
258
+ override fun onAdDismissed() {
259
+ BCLogger.d(TAG, "Interstitial dismissed: $placementId")
260
+ callback?.onAdDismissed()
261
+ }
262
+
263
+ override fun onAdClicked() {
264
+ BCLogger.d(TAG, "Interstitial clicked: $placementId")
265
+ callback?.onAdClicked()
266
+ }
267
+ }
268
+
269
+ orchestrator.showInterstitialAd(activity, placementId, internalCallback)
270
+ }
271
+
272
+ /**
273
+ * Show a preloaded interstitial ad (legacy API)
274
+ *
275
+ * @param activity The activity to show the ad in
276
+ * @param placementId The placement ID
277
+ * @param callback Legacy callback for ad events
278
+ */
279
+ fun show(
280
+ activity: Activity,
281
+ placementId: String,
282
+ callback: Callback? = null
283
+ ) {
284
+ show(
285
+ activity = activity,
286
+ placementId = placementId,
287
+ callback = callback?.let { legacyCallback ->
288
+ object : ShowCallback {
289
+ override fun onAdShowed() = legacyCallback.onAdShown()
290
+ override fun onAdDismissed() = legacyCallback.onAdDismissed()
291
+ override fun onAdClicked() {}
292
+ override fun onAdFailedToShow(error: String) = legacyCallback.onAdFailed(error)
293
+ }
294
+ }
295
+ )
296
+ }
297
+
298
+ /**
299
+ * Check if an interstitial ad is ready to show
300
+ *
301
+ * @param placementId The placement ID
302
+ * @return true if an ad is preloaded and ready to show
303
+ */
304
+ fun isReady(placementId: String): Boolean = safeExecute(false) {
305
+ if (!BigCrunchAds.isInitialized()) {
306
+ BCLogger.w(TAG, "isReady called before SDK initialized")
307
+ return@safeExecute false
308
+ }
309
+ adOrchestrator?.isInterstitialReady(placementId) ?: false
310
+ }
311
+
312
+ /**
313
+ * Load an interstitial ad with custom targeting
314
+ *
315
+ * @param placementId The placement ID for the ad
316
+ * @param customTargeting Optional custom targeting parameters
317
+ */
318
+ fun load(placementId: String, customTargeting: Map<String, String>? = null) {
319
+ // For now, just call preload - custom targeting will be added in AdOrchestrator
320
+ preload(placementId)
321
+ if (customTargeting != null) {
322
+ BCLogger.d(TAG, "Custom targeting requested: ${customTargeting.size} parameters")
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Check if an interstitial ad is loaded and ready to show
328
+ *
329
+ * @param placementId The placement ID to check
330
+ * @return true if the ad is loaded and ready, false otherwise
331
+ */
332
+ fun isLoaded(placementId: String): Boolean = isReady(placementId)
333
+
334
+ /**
335
+ * Destroy a specific interstitial ad
336
+ *
337
+ * @param placementId The placement ID to destroy
338
+ */
339
+ fun destroy(placementId: String) = safeExecute {
340
+ BCLogger.d(TAG, "Destroying interstitial: $placementId")
341
+ synchronized(orchestratorLock) {
342
+ adOrchestrator?.destroyInterstitialAd(placementId)
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Destroy all cached interstitial ads
348
+ */
349
+ fun destroyAll() = safeExecute {
350
+ clearCache()
351
+ }
352
+
353
+ /**
354
+ * Clear all cached interstitial ads
355
+ *
356
+ * Call this to free up memory when ads are no longer needed.
357
+ */
358
+ fun clearCache() = safeExecute {
359
+ BCLogger.d(TAG, "Clearing interstitial cache")
360
+ synchronized(orchestratorLock) {
361
+ adOrchestrator?.clearCache()
362
+ }
363
+ }
364
+
365
+ private fun getOrCreateOrchestrator(context: Context?): AdOrchestrator {
366
+ synchronized(orchestratorLock) {
367
+ if (adOrchestrator == null) {
368
+ val ctx = context?.applicationContext
369
+ ?: throw IllegalStateException("Context required to create AdOrchestrator")
370
+
371
+ val configManager = BigCrunchAds.getConfigManager()
372
+ val analyticsClient = BigCrunchAds.getAnalyticsClient()
373
+ val googleAdsAdapter = GoogleAdsAdapter(ctx, analyticsClient)
374
+
375
+ val bidRequestClient = BigCrunchAds.bidRequestClient ?: com.bigcrunch.ads.core.BidRequestClient(
376
+ httpClient = com.bigcrunch.ads.internal.HttpClient(),
377
+ configManager = configManager,
378
+ privacyStore = BigCrunchAds.privacyStore,
379
+ s2sConfig = com.bigcrunch.ads.models.S2SConfig(enabled = false, serverUrl = "", timeoutMs = 0)
380
+ )
381
+
382
+ adOrchestrator = AdOrchestrator(
383
+ ctx,
384
+ configManager,
385
+ analyticsClient,
386
+ bidRequestClient,
387
+ googleAdsAdapter
388
+ )
389
+ }
390
+ return adOrchestrator!!
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Reset for testing purposes only
396
+ */
397
+ internal fun resetForTesting() {
398
+ synchronized(orchestratorLock) {
399
+ adOrchestrator?.clearCache()
400
+ adOrchestrator = null
401
+ }
402
+ }
403
+ }