@bigcrunch/react-native-ads 0.1.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/README.md +417 -0
- package/android/build.gradle +70 -0
- package/android/settings.gradle +6 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsModule.kt +653 -0
- package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsPackage.kt +20 -0
- package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchBannerViewManager.kt +296 -0
- package/ios/BigCrunchAdsModule.swift +588 -0
- package/ios/BigCrunchBannerViewManager.swift +270 -0
- package/ios/react-native-bigcrunch-ads-Bridging-Header.h +8 -0
- package/lib/BigCrunchAds.d.ts +168 -0
- package/lib/BigCrunchAds.d.ts.map +1 -0
- package/lib/BigCrunchAds.js +241 -0
- package/lib/BigCrunchBannerView.d.ts +21 -0
- package/lib/BigCrunchBannerView.d.ts.map +1 -0
- package/lib/BigCrunchBannerView.js +176 -0
- package/lib/BigCrunchInterstitial.d.ts +66 -0
- package/lib/BigCrunchInterstitial.d.ts.map +1 -0
- package/lib/BigCrunchInterstitial.js +222 -0
- package/lib/BigCrunchRewarded.d.ts +85 -0
- package/lib/BigCrunchRewarded.d.ts.map +1 -0
- package/lib/BigCrunchRewarded.js +257 -0
- package/lib/NativeBigCrunchAds.d.ts +71 -0
- package/lib/NativeBigCrunchAds.d.ts.map +1 -0
- package/lib/NativeBigCrunchAds.js +54 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +32 -0
- package/lib/types/ads.d.ts +101 -0
- package/lib/types/ads.d.ts.map +1 -0
- package/lib/types/ads.js +4 -0
- package/lib/types/config.d.ts +137 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +4 -0
- package/lib/types/events.d.ts +306 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +4 -0
- package/lib/types/index.d.ts +175 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +23 -0
- package/package.json +88 -0
- package/react-native-bigcrunch-ads.podspec +27 -0
- package/src/BigCrunchAds.ts +298 -0
- package/src/BigCrunchBannerView.tsx +262 -0
- package/src/BigCrunchInterstitial.ts +266 -0
- package/src/BigCrunchRewarded.ts +307 -0
- package/src/NativeBigCrunchAds.ts +120 -0
- package/src/index.ts +71 -0
- package/src/types/ads.ts +112 -0
- package/src/types/config.ts +145 -0
- package/src/types/events.ts +337 -0
- package/src/types/index.ts +193 -0
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
package com.bigcrunch.ads.react
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.*
|
|
4
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
5
|
+
import com.bigcrunch.ads.*
|
|
6
|
+
import com.bigcrunch.ads.models.*
|
|
7
|
+
import kotlinx.coroutines.*
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* React Native bridge module for BigCrunch Ads SDK
|
|
11
|
+
*/
|
|
12
|
+
class BigCrunchAdsModule(reactContext: ReactApplicationContext) :
|
|
13
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
14
|
+
|
|
15
|
+
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
|
16
|
+
private val interstitialCache = mutableMapOf<String, Any>() // Placeholder for interstitial instances
|
|
17
|
+
private val rewardedCache = mutableMapOf<String, Any>() // Placeholder for rewarded instances
|
|
18
|
+
|
|
19
|
+
override fun getName(): String = "BigCrunchAdsModule"
|
|
20
|
+
|
|
21
|
+
override fun onCatalystInstanceDestroy() {
|
|
22
|
+
super.onCatalystInstanceDestroy()
|
|
23
|
+
scope.cancel()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initialize the SDK
|
|
28
|
+
*/
|
|
29
|
+
@ReactMethod
|
|
30
|
+
fun initialize(options: ReadableMap, promise: Promise) {
|
|
31
|
+
try {
|
|
32
|
+
val propertyId = options.getString("propertyId")
|
|
33
|
+
?: throw IllegalArgumentException("propertyId is required")
|
|
34
|
+
val apiKey = options.getString("apiKey")
|
|
35
|
+
?: throw IllegalArgumentException("apiKey is required")
|
|
36
|
+
val environment = options.getString("environment") ?: "production"
|
|
37
|
+
val debug = if (options.hasKey("debug")) options.getBoolean("debug") else false
|
|
38
|
+
|
|
39
|
+
// Initialize the native SDK
|
|
40
|
+
val context = reactApplicationContext.applicationContext
|
|
41
|
+
|
|
42
|
+
scope.launch {
|
|
43
|
+
try {
|
|
44
|
+
BigCrunchAds.initialize(
|
|
45
|
+
context = context,
|
|
46
|
+
propertyId = propertyId,
|
|
47
|
+
apiKey = apiKey,
|
|
48
|
+
env = if (environment == "staging")
|
|
49
|
+
BigCrunchAds.Environment.Staging
|
|
50
|
+
else
|
|
51
|
+
BigCrunchAds.Environment.Prod,
|
|
52
|
+
// Use mock config for testing/development
|
|
53
|
+
useMockConfig = environment == "sandbox"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if (debug) {
|
|
57
|
+
BigCrunchAds.setDebugMode(true)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// SDK initialization is complete
|
|
61
|
+
// The Android SDK now handles config loading internally
|
|
62
|
+
promise.resolve(null)
|
|
63
|
+
} catch (e: Exception) {
|
|
64
|
+
promise.reject("INIT_ERROR", "Failed to initialize SDK: ${e.message}", e)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} catch (e: Exception) {
|
|
68
|
+
promise.reject("INIT_ERROR", "Failed to initialize SDK: ${e.message}", e)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if SDK is initialized
|
|
74
|
+
*/
|
|
75
|
+
@ReactMethod
|
|
76
|
+
fun isInitialized(promise: Promise) {
|
|
77
|
+
promise.resolve(BigCrunchAds.isInitialized())
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Track screen view
|
|
82
|
+
*/
|
|
83
|
+
@ReactMethod
|
|
84
|
+
fun trackScreenView(screenName: String, promise: Promise) {
|
|
85
|
+
scope.launch {
|
|
86
|
+
try {
|
|
87
|
+
BigCrunchAds.trackScreenView(screenName)
|
|
88
|
+
promise.resolve(null)
|
|
89
|
+
} catch (e: Exception) {
|
|
90
|
+
promise.reject("TRACK_ERROR", "Failed to track screen view: ${e.message}", e)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get app configuration
|
|
97
|
+
*/
|
|
98
|
+
@ReactMethod
|
|
99
|
+
fun getAppConfig(promise: Promise) {
|
|
100
|
+
scope.launch {
|
|
101
|
+
try {
|
|
102
|
+
val config = BigCrunchAds.getAppConfig()
|
|
103
|
+
if (config != null) {
|
|
104
|
+
promise.resolve(convertAppConfigToMap(config))
|
|
105
|
+
} else {
|
|
106
|
+
promise.resolve(null)
|
|
107
|
+
}
|
|
108
|
+
} catch (e: Exception) {
|
|
109
|
+
promise.reject("CONFIG_ERROR", "Failed to get app config: ${e.message}", e)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Refresh configuration
|
|
116
|
+
*/
|
|
117
|
+
@ReactMethod
|
|
118
|
+
fun refreshConfig(promise: Promise) {
|
|
119
|
+
scope.launch {
|
|
120
|
+
try {
|
|
121
|
+
BigCrunchAds.refreshConfig()
|
|
122
|
+
promise.resolve(null)
|
|
123
|
+
} catch (e: Exception) {
|
|
124
|
+
promise.reject("CONFIG_ERROR", "Failed to refresh config: ${e.message}", e)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Load interstitial ad
|
|
131
|
+
*/
|
|
132
|
+
@ReactMethod
|
|
133
|
+
fun loadInterstitial(options: ReadableMap, promise: Promise) {
|
|
134
|
+
try {
|
|
135
|
+
val placementId = options.getString("placementId")
|
|
136
|
+
?: throw IllegalArgumentException("placementId is required")
|
|
137
|
+
|
|
138
|
+
scope.launch {
|
|
139
|
+
try {
|
|
140
|
+
// Create ad request options
|
|
141
|
+
val customTargeting = options.getMap("customTargeting")?.let {
|
|
142
|
+
convertMapToStringMap(it)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Set up callbacks to emit events to JavaScript
|
|
146
|
+
val context = reactApplicationContext.applicationContext
|
|
147
|
+
BigCrunchInterstitial.preload(
|
|
148
|
+
context = context,
|
|
149
|
+
placementId = placementId,
|
|
150
|
+
callback = object : BigCrunchInterstitial.PreloadCallback {
|
|
151
|
+
override fun onAdLoaded() {
|
|
152
|
+
val eventParams = Arguments.createMap()
|
|
153
|
+
eventParams.putString("placementId", placementId)
|
|
154
|
+
sendEvent("BigCrunchInterstitialAdLoaded", eventParams)
|
|
155
|
+
|
|
156
|
+
// Store the loaded ad in cache (for tracking)
|
|
157
|
+
interstitialCache[placementId] = true
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
override fun onAdFailedToLoad(error: String) {
|
|
161
|
+
val eventParams = Arguments.createMap()
|
|
162
|
+
eventParams.putString("placementId", placementId)
|
|
163
|
+
eventParams.putString("errorCode", "LOAD_FAILED")
|
|
164
|
+
eventParams.putString("errorMessage", error)
|
|
165
|
+
sendEvent("BigCrunchInterstitialAdFailedToLoad", eventParams)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
// Apply custom targeting if provided (will be implemented in AdOrchestrator later)
|
|
171
|
+
if (customTargeting != null) {
|
|
172
|
+
// TODO: Pass custom targeting to AdOrchestrator
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
promise.resolve(null)
|
|
176
|
+
} catch (e: Exception) {
|
|
177
|
+
promise.reject("LOAD_ERROR", "Failed to load interstitial: ${e.message}", e)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} catch (e: Exception) {
|
|
181
|
+
promise.reject("LOAD_ERROR", "Failed to load interstitial: ${e.message}", e)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Show interstitial ad
|
|
187
|
+
*/
|
|
188
|
+
@ReactMethod
|
|
189
|
+
fun showInterstitial(placementId: String, promise: Promise) {
|
|
190
|
+
val activity = currentActivity
|
|
191
|
+
if (activity == null) {
|
|
192
|
+
promise.reject("NO_ACTIVITY", "No current activity available")
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
scope.launch {
|
|
197
|
+
try {
|
|
198
|
+
val callback = object : BigCrunchInterstitial.ShowCallback {
|
|
199
|
+
override fun onAdShowed() {
|
|
200
|
+
val eventParams = Arguments.createMap()
|
|
201
|
+
eventParams.putString("placementId", placementId)
|
|
202
|
+
sendEvent("BigCrunchInterstitialAdOpened", eventParams)
|
|
203
|
+
|
|
204
|
+
// Also emit impression event
|
|
205
|
+
sendEvent("BigCrunchInterstitialAdImpression", eventParams)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
override fun onAdDismissed() {
|
|
209
|
+
val eventParams = Arguments.createMap()
|
|
210
|
+
eventParams.putString("placementId", placementId)
|
|
211
|
+
sendEvent("BigCrunchInterstitialAdClosed", eventParams)
|
|
212
|
+
|
|
213
|
+
// Clear from cache on dismissal
|
|
214
|
+
interstitialCache.remove(placementId)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
override fun onAdClicked() {
|
|
218
|
+
val eventParams = Arguments.createMap()
|
|
219
|
+
eventParams.putString("placementId", placementId)
|
|
220
|
+
sendEvent("BigCrunchInterstitialAdClicked", eventParams)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
override fun onAdFailedToShow(error: String) {
|
|
224
|
+
val eventParams = Arguments.createMap()
|
|
225
|
+
eventParams.putString("placementId", placementId)
|
|
226
|
+
eventParams.putString("errorCode", "SHOW_FAILED")
|
|
227
|
+
eventParams.putString("errorMessage", error)
|
|
228
|
+
sendEvent("BigCrunchInterstitialAdFailedToShow", eventParams)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
BigCrunchInterstitial.show(activity, placementId, callback)
|
|
233
|
+
promise.resolve(null)
|
|
234
|
+
} catch (e: Exception) {
|
|
235
|
+
promise.reject("SHOW_ERROR", "Failed to show interstitial: ${e.message}", e)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Check if interstitial is loaded
|
|
242
|
+
*/
|
|
243
|
+
@ReactMethod
|
|
244
|
+
fun isInterstitialLoaded(placementId: String, promise: Promise) {
|
|
245
|
+
promise.resolve(BigCrunchInterstitial.isLoaded(placementId))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Destroy interstitial
|
|
250
|
+
*/
|
|
251
|
+
@ReactMethod
|
|
252
|
+
fun destroyInterstitial(placementId: String, promise: Promise) {
|
|
253
|
+
try {
|
|
254
|
+
BigCrunchInterstitial.destroy(placementId)
|
|
255
|
+
interstitialCache.remove(placementId)
|
|
256
|
+
promise.resolve(null)
|
|
257
|
+
} catch (e: Exception) {
|
|
258
|
+
promise.reject("DESTROY_ERROR", "Failed to destroy interstitial: ${e.message}", e)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Load rewarded ad
|
|
264
|
+
*/
|
|
265
|
+
@ReactMethod
|
|
266
|
+
fun loadRewarded(options: ReadableMap, promise: Promise) {
|
|
267
|
+
try {
|
|
268
|
+
val placementId = options.getString("placementId")
|
|
269
|
+
?: throw IllegalArgumentException("placementId is required")
|
|
270
|
+
|
|
271
|
+
scope.launch {
|
|
272
|
+
try {
|
|
273
|
+
val customTargeting = options.getMap("customTargeting")?.let {
|
|
274
|
+
convertMapToStringMap(it)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Set up callbacks to emit events to JavaScript
|
|
278
|
+
val context = reactApplicationContext.applicationContext
|
|
279
|
+
BigCrunchRewarded.preload(
|
|
280
|
+
context = context,
|
|
281
|
+
placementId = placementId,
|
|
282
|
+
callback = object : BigCrunchRewarded.PreloadCallback {
|
|
283
|
+
override fun onAdLoaded() {
|
|
284
|
+
val eventParams = Arguments.createMap()
|
|
285
|
+
eventParams.putString("placementId", placementId)
|
|
286
|
+
sendEvent("BigCrunchRewardedAdLoaded", eventParams)
|
|
287
|
+
|
|
288
|
+
// Store the loaded ad in cache (for tracking)
|
|
289
|
+
rewardedCache[placementId] = true
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
override fun onAdFailedToLoad(error: String) {
|
|
293
|
+
val eventParams = Arguments.createMap()
|
|
294
|
+
eventParams.putString("placementId", placementId)
|
|
295
|
+
eventParams.putString("errorCode", "LOAD_FAILED")
|
|
296
|
+
eventParams.putString("errorMessage", error)
|
|
297
|
+
sendEvent("BigCrunchRewardedAdFailedToLoad", eventParams)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
// Apply custom targeting if provided (will be implemented in AdOrchestrator later)
|
|
303
|
+
if (customTargeting != null) {
|
|
304
|
+
// TODO: Pass custom targeting to AdOrchestrator
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
promise.resolve(null)
|
|
308
|
+
} catch (e: Exception) {
|
|
309
|
+
promise.reject("LOAD_ERROR", "Failed to load rewarded: ${e.message}", e)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} catch (e: Exception) {
|
|
313
|
+
promise.reject("LOAD_ERROR", "Failed to load rewarded: ${e.message}", e)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Show rewarded ad
|
|
319
|
+
*/
|
|
320
|
+
@ReactMethod
|
|
321
|
+
fun showRewarded(placementId: String, promise: Promise) {
|
|
322
|
+
val activity = currentActivity
|
|
323
|
+
if (activity == null) {
|
|
324
|
+
promise.reject("NO_ACTIVITY", "No current activity available")
|
|
325
|
+
return
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
scope.launch {
|
|
329
|
+
try {
|
|
330
|
+
val callback = object : BigCrunchRewarded.ShowCallback {
|
|
331
|
+
override fun onAdShowed() {
|
|
332
|
+
val eventParams = Arguments.createMap()
|
|
333
|
+
eventParams.putString("placementId", placementId)
|
|
334
|
+
sendEvent("BigCrunchRewardedAdOpened", eventParams)
|
|
335
|
+
|
|
336
|
+
// Also emit impression event
|
|
337
|
+
sendEvent("BigCrunchRewardedAdImpression", eventParams)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
override fun onUserEarnedReward(type: String, amount: Int) {
|
|
341
|
+
val eventParams = Arguments.createMap()
|
|
342
|
+
eventParams.putString("placementId", placementId)
|
|
343
|
+
eventParams.putString("type", type)
|
|
344
|
+
eventParams.putInt("amount", amount)
|
|
345
|
+
sendEvent("BigCrunchRewardedAdEarned", eventParams)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
override fun onAdDismissed() {
|
|
349
|
+
val eventParams = Arguments.createMap()
|
|
350
|
+
eventParams.putString("placementId", placementId)
|
|
351
|
+
sendEvent("BigCrunchRewardedAdClosed", eventParams)
|
|
352
|
+
|
|
353
|
+
// Clear from cache on dismissal
|
|
354
|
+
rewardedCache.remove(placementId)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
override fun onAdClicked() {
|
|
358
|
+
val eventParams = Arguments.createMap()
|
|
359
|
+
eventParams.putString("placementId", placementId)
|
|
360
|
+
sendEvent("BigCrunchRewardedAdClicked", eventParams)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
override fun onAdFailedToShow(error: String) {
|
|
364
|
+
val eventParams = Arguments.createMap()
|
|
365
|
+
eventParams.putString("placementId", placementId)
|
|
366
|
+
eventParams.putString("errorCode", "SHOW_FAILED")
|
|
367
|
+
eventParams.putString("errorMessage", error)
|
|
368
|
+
sendEvent("BigCrunchRewardedAdFailedToShow", eventParams)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
BigCrunchRewarded.show(activity, placementId, callback)
|
|
373
|
+
promise.resolve(null)
|
|
374
|
+
} catch (e: Exception) {
|
|
375
|
+
promise.reject("SHOW_ERROR", "Failed to show rewarded: ${e.message}", e)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Check if rewarded is loaded
|
|
382
|
+
*/
|
|
383
|
+
@ReactMethod
|
|
384
|
+
fun isRewardedLoaded(placementId: String, promise: Promise) {
|
|
385
|
+
promise.resolve(BigCrunchRewarded.isLoaded(placementId))
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Destroy rewarded
|
|
390
|
+
*/
|
|
391
|
+
@ReactMethod
|
|
392
|
+
fun destroyRewarded(placementId: String, promise: Promise) {
|
|
393
|
+
try {
|
|
394
|
+
BigCrunchRewarded.destroy(placementId)
|
|
395
|
+
rewardedCache.remove(placementId)
|
|
396
|
+
promise.resolve(null)
|
|
397
|
+
} catch (e: Exception) {
|
|
398
|
+
promise.reject("DESTROY_ERROR", "Failed to destroy rewarded: ${e.message}", e)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Get session info
|
|
404
|
+
*/
|
|
405
|
+
@ReactMethod
|
|
406
|
+
fun getSessionInfo(promise: Promise) {
|
|
407
|
+
scope.launch {
|
|
408
|
+
try {
|
|
409
|
+
val sessionInfo = BigCrunchAds.getSessionInfo()
|
|
410
|
+
promise.resolve(convertSessionInfoToMap(sessionInfo))
|
|
411
|
+
} catch (e: Exception) {
|
|
412
|
+
promise.reject("SESSION_ERROR", "Failed to get session info: ${e.message}", e)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Start new session
|
|
419
|
+
*/
|
|
420
|
+
@ReactMethod
|
|
421
|
+
fun startNewSession(promise: Promise) {
|
|
422
|
+
scope.launch {
|
|
423
|
+
try {
|
|
424
|
+
BigCrunchAds.startNewSession()
|
|
425
|
+
promise.resolve(null)
|
|
426
|
+
} catch (e: Exception) {
|
|
427
|
+
promise.reject("SESSION_ERROR", "Failed to start new session: ${e.message}", e)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Get device context
|
|
434
|
+
*/
|
|
435
|
+
@ReactMethod
|
|
436
|
+
fun getDeviceContext(promise: Promise) {
|
|
437
|
+
scope.launch {
|
|
438
|
+
try {
|
|
439
|
+
val deviceData = BigCrunchAds.getDeviceData()
|
|
440
|
+
promise.resolve(convertDeviceDataToMap(deviceData))
|
|
441
|
+
} catch (e: Exception) {
|
|
442
|
+
promise.reject("DEVICE_ERROR", "Failed to get device data: ${e.message}", e)
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Set GDPR consent
|
|
449
|
+
*/
|
|
450
|
+
@ReactMethod
|
|
451
|
+
fun setGdprConsent(consent: String, promise: Promise) {
|
|
452
|
+
try {
|
|
453
|
+
BigCrunchAds.setGdprConsent(consent)
|
|
454
|
+
promise.resolve(null)
|
|
455
|
+
} catch (e: Exception) {
|
|
456
|
+
promise.reject("PRIVACY_ERROR", "Failed to set GDPR consent: ${e.message}", e)
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Set CCPA string
|
|
462
|
+
*/
|
|
463
|
+
@ReactMethod
|
|
464
|
+
fun setCcpaString(ccpaString: String, promise: Promise) {
|
|
465
|
+
try {
|
|
466
|
+
BigCrunchAds.setCcpaString(ccpaString)
|
|
467
|
+
promise.resolve(null)
|
|
468
|
+
} catch (e: Exception) {
|
|
469
|
+
promise.reject("PRIVACY_ERROR", "Failed to set CCPA string: ${e.message}", e)
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Set COPPA compliant
|
|
475
|
+
*/
|
|
476
|
+
@ReactMethod
|
|
477
|
+
fun setCoppaCompliant(isCompliant: Boolean, promise: Promise) {
|
|
478
|
+
try {
|
|
479
|
+
BigCrunchAds.setCoppaCompliant(isCompliant)
|
|
480
|
+
promise.resolve(null)
|
|
481
|
+
} catch (e: Exception) {
|
|
482
|
+
promise.reject("PRIVACY_ERROR", "Failed to set COPPA compliance: ${e.message}", e)
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Set debug mode
|
|
488
|
+
*/
|
|
489
|
+
@ReactMethod
|
|
490
|
+
fun setDebugMode(enabled: Boolean, promise: Promise) {
|
|
491
|
+
try {
|
|
492
|
+
BigCrunchAds.setDebugMode(enabled)
|
|
493
|
+
promise.resolve(null)
|
|
494
|
+
} catch (e: Exception) {
|
|
495
|
+
promise.reject("DEBUG_ERROR", "Failed to set debug mode: ${e.message}", e)
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Add test device
|
|
501
|
+
*/
|
|
502
|
+
@ReactMethod
|
|
503
|
+
fun addTestDevice(deviceId: String, promise: Promise) {
|
|
504
|
+
try {
|
|
505
|
+
BigCrunchAds.addTestDevice(deviceId)
|
|
506
|
+
promise.resolve(null)
|
|
507
|
+
} catch (e: Exception) {
|
|
508
|
+
promise.reject("TEST_ERROR", "Failed to add test device: ${e.message}", e)
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Remove test device
|
|
514
|
+
*/
|
|
515
|
+
@ReactMethod
|
|
516
|
+
fun removeTestDevice(deviceId: String, promise: Promise) {
|
|
517
|
+
try {
|
|
518
|
+
BigCrunchAds.removeTestDevice(deviceId)
|
|
519
|
+
promise.resolve(null)
|
|
520
|
+
} catch (e: Exception) {
|
|
521
|
+
promise.reject("TEST_ERROR", "Failed to remove test device: ${e.message}", e)
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Get test devices
|
|
527
|
+
*/
|
|
528
|
+
@ReactMethod
|
|
529
|
+
fun getTestDevices(promise: Promise) {
|
|
530
|
+
try {
|
|
531
|
+
val devices = BigCrunchAds.getTestDevices()
|
|
532
|
+
promise.resolve(Arguments.fromList(devices))
|
|
533
|
+
} catch (e: Exception) {
|
|
534
|
+
promise.reject("TEST_ERROR", "Failed to get test devices: ${e.message}", e)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Add event listener (required for NativeEventEmitter)
|
|
540
|
+
*/
|
|
541
|
+
@ReactMethod
|
|
542
|
+
fun addListener(eventName: String) {
|
|
543
|
+
// Keep track of listeners if needed
|
|
544
|
+
// This is required for NativeEventEmitter to work properly
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Remove event listeners (required for NativeEventEmitter)
|
|
549
|
+
*/
|
|
550
|
+
@ReactMethod
|
|
551
|
+
fun removeListeners(count: Int) {
|
|
552
|
+
// Remove listeners if needed
|
|
553
|
+
// This is required for NativeEventEmitter to work properly
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Send event to JavaScript
|
|
558
|
+
*/
|
|
559
|
+
private fun sendEvent(eventName: String, params: WritableMap?) {
|
|
560
|
+
reactApplicationContext
|
|
561
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
562
|
+
.emit(eventName, params)
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Helper conversion methods
|
|
566
|
+
private fun convertAppConfigToMap(config: AppConfig): WritableMap {
|
|
567
|
+
val map = Arguments.createMap()
|
|
568
|
+
map.putString("propertyId", config.propertyId)
|
|
569
|
+
map.putString("appName", config.appName)
|
|
570
|
+
|
|
571
|
+
val placements = Arguments.createArray()
|
|
572
|
+
config.placements.forEach { placement ->
|
|
573
|
+
placements.pushMap(convertPlacementConfigToMap(placement))
|
|
574
|
+
}
|
|
575
|
+
map.putArray("placements", placements)
|
|
576
|
+
|
|
577
|
+
return map
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
private fun convertPlacementConfigToMap(config: PlacementConfig): WritableMap {
|
|
581
|
+
val map = Arguments.createMap()
|
|
582
|
+
map.putString("placementId", config.placementId)
|
|
583
|
+
map.putString("format", config.format)
|
|
584
|
+
map.putString("gamAdUnit", config.gamAdUnit)
|
|
585
|
+
|
|
586
|
+
// Add sizes array if available
|
|
587
|
+
config.sizes?.let { sizes ->
|
|
588
|
+
val sizesArray = Arguments.createArray()
|
|
589
|
+
for (size in sizes) {
|
|
590
|
+
val sizeMap = Arguments.createMap()
|
|
591
|
+
sizeMap.putInt("width", size.width)
|
|
592
|
+
sizeMap.putInt("height", size.height)
|
|
593
|
+
sizesArray.pushMap(sizeMap)
|
|
594
|
+
}
|
|
595
|
+
map.putArray("sizes", sizesArray)
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Add Prebid config ID if available
|
|
599
|
+
config.prebidConfigId?.let {
|
|
600
|
+
map.putString("prebidConfigId", it)
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Add refresh config if available
|
|
604
|
+
config.refresh?.let { refresh ->
|
|
605
|
+
val refreshMap = Arguments.createMap()
|
|
606
|
+
refreshMap.putBoolean("enabled", refresh.enabled)
|
|
607
|
+
refreshMap.putInt("intervalMs", refresh.intervalMs)
|
|
608
|
+
refresh.maxRefreshes?.let { refreshMap.putInt("maxRefreshes", it) }
|
|
609
|
+
map.putMap("refresh", refreshMap)
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
return map
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
private fun convertSessionInfoToMap(info: SessionInfo): WritableMap {
|
|
616
|
+
val map = Arguments.createMap()
|
|
617
|
+
map.putString("sessionId", info.sessionId)
|
|
618
|
+
map.putString("startTime", info.startTime) // Changed from toDouble() - now ISO 8601 string
|
|
619
|
+
map.putInt("screenViewCount", info.screenViewCount)
|
|
620
|
+
map.putInt("adRequestCount", info.adRequestCount)
|
|
621
|
+
map.putInt("adImpressionCount", info.adImpressionCount)
|
|
622
|
+
map.putDouble("totalRevenueMicros", info.totalRevenueMicros.toDouble())
|
|
623
|
+
return map
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
private fun convertDeviceDataToMap(data: DeviceData): WritableMap {
|
|
627
|
+
val map = Arguments.createMap()
|
|
628
|
+
map.putString("deviceId", data.deviceId)
|
|
629
|
+
map.putString("deviceModel", data.deviceModel)
|
|
630
|
+
map.putString("osVersion", data.osVersion)
|
|
631
|
+
map.putString("appVersion", data.appVersion)
|
|
632
|
+
map.putInt("screenWidth", data.screenWidth)
|
|
633
|
+
map.putInt("screenHeight", data.screenHeight)
|
|
634
|
+
map.putString("language", data.language)
|
|
635
|
+
map.putString("country", data.country)
|
|
636
|
+
map.putBoolean("isTablet", data.isTablet)
|
|
637
|
+
data.carrier?.let { map.putString("carrier", it) }
|
|
638
|
+
data.networkType?.let { map.putString("networkType", it) }
|
|
639
|
+
return map
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
private fun convertMapToStringMap(map: ReadableMap): Map<String, String> {
|
|
643
|
+
val result = mutableMapOf<String, String>()
|
|
644
|
+
val iterator = map.keySetIterator()
|
|
645
|
+
while (iterator.hasNextKey()) {
|
|
646
|
+
val key = iterator.nextKey()
|
|
647
|
+
map.getString(key)?.let { value ->
|
|
648
|
+
result[key] = value
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return result
|
|
652
|
+
}
|
|
653
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.bigcrunch.ads.react
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* React Native package for BigCrunch Ads SDK
|
|
10
|
+
*/
|
|
11
|
+
class BigCrunchAdsPackage : ReactPackage {
|
|
12
|
+
|
|
13
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
14
|
+
return listOf(BigCrunchAdsModule(reactContext))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
18
|
+
return listOf(BigCrunchBannerViewManager())
|
|
19
|
+
}
|
|
20
|
+
}
|