cloudx-react-native 3.4.7 → 3.6.1
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/android/build.gradle +1 -1
- package/android/src/main/java/com/cloudxreactnative/CloudXAdEvents.kt +11 -5
- package/android/src/main/java/com/cloudxreactnative/CloudXAdInfo.kt +14 -0
- package/android/src/main/java/com/cloudxreactnative/CloudXAdView.kt +9 -15
- package/android/src/main/java/com/cloudxreactnative/CloudXAdViewEvent.kt +1 -1
- package/android/src/main/java/com/cloudxreactnative/CloudXModuleImpl.kt +202 -0
- package/android/src/newarch/com/cloudxreactnative/CloudXModule.kt +7 -0
- package/android/src/oldarch/com/cloudxreactnative/CloudXModule.kt +7 -0
- package/cloudx-react-native.podspec +3 -3
- package/ios/CloudX.h +2 -2
- package/ios/CloudX.mm +284 -9
- package/ios/CloudXAdView.h +10 -12
- package/ios/CloudXAdView.mm +10 -15
- package/ios/CloudXAdViewManager.h +6 -6
- package/ios/CloudXAdViewManager.mm +4 -4
- package/lib/commonjs/CloudX.js +5 -1
- package/lib/commonjs/CloudX.js.map +1 -1
- package/lib/commonjs/CloudXAdViewBase.js +11 -9
- package/lib/commonjs/CloudXAdViewBase.js.map +1 -1
- package/lib/commonjs/CloudXAppOpenAd.js +98 -0
- package/lib/commonjs/CloudXAppOpenAd.js.map +1 -0
- package/lib/commonjs/CloudXBannerView.js +2 -2
- package/lib/commonjs/CloudXMRECView.js +2 -2
- package/lib/commonjs/hooks.js +81 -0
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/commonjs/index.js +37 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/CloudXAdViewNativeComponent.js +1 -1
- package/lib/commonjs/specs/NativeCloudX.js.map +1 -1
- package/lib/commonjs/types/AppOpenAd.js +6 -0
- package/lib/commonjs/types/AppOpenAd.js.map +1 -0
- package/lib/commonjs/types/Arbiter.js +6 -0
- package/lib/commonjs/types/Arbiter.js.map +1 -1
- package/lib/commonjs/types/RevenueData.js +21 -0
- package/lib/commonjs/types/RevenueData.js.map +1 -0
- package/lib/commonjs/types/index.js +17 -0
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/CloudX.js +5 -1
- package/lib/module/CloudX.js.map +1 -1
- package/lib/module/CloudXAdViewBase.js +11 -9
- package/lib/module/CloudXAdViewBase.js.map +1 -1
- package/lib/module/CloudXAppOpenAd.js +91 -0
- package/lib/module/CloudXAppOpenAd.js.map +1 -0
- package/lib/module/CloudXBannerView.js +2 -2
- package/lib/module/CloudXMRECView.js +2 -2
- package/lib/module/hooks.js +80 -0
- package/lib/module/hooks.js.map +1 -1
- package/lib/module/index.js +7 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/CloudXAdViewNativeComponent.js +1 -1
- package/lib/module/specs/NativeCloudX.js.map +1 -1
- package/lib/module/types/AppOpenAd.js +2 -0
- package/lib/module/types/AppOpenAd.js.map +1 -0
- package/lib/module/types/Arbiter.js +6 -0
- package/lib/module/types/Arbiter.js.map +1 -1
- package/lib/module/types/RevenueData.js +15 -0
- package/lib/module/types/RevenueData.js.map +1 -0
- package/lib/module/types/index.js +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/CloudX.d.ts.map +1 -1
- package/lib/typescript/src/CloudXAdViewBase.d.ts +1 -1
- package/lib/typescript/src/CloudXAdViewBase.d.ts.map +1 -1
- package/lib/typescript/src/CloudXAppOpenAd.d.ts +4 -0
- package/lib/typescript/src/CloudXAppOpenAd.d.ts.map +1 -0
- package/lib/typescript/src/CloudXBannerView.d.ts +2 -2
- package/lib/typescript/src/CloudXMRECView.d.ts +2 -2
- package/lib/typescript/src/hooks.d.ts +14 -0
- package/lib/typescript/src/hooks.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts +1 -1
- package/lib/typescript/src/specs/NativeCloudX.d.ts +13 -0
- package/lib/typescript/src/specs/NativeCloudX.d.ts.map +1 -1
- package/lib/typescript/src/types/AppOpenAd.d.ts +8 -0
- package/lib/typescript/src/types/AppOpenAd.d.ts.map +1 -0
- package/lib/typescript/src/types/Arbiter.d.ts +12 -2
- package/lib/typescript/src/types/Arbiter.d.ts.map +1 -1
- package/lib/typescript/src/types/CloudX.d.ts +6 -0
- package/lib/typescript/src/types/CloudX.d.ts.map +1 -1
- package/lib/typescript/src/types/RevenueData.d.ts +32 -0
- package/lib/typescript/src/types/RevenueData.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +4 -1
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +6 -2
- package/src/CloudX.ts +6 -0
- package/src/CloudXAdViewBase.tsx +12 -11
- package/src/CloudXAppOpenAd.ts +109 -0
- package/src/CloudXBannerView.tsx +2 -2
- package/src/CloudXMRECView.tsx +2 -2
- package/src/hooks.ts +103 -0
- package/src/index.ts +18 -2
- package/src/specs/CloudXAdViewNativeComponent.ts +1 -1
- package/src/specs/NativeCloudX.ts +22 -0
- package/src/types/AppOpenAd.ts +8 -0
- package/src/types/Arbiter.ts +20 -2
- package/src/types/CloudX.ts +7 -0
- package/src/types/RevenueData.ts +39 -0
- package/src/types/index.ts +4 -0
- package/src/version.ts +1 -1
package/android/build.gradle
CHANGED
|
@@ -17,11 +17,8 @@ object CloudXAdEvents {
|
|
|
17
17
|
const val ON_MREC_AD_COLLAPSED_EVENT = "OnMRecAdCollapsedEvent"
|
|
18
18
|
const val ON_MREC_AD_REVENUE_PAID = "OnMRecAdRevenuePaid"
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* direct events. These strings are both the event key and the JS prop
|
|
23
|
-
* registrationName.
|
|
24
|
-
*/
|
|
20
|
+
// In-tree Ad View component (CloudXBannerView / CloudXMRECView) per-view direct events.
|
|
21
|
+
// These strings are both the event key and the JS prop registrationName.
|
|
25
22
|
const val ON_AD_VIEW_LOADED_EVENT = "onAdLoadedEvent"
|
|
26
23
|
const val ON_AD_VIEW_LOAD_FAILED_EVENT = "onAdLoadFailedEvent"
|
|
27
24
|
const val ON_AD_VIEW_CLICKED_EVENT = "onAdClickedEvent"
|
|
@@ -36,6 +33,15 @@ object CloudXAdEvents {
|
|
|
36
33
|
const val ON_INTERSTITIAL_HIDDEN_EVENT = "OnInterstitialHiddenEvent"
|
|
37
34
|
const val ON_INTERSTITIAL_AD_REVENUE_PAID = "OnInterstitialAdRevenuePaid"
|
|
38
35
|
|
|
36
|
+
// App Open Events
|
|
37
|
+
const val ON_APPOPEN_LOADED_EVENT = "OnAppOpenLoadedEvent"
|
|
38
|
+
const val ON_APPOPEN_LOAD_FAILED_EVENT = "OnAppOpenLoadFailedEvent"
|
|
39
|
+
const val ON_APPOPEN_CLICKED_EVENT = "OnAppOpenClickedEvent"
|
|
40
|
+
const val ON_APPOPEN_DISPLAYED_EVENT = "OnAppOpenDisplayedEvent"
|
|
41
|
+
const val ON_APPOPEN_DISPLAY_FAILED_EVENT = "OnAppOpenDisplayFailedEvent"
|
|
42
|
+
const val ON_APPOPEN_HIDDEN_EVENT = "OnAppOpenHiddenEvent"
|
|
43
|
+
const val ON_APPOPEN_AD_REVENUE_PAID = "OnAppOpenAdRevenuePaid"
|
|
44
|
+
|
|
39
45
|
// Rewarded Events
|
|
40
46
|
const val ON_REWARDED_AD_LOADED_EVENT = "OnRewardedAdLoadedEvent"
|
|
41
47
|
const val ON_REWARDED_AD_LOAD_FAILED_EVENT = "OnRewardedAdLoadFailedEvent"
|
|
@@ -39,3 +39,17 @@ fun getAdDisplayFailedInfo(ad: CloudXAd, error: CloudXError): WritableMap {
|
|
|
39
39
|
map.putString("message", error.message)
|
|
40
40
|
return map
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Synthetic display-failure payload for the no-current-activity show path.
|
|
45
|
+
* Mirrors the iOS no-view-controller payload ({adUnitId, code: -1, message})
|
|
46
|
+
* so JS can reset its isLoaded state instead of hanging on a show that
|
|
47
|
+
* silently never happened.
|
|
48
|
+
*/
|
|
49
|
+
fun getNoActivityDisplayFailedInfo(adUnitId: String): WritableMap {
|
|
50
|
+
val map = Arguments.createMap()
|
|
51
|
+
map.putString("adUnitId", adUnitId)
|
|
52
|
+
map.putInt("code", -1)
|
|
53
|
+
map.putString("message", "No activity available to show the ad from")
|
|
54
|
+
return map
|
|
55
|
+
}
|
|
@@ -28,11 +28,9 @@ class CloudXAdView(private val reactContext: ThemedReactContext) : FrameLayout(r
|
|
|
28
28
|
const val TAG = "CloudXAdView"
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* key instead. The value check keeps benign same-value re-renders quiet.
|
|
35
|
-
*/
|
|
31
|
+
// adUnitId / adFormat are immutable once the ad view is created. Changing
|
|
32
|
+
// them on a mounted view is ignored (with a warning) — remount via a React
|
|
33
|
+
// key instead. The value check keeps benign same-value re-renders quiet.
|
|
36
34
|
var adUnitId: String? = null
|
|
37
35
|
set(value) {
|
|
38
36
|
if (adView != null && value != field) {
|
|
@@ -80,7 +78,7 @@ class CloudXAdView(private val reactContext: ThemedReactContext) : FrameLayout(r
|
|
|
80
78
|
|
|
81
79
|
/*
|
|
82
80
|
* ReactViewGroup no-ops requestLayout, and getWidth()/getHeight() are 0 on
|
|
83
|
-
* attach
|
|
81
|
+
* attach — re-run measure/layout on the next frame so the hosted ad renders.
|
|
84
82
|
*/
|
|
85
83
|
override fun requestLayout() {
|
|
86
84
|
super.requestLayout()
|
|
@@ -130,10 +128,8 @@ class CloudXAdView(private val reactContext: ThemedReactContext) : FrameLayout(r
|
|
|
130
128
|
super.onDetachedFromWindow()
|
|
131
129
|
adView?.stopAutoRefresh()
|
|
132
130
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
* unmount removes it. Destroy only on a genuine unmount.
|
|
136
|
-
*/
|
|
131
|
+
// Defer one frame: a tab switch detaches but keeps the parent, a real
|
|
132
|
+
// unmount removes it. Destroy only on a genuine unmount.
|
|
137
133
|
post {
|
|
138
134
|
if (parent == null) {
|
|
139
135
|
destroyAdView()
|
|
@@ -143,7 +139,7 @@ class CloudXAdView(private val reactContext: ThemedReactContext) : FrameLayout(r
|
|
|
143
139
|
* unmount, so re-arm refresh. If the view is instead being
|
|
144
140
|
* dropped, CloudXAdViewManagerImpl.onDropViewInstance calls
|
|
145
141
|
* destroyAdView() first (nulling adView), so this stays a
|
|
146
|
-
* null-safe no-op
|
|
142
|
+
* null-safe no-op — refresh is never armed on a dead view.
|
|
147
143
|
*/
|
|
148
144
|
adView?.startAutoRefresh()
|
|
149
145
|
}
|
|
@@ -233,10 +229,8 @@ class CloudXAdView(private val reactContext: ThemedReactContext) : FrameLayout(r
|
|
|
233
229
|
private fun loadFailedPayload(failedAdUnitId: String, error: CloudXError): WritableMap {
|
|
234
230
|
val map = Arguments.createMap()
|
|
235
231
|
map.putString("adUnitId", failedAdUnitId)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
* to stay consistent with `revenue` and the iOS side).
|
|
239
|
-
*/
|
|
232
|
+
// Codegen spec declares `code` as Double; emit a double to match (and
|
|
233
|
+
// to stay consistent with `revenue` and the iOS side).
|
|
240
234
|
map.putDouble("code", error.code.code.toDouble())
|
|
241
235
|
map.putString("message", error.message)
|
|
242
236
|
return map
|
|
@@ -21,7 +21,7 @@ class CloudXAdViewEvent(
|
|
|
21
21
|
/*
|
|
22
22
|
* Ad-lifecycle events are discrete and must never be dropped. The default
|
|
23
23
|
* (true) lets the dispatcher coalesce events sharing the same
|
|
24
|
-
* (eventName, viewId) within a batch, keeping only the latest
|
|
24
|
+
* (eventName, viewId) within a batch, keeping only the latest — which would
|
|
25
25
|
* silently drop, e.g., back-to-back revenue events on the same view.
|
|
26
26
|
*/
|
|
27
27
|
override fun canCoalesce(): Boolean = false
|
|
@@ -26,13 +26,19 @@ import io.cloudx.sdk.CloudXAdViewListener
|
|
|
26
26
|
import io.cloudx.sdk.CloudXArbiterBid
|
|
27
27
|
import io.cloudx.sdk.CloudXArbiterConfiguration
|
|
28
28
|
import io.cloudx.sdk.CloudXArbiterListener
|
|
29
|
+
import io.cloudx.sdk.CloudXArbiterPrecision
|
|
29
30
|
import io.cloudx.sdk.CloudXArbiterResult
|
|
30
31
|
import io.cloudx.sdk.CloudXError
|
|
31
32
|
import io.cloudx.sdk.CloudXInitializationConfiguration
|
|
32
33
|
import io.cloudx.sdk.CloudXInitializationListener
|
|
34
|
+
import io.cloudx.sdk.CloudXAppOpenAd
|
|
35
|
+
import io.cloudx.sdk.CloudXAppOpenListener
|
|
33
36
|
import io.cloudx.sdk.CloudXInterstitialAd
|
|
34
37
|
import io.cloudx.sdk.CloudXInterstitialListener
|
|
35
38
|
import io.cloudx.sdk.CloudXLogLevel
|
|
39
|
+
import io.cloudx.sdk.CloudXRevenueData
|
|
40
|
+
import io.cloudx.sdk.CloudXRevenuePlatform
|
|
41
|
+
import io.cloudx.sdk.CloudXRevenuePrecision
|
|
36
42
|
import io.cloudx.sdk.CloudXReward
|
|
37
43
|
import io.cloudx.sdk.CloudXRewardedAd
|
|
38
44
|
import io.cloudx.sdk.CloudXRewardedListener
|
|
@@ -47,6 +53,7 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
private val interstitials = ConcurrentHashMap<String, CloudXInterstitialAd>()
|
|
56
|
+
private val appOpenAds = ConcurrentHashMap<String, CloudXAppOpenAd>()
|
|
50
57
|
private val rewardedAds = ConcurrentHashMap<String, CloudXRewardedAd>()
|
|
51
58
|
private val adViews = ConcurrentHashMap<String, SdkAdView>()
|
|
52
59
|
private val adViewAdFormats = ConcurrentHashMap<String, CloudXAdFormat>()
|
|
@@ -175,6 +182,11 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
175
182
|
|
|
176
183
|
fun arbiter(configuration: ReadableMap, promise: Promise) {
|
|
177
184
|
val bids = arbiterBids(configuration)
|
|
185
|
+
if (bids.isEmpty()) {
|
|
186
|
+
promise.resolve(emptyArbiterResult())
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
|
|
178
190
|
val arbiterConfiguration = CloudXArbiterConfiguration.builder(bids).build()
|
|
179
191
|
CloudX.arbiter(arbiterConfiguration, object : CloudXArbiterListener {
|
|
180
192
|
override fun onCompleted(result: CloudXArbiterResult) {
|
|
@@ -183,6 +195,15 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
183
195
|
})
|
|
184
196
|
}
|
|
185
197
|
|
|
198
|
+
fun reportRevenueData(data: ReadableMap, promise: Promise) {
|
|
199
|
+
val revenueData = data.toRevenueData()
|
|
200
|
+
if (revenueData == null) {
|
|
201
|
+
promise.resolve(false)
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
promise.resolve(CloudX.reportRevenueData(revenueData))
|
|
205
|
+
}
|
|
206
|
+
|
|
186
207
|
// =========================================================================
|
|
187
208
|
// Banner (Programmatic)
|
|
188
209
|
// =========================================================================
|
|
@@ -243,6 +264,10 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
243
264
|
val activity = maybeGetCurrentActivity()
|
|
244
265
|
if (activity == null) {
|
|
245
266
|
Log.e(TAG, "showInterstitial: no activity available")
|
|
267
|
+
sendReactNativeEvent(
|
|
268
|
+
CloudXAdEvents.ON_INTERSTITIAL_DISPLAY_FAILED_EVENT,
|
|
269
|
+
getNoActivityDisplayFailedInfo(adUnitId),
|
|
270
|
+
)
|
|
246
271
|
return@runOnUiQueueThread
|
|
247
272
|
}
|
|
248
273
|
interstitial.show(activity, placement, customData)
|
|
@@ -259,6 +284,50 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
259
284
|
}
|
|
260
285
|
}
|
|
261
286
|
|
|
287
|
+
// =========================================================================
|
|
288
|
+
// App Open
|
|
289
|
+
// =========================================================================
|
|
290
|
+
|
|
291
|
+
fun loadAppOpen(adUnitId: String) {
|
|
292
|
+
retrieveAppOpen(adUnitId).load()
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
fun setAppOpenExtraParameters(adUnitId: String, extraParameters: ReadableMap) {
|
|
296
|
+
CloudXExtraParameters.forEach(extraParameters) { key, value ->
|
|
297
|
+
retrieveAppOpen(adUnitId).setExtraParameter(key, value)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
fun isAppOpenReady(adUnitId: String, promise: Promise) {
|
|
302
|
+
promise.resolve(retrieveAppOpen(adUnitId).isAdReady)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
fun showAppOpen(adUnitId: String, placement: String?, customData: String?) {
|
|
306
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
307
|
+
val appOpen = retrieveAppOpen(adUnitId)
|
|
308
|
+
val activity = maybeGetCurrentActivity()
|
|
309
|
+
if (activity == null) {
|
|
310
|
+
Log.e(TAG, "showAppOpen: no activity available")
|
|
311
|
+
sendReactNativeEvent(
|
|
312
|
+
CloudXAdEvents.ON_APPOPEN_DISPLAY_FAILED_EVENT,
|
|
313
|
+
getNoActivityDisplayFailedInfo(adUnitId),
|
|
314
|
+
)
|
|
315
|
+
return@runOnUiQueueThread
|
|
316
|
+
}
|
|
317
|
+
appOpen.show(activity, placement, customData)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fun destroyAppOpen(adUnitId: String) {
|
|
322
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
323
|
+
appOpenAds.remove(adUnitId)?.let {
|
|
324
|
+
it.listener = null
|
|
325
|
+
it.revenueListener = null
|
|
326
|
+
it.destroy()
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
262
331
|
// =========================================================================
|
|
263
332
|
// Rewarded
|
|
264
333
|
// =========================================================================
|
|
@@ -283,6 +352,10 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
283
352
|
val activity = maybeGetCurrentActivity()
|
|
284
353
|
if (activity == null) {
|
|
285
354
|
Log.e(TAG, "showRewarded: no activity available")
|
|
355
|
+
sendReactNativeEvent(
|
|
356
|
+
CloudXAdEvents.ON_REWARDED_AD_DISPLAY_FAILED_EVENT,
|
|
357
|
+
getNoActivityDisplayFailedInfo(adUnitId),
|
|
358
|
+
)
|
|
286
359
|
return@runOnUiQueueThread
|
|
287
360
|
}
|
|
288
361
|
rewarded.show(activity, placement, customData)
|
|
@@ -372,6 +445,29 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
372
445
|
}
|
|
373
446
|
}
|
|
374
447
|
|
|
448
|
+
private fun createAppOpenListener(adUnitId: String): CloudXAppOpenListener {
|
|
449
|
+
return object : CloudXAppOpenListener {
|
|
450
|
+
override fun onAdLoaded(cloudXAd: CloudXAd) {
|
|
451
|
+
sendReactNativeEvent(CloudXAdEvents.ON_APPOPEN_LOADED_EVENT, getAdInfo(cloudXAd))
|
|
452
|
+
}
|
|
453
|
+
override fun onAdLoadFailed(failedAdUnitId: String, cloudXError: CloudXError) {
|
|
454
|
+
sendReactNativeEvent(CloudXAdEvents.ON_APPOPEN_LOAD_FAILED_EVENT, getAdLoadFailedInfo(failedAdUnitId, cloudXError))
|
|
455
|
+
}
|
|
456
|
+
override fun onAdClicked(cloudXAd: CloudXAd) {
|
|
457
|
+
sendReactNativeEvent(CloudXAdEvents.ON_APPOPEN_CLICKED_EVENT, getAdInfo(cloudXAd))
|
|
458
|
+
}
|
|
459
|
+
override fun onAdDisplayed(cloudXAd: CloudXAd) {
|
|
460
|
+
sendReactNativeEvent(CloudXAdEvents.ON_APPOPEN_DISPLAYED_EVENT, getAdInfo(cloudXAd))
|
|
461
|
+
}
|
|
462
|
+
override fun onAdDisplayFailed(cloudXAd: CloudXAd, cloudXError: CloudXError) {
|
|
463
|
+
sendReactNativeEvent(CloudXAdEvents.ON_APPOPEN_DISPLAY_FAILED_EVENT, getAdDisplayFailedInfo(cloudXAd, cloudXError))
|
|
464
|
+
}
|
|
465
|
+
override fun onAdHidden(cloudXAd: CloudXAd) {
|
|
466
|
+
sendReactNativeEvent(CloudXAdEvents.ON_APPOPEN_HIDDEN_EVENT, getAdInfo(cloudXAd))
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
375
471
|
private fun createRewardedListener(adUnitId: String): CloudXRewardedListener {
|
|
376
472
|
return object : CloudXRewardedListener {
|
|
377
473
|
override fun onAdLoaded(cloudXAd: CloudXAd) {
|
|
@@ -506,6 +602,7 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
506
602
|
"CLOUDX" -> cloudXArbiterBid(index)
|
|
507
603
|
"LEVELPLAY" -> levelPlayArbiterBid(index)
|
|
508
604
|
"PUBMATIC" -> pubMaticArbiterBid(index)
|
|
605
|
+
"CUSTOM" -> customArbiterBid(index)
|
|
509
606
|
else -> {
|
|
510
607
|
Log.w(TAG, "arbiter: ignoring bid with unsupported platform=$platform at index=$index")
|
|
511
608
|
null
|
|
@@ -572,10 +669,81 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
572
669
|
)
|
|
573
670
|
}
|
|
574
671
|
|
|
672
|
+
private fun ReadableMap.customArbiterBid(index: Int): CloudXArbiterBid? {
|
|
673
|
+
val platformName = stringValue("platformName")
|
|
674
|
+
val revenuePerImpressionUSD = doubleValue("revenuePerImpressionUSD")
|
|
675
|
+
val precision = stringValue("precision")
|
|
676
|
+
if (platformName.isNullOrBlank() || revenuePerImpressionUSD == null || precision.isNullOrBlank()) {
|
|
677
|
+
Log.w(TAG, "arbiter: ignoring CUSTOM bid with missing required fields at index=$index")
|
|
678
|
+
return null
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
return CloudXArbiterBid.custom(
|
|
682
|
+
platformName = platformName,
|
|
683
|
+
networkName = optionalStringValue("networkName").orEmpty(),
|
|
684
|
+
revenuePerImpressionUSD = revenuePerImpressionUSD,
|
|
685
|
+
precision = CloudXArbiterPrecision.of(precision),
|
|
686
|
+
extras = stringMapValue("extras"),
|
|
687
|
+
)
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
private fun ReadableMap.toRevenueData(): CloudXRevenueData? {
|
|
691
|
+
val platform = stringValue("platform")
|
|
692
|
+
val revenuePlatform = platform?.toRevenuePlatformOrNull()
|
|
693
|
+
val revenue = doubleValue("revenue")
|
|
694
|
+
val adFormat = stringValue("adFormat")
|
|
695
|
+
if (revenuePlatform == null || revenue == null || adFormat.isNullOrBlank()) {
|
|
696
|
+
Log.w(TAG, "reportRevenueData: ignoring data with missing or invalid required fields")
|
|
697
|
+
return null
|
|
698
|
+
}
|
|
699
|
+
if (!revenue.isFinite()) {
|
|
700
|
+
Log.w(TAG, "reportRevenueData: ignoring data with non-finite revenue=$revenue")
|
|
701
|
+
return null
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return CloudXRevenueData.builder(
|
|
705
|
+
revenuePlatform,
|
|
706
|
+
revenue,
|
|
707
|
+
adFormat,
|
|
708
|
+
)
|
|
709
|
+
.currencyCode(optionalStringValue("currencyCode"))
|
|
710
|
+
.precision(stringValue("precision")?.toRevenuePrecisionOrNull())
|
|
711
|
+
.networkName(optionalStringValue("networkName"))
|
|
712
|
+
.adUnitId(optionalStringValue("adUnitId"))
|
|
713
|
+
.thirdPartyAdPlacementId(optionalStringValue("thirdPartyAdPlacementId"))
|
|
714
|
+
.creativeId(optionalStringValue("creativeId"))
|
|
715
|
+
.networkPlacement(optionalStringValue("networkPlacement"))
|
|
716
|
+
.countryCode(optionalStringValue("countryCode"))
|
|
717
|
+
.userSegment(optionalStringValue("userSegment"))
|
|
718
|
+
.build()
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
private fun String.toRevenuePlatformOrNull(): CloudXRevenuePlatform? {
|
|
722
|
+
val platform = trim()
|
|
723
|
+
if (platform.isBlank()) return null
|
|
724
|
+
return when {
|
|
725
|
+
platform.equals("AdMob", ignoreCase = true) -> CloudXRevenuePlatform.ADMOB
|
|
726
|
+
platform.equals("InMobi", ignoreCase = true) -> CloudXRevenuePlatform.INMOBI
|
|
727
|
+
else -> CloudXRevenuePlatform.custom(platform)
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
private fun String.toRevenuePrecisionOrNull(): CloudXRevenuePrecision? = when (lowercase(Locale.ROOT)) {
|
|
732
|
+
"exact" -> CloudXRevenuePrecision.EXACT
|
|
733
|
+
"estimated" -> CloudXRevenuePrecision.ESTIMATED
|
|
734
|
+
"publisher_defined" -> CloudXRevenuePrecision.PUBLISHER_DEFINED
|
|
735
|
+
"undefined" -> CloudXRevenuePrecision.UNDEFINED
|
|
736
|
+
else -> {
|
|
737
|
+
Log.w(TAG, "reportRevenueData: ignoring unknown precision=$this")
|
|
738
|
+
null
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
575
742
|
private fun String.toCloudXAdFormatOrNull(): CloudXAdFormat? = when (uppercase(Locale.ROOT)) {
|
|
576
743
|
CloudXAdFormat.BANNER.name -> CloudXAdFormat.BANNER
|
|
577
744
|
CloudXAdFormat.MREC.name -> CloudXAdFormat.MREC
|
|
578
745
|
CloudXAdFormat.INTERSTITIAL.name -> CloudXAdFormat.INTERSTITIAL
|
|
746
|
+
CloudXAdFormat.APP_OPEN.name -> CloudXAdFormat.APP_OPEN
|
|
579
747
|
CloudXAdFormat.REWARDED.name -> CloudXAdFormat.REWARDED
|
|
580
748
|
CloudXAdFormat.NATIVE.name -> CloudXAdFormat.NATIVE
|
|
581
749
|
else -> null
|
|
@@ -606,10 +774,21 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
606
774
|
return result
|
|
607
775
|
}
|
|
608
776
|
|
|
777
|
+
private fun emptyArbiterResult(): WritableMap {
|
|
778
|
+
val map = Arguments.createMap()
|
|
779
|
+
map.putString("id", "")
|
|
780
|
+
map.putString("platform", "NONE")
|
|
781
|
+
map.putString("platformName", "NONE")
|
|
782
|
+
map.putNull("bidId")
|
|
783
|
+
map.putMap("extras", Arguments.createMap())
|
|
784
|
+
return map
|
|
785
|
+
}
|
|
786
|
+
|
|
609
787
|
private fun CloudXArbiterResult.toWritableMap(): WritableMap {
|
|
610
788
|
val map = Arguments.createMap()
|
|
611
789
|
map.putString("id", id)
|
|
612
790
|
map.putString("platform", platform.name)
|
|
791
|
+
map.putString("platformName", platformName)
|
|
613
792
|
map.putString("bidId", bidId)
|
|
614
793
|
map.putMap("extras", extras.toWritableMap())
|
|
615
794
|
return map
|
|
@@ -743,6 +922,17 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
743
922
|
return interstitial
|
|
744
923
|
}
|
|
745
924
|
|
|
925
|
+
private fun retrieveAppOpen(adUnitId: String): CloudXAppOpenAd {
|
|
926
|
+
var appOpen = appOpenAds[adUnitId]
|
|
927
|
+
if (appOpen == null) {
|
|
928
|
+
appOpen = CloudX.createAppOpen(reactApplicationContext, adUnitId)
|
|
929
|
+
appOpen.listener = createAppOpenListener(adUnitId)
|
|
930
|
+
appOpen.revenueListener = createFullscreenRevenueListener(adUnitId, CloudXAdEvents.ON_APPOPEN_AD_REVENUE_PAID)
|
|
931
|
+
appOpenAds[adUnitId] = appOpen
|
|
932
|
+
}
|
|
933
|
+
return appOpen
|
|
934
|
+
}
|
|
935
|
+
|
|
746
936
|
private fun retrieveRewarded(adUnitId: String): CloudXRewardedAd {
|
|
747
937
|
var rewarded = rewardedAds[adUnitId]
|
|
748
938
|
if (rewarded == null) {
|
|
@@ -885,6 +1075,11 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
885
1075
|
}
|
|
886
1076
|
interstitials.clear()
|
|
887
1077
|
|
|
1078
|
+
for (appOpen in appOpenAds.values) {
|
|
1079
|
+
appOpen.destroy()
|
|
1080
|
+
}
|
|
1081
|
+
appOpenAds.clear()
|
|
1082
|
+
|
|
888
1083
|
for (rewarded in rewardedAds.values) {
|
|
889
1084
|
rewarded.destroy()
|
|
890
1085
|
}
|
|
@@ -926,6 +1121,13 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
926
1121
|
"ON_INTERSTITIAL_DISPLAY_FAILED_EVENT" to CloudXAdEvents.ON_INTERSTITIAL_DISPLAY_FAILED_EVENT,
|
|
927
1122
|
"ON_INTERSTITIAL_HIDDEN_EVENT" to CloudXAdEvents.ON_INTERSTITIAL_HIDDEN_EVENT,
|
|
928
1123
|
"ON_INTERSTITIAL_AD_REVENUE_PAID" to CloudXAdEvents.ON_INTERSTITIAL_AD_REVENUE_PAID,
|
|
1124
|
+
"ON_APPOPEN_LOADED_EVENT" to CloudXAdEvents.ON_APPOPEN_LOADED_EVENT,
|
|
1125
|
+
"ON_APPOPEN_LOAD_FAILED_EVENT" to CloudXAdEvents.ON_APPOPEN_LOAD_FAILED_EVENT,
|
|
1126
|
+
"ON_APPOPEN_CLICKED_EVENT" to CloudXAdEvents.ON_APPOPEN_CLICKED_EVENT,
|
|
1127
|
+
"ON_APPOPEN_DISPLAYED_EVENT" to CloudXAdEvents.ON_APPOPEN_DISPLAYED_EVENT,
|
|
1128
|
+
"ON_APPOPEN_DISPLAY_FAILED_EVENT" to CloudXAdEvents.ON_APPOPEN_DISPLAY_FAILED_EVENT,
|
|
1129
|
+
"ON_APPOPEN_HIDDEN_EVENT" to CloudXAdEvents.ON_APPOPEN_HIDDEN_EVENT,
|
|
1130
|
+
"ON_APPOPEN_AD_REVENUE_PAID" to CloudXAdEvents.ON_APPOPEN_AD_REVENUE_PAID,
|
|
929
1131
|
"ON_REWARDED_AD_LOADED_EVENT" to CloudXAdEvents.ON_REWARDED_AD_LOADED_EVENT,
|
|
930
1132
|
"ON_REWARDED_AD_LOAD_FAILED_EVENT" to CloudXAdEvents.ON_REWARDED_AD_LOAD_FAILED_EVENT,
|
|
931
1133
|
"ON_REWARDED_AD_CLICKED_EVENT" to CloudXAdEvents.ON_REWARDED_AD_CLICKED_EVENT,
|
|
@@ -31,6 +31,7 @@ class CloudXModule(reactContext: ReactApplicationContext) :
|
|
|
31
31
|
@ReactMethod override fun setHasUserConsent(hasUserConsent: Boolean?) = impl.setHasUserConsent(hasUserConsent)
|
|
32
32
|
@ReactMethod override fun setDoNotSell(isDoNotSell: Boolean?) = impl.setDoNotSell(isDoNotSell)
|
|
33
33
|
@ReactMethod override fun arbiter(configuration: ReadableMap, promise: Promise) = impl.arbiter(configuration, promise)
|
|
34
|
+
@ReactMethod override fun reportRevenueData(data: ReadableMap, promise: Promise) = impl.reportRevenueData(data, promise)
|
|
34
35
|
|
|
35
36
|
@ReactMethod override fun createBanner(adUnitId: String, position: String) = impl.createBanner(adUnitId, position)
|
|
36
37
|
@ReactMethod override fun createBannerWithOffsets(adUnitId: String, position: String, xOffset: Double, yOffset: Double) = impl.createBannerWithOffsets(adUnitId, position, xOffset, yOffset)
|
|
@@ -66,6 +67,12 @@ class CloudXModule(reactContext: ReactApplicationContext) :
|
|
|
66
67
|
@ReactMethod override fun showInterstitial(adUnitId: String, placement: String?, customData: String?) = impl.showInterstitial(adUnitId, placement, customData)
|
|
67
68
|
@ReactMethod override fun destroyInterstitial(adUnitId: String) = impl.destroyInterstitial(adUnitId)
|
|
68
69
|
|
|
70
|
+
@ReactMethod override fun loadAppOpen(adUnitId: String) = impl.loadAppOpen(adUnitId)
|
|
71
|
+
@ReactMethod override fun setAppOpenExtraParameters(adUnitId: String, extraParameters: ReadableMap) = impl.setAppOpenExtraParameters(adUnitId, extraParameters)
|
|
72
|
+
@ReactMethod override fun isAppOpenReady(adUnitId: String, promise: Promise) = impl.isAppOpenReady(adUnitId, promise)
|
|
73
|
+
@ReactMethod override fun showAppOpen(adUnitId: String, placement: String?, customData: String?) = impl.showAppOpen(adUnitId, placement, customData)
|
|
74
|
+
@ReactMethod override fun destroyAppOpen(adUnitId: String) = impl.destroyAppOpen(adUnitId)
|
|
75
|
+
|
|
69
76
|
@ReactMethod override fun loadRewarded(adUnitId: String) = impl.loadRewarded(adUnitId)
|
|
70
77
|
@ReactMethod override fun setRewardedExtraParameters(adUnitId: String, extraParameters: ReadableMap) = impl.setRewardedExtraParameters(adUnitId, extraParameters)
|
|
71
78
|
@ReactMethod override fun isRewardedReady(adUnitId: String, promise: Promise) = impl.isRewardedReady(adUnitId, promise)
|
|
@@ -46,6 +46,7 @@ class CloudXModule(reactContext: ReactApplicationContext) :
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
@ReactMethod fun arbiter(configuration: ReadableMap, promise: Promise) = impl.arbiter(configuration, promise)
|
|
49
|
+
@ReactMethod fun reportRevenueData(data: ReadableMap, promise: Promise) = impl.reportRevenueData(data, promise)
|
|
49
50
|
|
|
50
51
|
@ReactMethod fun createBanner(adUnitId: String, position: String) = impl.createBanner(adUnitId, position)
|
|
51
52
|
@ReactMethod fun createBannerWithOffsets(adUnitId: String, position: String, xOffset: Double, yOffset: Double) = impl.createBannerWithOffsets(adUnitId, position, xOffset, yOffset)
|
|
@@ -81,6 +82,12 @@ class CloudXModule(reactContext: ReactApplicationContext) :
|
|
|
81
82
|
@ReactMethod fun showInterstitial(adUnitId: String, placement: String?, customData: String?) = impl.showInterstitial(adUnitId, placement, customData)
|
|
82
83
|
@ReactMethod fun destroyInterstitial(adUnitId: String) = impl.destroyInterstitial(adUnitId)
|
|
83
84
|
|
|
85
|
+
@ReactMethod fun loadAppOpen(adUnitId: String) = impl.loadAppOpen(adUnitId)
|
|
86
|
+
@ReactMethod fun setAppOpenExtraParameters(adUnitId: String, extraParameters: ReadableMap) = impl.setAppOpenExtraParameters(adUnitId, extraParameters)
|
|
87
|
+
@ReactMethod fun isAppOpenReady(adUnitId: String, promise: Promise) = impl.isAppOpenReady(adUnitId, promise)
|
|
88
|
+
@ReactMethod fun showAppOpen(adUnitId: String, placement: String?, customData: String?) = impl.showAppOpen(adUnitId, placement, customData)
|
|
89
|
+
@ReactMethod fun destroyAppOpen(adUnitId: String) = impl.destroyAppOpen(adUnitId)
|
|
90
|
+
|
|
84
91
|
@ReactMethod fun loadRewarded(adUnitId: String) = impl.loadRewarded(adUnitId)
|
|
85
92
|
@ReactMethod fun setRewardedExtraParameters(adUnitId: String, extraParameters: ReadableMap) = impl.setRewardedExtraParameters(adUnitId, extraParameters)
|
|
86
93
|
@ReactMethod fun isRewardedReady(adUnitId: String, promise: Promise) = impl.isRewardedReady(adUnitId, promise)
|
|
@@ -6,15 +6,15 @@ Pod::Spec.new do |s|
|
|
|
6
6
|
s.name = "cloudx-react-native"
|
|
7
7
|
s.version = package["version"]
|
|
8
8
|
s.summary = package["description"]
|
|
9
|
-
s.homepage = "https://github.com/cloudx-io/
|
|
9
|
+
s.homepage = "https://github.com/cloudx-io/mobile/tree/main/react-native"
|
|
10
10
|
s.license = package["license"]
|
|
11
11
|
s.authors = { "CloudX" => "support@cloudx.io" }
|
|
12
12
|
s.platforms = { :ios => "13.0" }
|
|
13
|
-
s.source = { :git => "https://github.com/cloudx-io/
|
|
13
|
+
s.source = { :git => "https://github.com/cloudx-io/mobile.git", :tag => "react-native/sdk/#{s.version}" }
|
|
14
14
|
|
|
15
15
|
s.requires_arc = true
|
|
16
16
|
|
|
17
|
-
s.dependency "CloudXCore", "~> 3.
|
|
17
|
+
s.dependency "CloudXCore", "~> 3.6.0"
|
|
18
18
|
|
|
19
19
|
s.source_files = "ios/**/*.{h,mm}"
|
|
20
20
|
|
package/ios/CloudX.h
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
13
13
|
#import <CloudXSpec/CloudXSpec.h>
|
|
14
|
-
@interface CloudX : RCTEventEmitter<NativeCloudXSpec, CLXInterstitialDelegate, CLXRewardedDelegate, CLXBannerDelegate, CLXAdRevenueDelegate>
|
|
14
|
+
@interface CloudX : RCTEventEmitter<NativeCloudXSpec, CLXInterstitialDelegate, CLXAppOpenDelegate, CLXRewardedDelegate, CLXBannerDelegate, CLXAdRevenueDelegate>
|
|
15
15
|
#else
|
|
16
16
|
#import <React/RCTBridgeModule.h>
|
|
17
|
-
@interface CloudX : RCTEventEmitter<RCTBridgeModule, CLXInterstitialDelegate, CLXRewardedDelegate, CLXBannerDelegate, CLXAdRevenueDelegate>
|
|
17
|
+
@interface CloudX : RCTEventEmitter<RCTBridgeModule, CLXInterstitialDelegate, CLXAppOpenDelegate, CLXRewardedDelegate, CLXBannerDelegate, CLXAdRevenueDelegate>
|
|
18
18
|
#endif
|
|
19
19
|
|
|
20
20
|
NS_ASSUME_NONNULL_BEGIN
|