cloudx-react-native 3.1.2 → 3.2.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 +20 -17
- package/android/build.gradle +1 -2
- package/android/src/main/java/com/cloudxreactnative/CloudXModuleImpl.kt +37 -27
- package/android/src/oldarch/com/cloudxreactnative/CloudXModule.kt +18 -2
- package/cloudx-react-native.podspec +1 -1
- package/ios/CloudX.mm +106 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ The CloudX React Native SDK enables monetization of your React Native apps with
|
|
|
19
19
|
|
|
20
20
|
| Plugin | iOS (`CloudXCore`) | Android (`io.cloudx:sdk`) |
|
|
21
21
|
|--------|-------------------|---------------------------|
|
|
22
|
+
| 3.2.0 | 3.2.0 | 3.2.0 |
|
|
22
23
|
| 3.1.2 | 3.1.0 | 3.1.0 |
|
|
23
24
|
| 2.2.3 | 2.2.3 | 2.2.3 |
|
|
24
25
|
|
|
@@ -39,12 +40,13 @@ target 'YourApp' do
|
|
|
39
40
|
# ... existing config ...
|
|
40
41
|
|
|
41
42
|
# CloudX ad network adapters (add as needed)
|
|
42
|
-
pod 'CloudXMetaAdapter', '~> 3.
|
|
43
|
-
pod 'CloudXVungleAdapter', '~> 3.
|
|
44
|
-
pod 'CloudXInMobiAdapter', '~> 3.
|
|
45
|
-
pod 'CloudXMintegralAdapter', '~> 3.
|
|
46
|
-
pod 'CloudXUnityAdsAdapter', '~> 3.
|
|
47
|
-
pod '
|
|
43
|
+
pod 'CloudXMetaAdapter', '~> 3.2.0'
|
|
44
|
+
pod 'CloudXVungleAdapter', '~> 3.2.0'
|
|
45
|
+
pod 'CloudXInMobiAdapter', '~> 3.2.0'
|
|
46
|
+
pod 'CloudXMintegralAdapter', '~> 3.2.0'
|
|
47
|
+
pod 'CloudXUnityAdsAdapter', '~> 3.2.0'
|
|
48
|
+
pod 'CloudXMagniteAdapter', '~> 3.2.0'
|
|
49
|
+
pod 'CloudXRenderer', '~> 3.2.0'
|
|
48
50
|
end
|
|
49
51
|
```
|
|
50
52
|
|
|
@@ -75,16 +77,17 @@ Add CloudX SDK and adapter dependencies to your `android/app/build.gradle`:
|
|
|
75
77
|
```kotlin
|
|
76
78
|
dependencies {
|
|
77
79
|
// CloudX Android SDK
|
|
78
|
-
implementation "io.cloudx:sdk:3.
|
|
80
|
+
implementation "io.cloudx:sdk:3.2.0"
|
|
79
81
|
|
|
80
82
|
// Adapters for ad networks (add as needed)
|
|
81
|
-
implementation "io.cloudx:adapter-meta:3.
|
|
82
|
-
implementation "io.cloudx:adapter-vungle:3.
|
|
83
|
-
implementation "io.cloudx:adapter-inmobi:3.
|
|
84
|
-
implementation "io.cloudx:adapter-mintegral:3.
|
|
85
|
-
implementation "io.cloudx:adapter-unityads:3.
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
implementation "io.cloudx:adapter-meta:3.2.0"
|
|
84
|
+
implementation "io.cloudx:adapter-vungle:3.2.0"
|
|
85
|
+
implementation "io.cloudx:adapter-inmobi:3.2.0"
|
|
86
|
+
implementation "io.cloudx:adapter-mintegral:3.2.0"
|
|
87
|
+
implementation "io.cloudx:adapter-unityads:3.2.0"
|
|
88
|
+
implementation "io.cloudx:adapter-magnite:3.2.0"
|
|
89
|
+
|
|
90
|
+
// Required by the native SDK 3.2.0 when using the Meta adapter.
|
|
88
91
|
implementation "com.facebook.android:audience-network-sdk:6.21.0"
|
|
89
92
|
}
|
|
90
93
|
```
|
|
@@ -637,12 +640,12 @@ CloudX.setVisualDebuggingEnabled(true);
|
|
|
637
640
|
- Xcode 14.0+ / CocoaPods (iOS)
|
|
638
641
|
- Gradle 8.0+ / Kotlin 1.8+ (Android)
|
|
639
642
|
|
|
640
|
-
### Native SDK Versions (3.
|
|
643
|
+
### Native SDK Versions (3.2.0)
|
|
641
644
|
|
|
642
645
|
| Platform | Dependency | Version |
|
|
643
646
|
|----------|-----------|---------|
|
|
644
|
-
| iOS | CloudXCore | ~> 3.
|
|
645
|
-
| Android | io.cloudx:sdk | 3.
|
|
647
|
+
| iOS | CloudXCore | ~> 3.2.0 |
|
|
648
|
+
| Android | io.cloudx:sdk | 3.2.0 |
|
|
646
649
|
|
|
647
650
|
## Troubleshooting
|
|
648
651
|
|
package/android/build.gradle
CHANGED
|
@@ -65,7 +65,6 @@ android {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
repositories {
|
|
68
|
-
mavenLocal()
|
|
69
68
|
mavenCentral()
|
|
70
69
|
google()
|
|
71
70
|
}
|
|
@@ -73,5 +72,5 @@ repositories {
|
|
|
73
72
|
dependencies {
|
|
74
73
|
implementation "com.facebook.react:react-native:0.76.2"
|
|
75
74
|
|
|
76
|
-
implementation "io.cloudx:sdk:3.
|
|
75
|
+
implementation "io.cloudx:sdk:3.2.0"
|
|
77
76
|
}
|
|
@@ -208,20 +208,24 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
fun showInterstitial(adUnitId: String, placement: String?, customData: String?) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
212
|
+
val interstitial = retrieveInterstitial(adUnitId)
|
|
213
|
+
val activity = maybeGetCurrentActivity()
|
|
214
|
+
if (activity == null) {
|
|
215
|
+
Log.e(TAG, "showInterstitial: no activity available")
|
|
216
|
+
return@runOnUiQueueThread
|
|
217
|
+
}
|
|
218
|
+
interstitial.show(activity, placement, customData)
|
|
216
219
|
}
|
|
217
|
-
interstitial.show(activity, placement, customData)
|
|
218
220
|
}
|
|
219
221
|
|
|
220
222
|
fun destroyInterstitial(adUnitId: String) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
224
|
+
interstitials.remove(adUnitId)?.let {
|
|
225
|
+
it.listener = null
|
|
226
|
+
it.revenueListener = null
|
|
227
|
+
it.destroy()
|
|
228
|
+
}
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
231
|
|
|
@@ -238,20 +242,24 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
238
242
|
}
|
|
239
243
|
|
|
240
244
|
fun showRewarded(adUnitId: String, placement: String?, customData: String?) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
245
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
246
|
+
val rewarded = retrieveRewarded(adUnitId)
|
|
247
|
+
val activity = maybeGetCurrentActivity()
|
|
248
|
+
if (activity == null) {
|
|
249
|
+
Log.e(TAG, "showRewarded: no activity available")
|
|
250
|
+
return@runOnUiQueueThread
|
|
251
|
+
}
|
|
252
|
+
rewarded.show(activity, placement, customData)
|
|
246
253
|
}
|
|
247
|
-
rewarded.show(activity, placement, customData)
|
|
248
254
|
}
|
|
249
255
|
|
|
250
256
|
fun destroyRewarded(adUnitId: String) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
257
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
258
|
+
rewardedAds.remove(adUnitId)?.let {
|
|
259
|
+
it.listener = null
|
|
260
|
+
it.revenueListener = null
|
|
261
|
+
it.destroy()
|
|
262
|
+
}
|
|
255
263
|
}
|
|
256
264
|
}
|
|
257
265
|
|
|
@@ -661,15 +669,17 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
|
|
|
661
669
|
destroyAdView(adUnitId, adFormat)
|
|
662
670
|
}
|
|
663
671
|
|
|
664
|
-
|
|
665
|
-
interstitial.
|
|
666
|
-
|
|
667
|
-
|
|
672
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
673
|
+
for (interstitial in interstitials.values) {
|
|
674
|
+
interstitial.destroy()
|
|
675
|
+
}
|
|
676
|
+
interstitials.clear()
|
|
668
677
|
|
|
669
|
-
|
|
670
|
-
|
|
678
|
+
for (rewarded in rewardedAds.values) {
|
|
679
|
+
rewarded.destroy()
|
|
680
|
+
}
|
|
681
|
+
rewardedAds.clear()
|
|
671
682
|
}
|
|
672
|
-
rewardedAds.clear()
|
|
673
683
|
}
|
|
674
684
|
|
|
675
685
|
// =========================================================================
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.cloudxreactnative
|
|
2
2
|
|
|
3
|
+
import com.facebook.react.bridge.Dynamic
|
|
3
4
|
import com.facebook.react.bridge.Promise
|
|
4
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
6
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
@@ -25,8 +26,23 @@ class CloudXModule(reactContext: ReactApplicationContext) :
|
|
|
25
26
|
@ReactMethod fun setAppKeyValue(key: String, value: String) = impl.setAppKeyValue(key, value)
|
|
26
27
|
@ReactMethod fun clearAllKeyValues() = impl.clearAllKeyValues()
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
// Paper's `JavaMethodWrapper` extracts primitive boxed types via
|
|
30
|
+
// `ReadableNativeArray.getBoolean(int)` which unconditionally calls
|
|
31
|
+
// `booleanValue()` on the boxed result — null arguments therefore throw
|
|
32
|
+
// `NativeArgumentsParseException` *before* the method runs, even when the
|
|
33
|
+
// Kotlin signature is `Boolean?`. Declaring the parameter as `Dynamic`
|
|
34
|
+
// lets the bridge hand us the raw value and we null-check it ourselves.
|
|
35
|
+
// TurboModules (NewArch) don't have this limitation, which is why the
|
|
36
|
+
// newarch counterpart keeps the `Boolean?` signature directly.
|
|
37
|
+
@ReactMethod fun setHasUserConsent(hasUserConsent: Dynamic) {
|
|
38
|
+
val value: Boolean? = if (hasUserConsent.isNull) null else hasUserConsent.asBoolean()
|
|
39
|
+
impl.setHasUserConsent(value)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@ReactMethod fun setDoNotSell(isDoNotSell: Dynamic) {
|
|
43
|
+
val value: Boolean? = if (isDoNotSell.isNull) null else isDoNotSell.asBoolean()
|
|
44
|
+
impl.setDoNotSell(value)
|
|
45
|
+
}
|
|
30
46
|
|
|
31
47
|
@ReactMethod fun createBanner(adUnitId: String, position: String) = impl.createBanner(adUnitId, position)
|
|
32
48
|
@ReactMethod fun createBannerWithOffsets(adUnitId: String, position: String, xOffset: Double, yOffset: Double) = impl.createBannerWithOffsets(adUnitId, position, xOffset, yOffset)
|
package/ios/CloudX.mm
CHANGED
|
@@ -11,6 +11,42 @@
|
|
|
11
11
|
+ (nullable UIColor *)clx_colorWithHexString:(NSString *)hexString;
|
|
12
12
|
@end
|
|
13
13
|
|
|
14
|
+
// Diagnostic-only observer. Inserted as a zero-size hidden subview of the
|
|
15
|
+
// CLXBannerAdView so we can detect when the banner's window attachment changes.
|
|
16
|
+
// A subview's window follows its superview's, so window transitions on the
|
|
17
|
+
// observer are a reliable proxy for transitions on the banner itself.
|
|
18
|
+
// TODO(CXD-banner-diag): remove once the iOS RN banner visibility issue is
|
|
19
|
+
// root-caused and fixed.
|
|
20
|
+
@interface CLXDiagBannerWindowObserver : UIView
|
|
21
|
+
@property (nonatomic, copy, nullable) NSString *adUnitIdentifier;
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
@implementation CLXDiagBannerWindowObserver
|
|
25
|
+
|
|
26
|
+
- (instancetype)initWithAdUnitIdentifier:(NSString *)adUnitIdentifier
|
|
27
|
+
{
|
|
28
|
+
self = [super initWithFrame: CGRectZero];
|
|
29
|
+
if (self) {
|
|
30
|
+
_adUnitIdentifier = [adUnitIdentifier copy];
|
|
31
|
+
self.hidden = YES;
|
|
32
|
+
self.userInteractionEnabled = NO;
|
|
33
|
+
self.translatesAutoresizingMaskIntoConstraints = YES;
|
|
34
|
+
}
|
|
35
|
+
return self;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (void)didMoveToWindow
|
|
39
|
+
{
|
|
40
|
+
[super didMoveToWindow];
|
|
41
|
+
NSLog(@"[CloudXCore] [CloudX] DIAG banner[%@] didMoveToWindow: window=%@ superview=%@ superview.window=%@",
|
|
42
|
+
self.adUnitIdentifier ?: @"(nil)",
|
|
43
|
+
self.window,
|
|
44
|
+
self.superview ? NSStringFromClass([self.superview class]) : @"(nil)",
|
|
45
|
+
self.superview ? self.superview.window : @"(nil)");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@end
|
|
49
|
+
|
|
14
50
|
@interface CloudX()
|
|
15
51
|
|
|
16
52
|
// A simple BOOL tracks initialization state. Concurrent initialize calls are serialized
|
|
@@ -840,14 +876,22 @@ RCT_EXPORT_METHOD(destroyRewarded:(NSString *)adUnitIdentifier)
|
|
|
840
876
|
// on window attachment" path inserts the adapter view immediately.
|
|
841
877
|
if ( !view.superview )
|
|
842
878
|
{
|
|
879
|
+
// TODO(CXD-banner-diag): remove once the iOS RN banner visibility
|
|
880
|
+
// issue is root-caused and fixed.
|
|
881
|
+
[self logBannerAttachDiagnosticsForAdUnit: adUnitIdentifier phase: @"pre-attach" view: view];
|
|
882
|
+
|
|
843
883
|
UIView *rootView = [self topViewController].view;
|
|
844
884
|
if ( rootView )
|
|
845
885
|
{
|
|
846
886
|
[rootView addSubview: view];
|
|
887
|
+
[self attachDiagObserverToBanner: view adUnit: adUnitIdentifier];
|
|
888
|
+
[self logBannerAttachDiagnosticsForAdUnit: adUnitIdentifier phase: @"post-attach" view: view];
|
|
889
|
+
[self scheduleBannerAttachFollowupsForAdUnit: adUnitIdentifier view: view];
|
|
847
890
|
}
|
|
848
891
|
else
|
|
849
892
|
{
|
|
850
893
|
[self log: @"showAdView: no visible root view for ad unit \"%@\"; deferring.", adUnitIdentifier];
|
|
894
|
+
[self logBannerAttachDiagnosticsForAdUnit: adUnitIdentifier phase: @"no-root-view" view: view];
|
|
851
895
|
[self.adUnitIdentifiersToShowAfterCreate addObject: adUnitIdentifier];
|
|
852
896
|
return;
|
|
853
897
|
}
|
|
@@ -862,6 +906,68 @@ RCT_EXPORT_METHOD(destroyRewarded:(NSString *)adUnitIdentifier)
|
|
|
862
906
|
}];
|
|
863
907
|
}
|
|
864
908
|
|
|
909
|
+
// TODO(CXD-banner-diag): remove once the iOS RN banner visibility issue is
|
|
910
|
+
// root-caused and fixed.
|
|
911
|
+
- (void)logBannerAttachDiagnosticsForAdUnit:(NSString *)adUnitIdentifier
|
|
912
|
+
phase:(NSString *)phase
|
|
913
|
+
view:(CLXBannerAdView *)view
|
|
914
|
+
{
|
|
915
|
+
UIViewController *topVC = [self topViewController];
|
|
916
|
+
UIViewController *rootVC = [self keyWindowRootViewController];
|
|
917
|
+
NSUInteger connectedSceneCount = UIApplication.sharedApplication.connectedScenes.count;
|
|
918
|
+
NSUInteger foregroundSceneCount = 0;
|
|
919
|
+
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
|
|
920
|
+
if (scene.activationState == UISceneActivationStateForegroundActive) foregroundSceneCount++;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
NSLog(@"[CloudXCore] [CloudX] DIAG banner[%@] %@: "
|
|
924
|
+
@"view.window=%@ view.superview=%@ view.hidden=%d "
|
|
925
|
+
@"topVC=%@ topVC.view.window=%@ "
|
|
926
|
+
@"rootVC=%@ rootVC.view.window=%@ "
|
|
927
|
+
@"scenes=total:%lu foregroundActive:%lu",
|
|
928
|
+
adUnitIdentifier,
|
|
929
|
+
phase,
|
|
930
|
+
view.window,
|
|
931
|
+
view.superview ? NSStringFromClass([view.superview class]) : @"(nil)",
|
|
932
|
+
view.hidden,
|
|
933
|
+
topVC ? NSStringFromClass([topVC class]) : @"(nil)",
|
|
934
|
+
topVC.view.window,
|
|
935
|
+
rootVC ? NSStringFromClass([rootVC class]) : @"(nil)",
|
|
936
|
+
rootVC.view.window,
|
|
937
|
+
(unsigned long)connectedSceneCount,
|
|
938
|
+
(unsigned long)foregroundSceneCount);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// TODO(CXD-banner-diag): remove once root-caused.
|
|
942
|
+
- (void)scheduleBannerAttachFollowupsForAdUnit:(NSString *)adUnitIdentifier
|
|
943
|
+
view:(CLXBannerAdView *)view
|
|
944
|
+
{
|
|
945
|
+
__weak CloudX *weakSelf = self;
|
|
946
|
+
__weak CLXBannerAdView *weakView = view;
|
|
947
|
+
NSArray<NSNumber *> *delaysSeconds = @[ @0.25, @1.0, @3.0, @10.0 ];
|
|
948
|
+
for (NSNumber *delay in delaysSeconds) {
|
|
949
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay.doubleValue * NSEC_PER_SEC)),
|
|
950
|
+
dispatch_get_main_queue(), ^{
|
|
951
|
+
CloudX *strongSelf = weakSelf;
|
|
952
|
+
CLXBannerAdView *strongView = weakView;
|
|
953
|
+
if (!strongSelf || !strongView) return;
|
|
954
|
+
NSString *phase = [NSString stringWithFormat: @"post-attach+%@s", delay];
|
|
955
|
+
[strongSelf logBannerAttachDiagnosticsForAdUnit: adUnitIdentifier phase: phase view: strongView];
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// TODO(CXD-banner-diag): remove once root-caused.
|
|
961
|
+
- (void)attachDiagObserverToBanner:(CLXBannerAdView *)view
|
|
962
|
+
adUnit:(NSString *)adUnitIdentifier
|
|
963
|
+
{
|
|
964
|
+
for (UIView *subview in view.subviews) {
|
|
965
|
+
if ([subview isKindOfClass: [CLXDiagBannerWindowObserver class]]) return;
|
|
966
|
+
}
|
|
967
|
+
CLXDiagBannerWindowObserver *observer = [[CLXDiagBannerWindowObserver alloc] initWithAdUnitIdentifier: adUnitIdentifier];
|
|
968
|
+
[view addSubview: observer];
|
|
969
|
+
}
|
|
970
|
+
|
|
865
971
|
- (void)hideAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
866
972
|
{
|
|
867
973
|
[self executeOnMainQueue:^{
|
package/lib/commonjs/version.js
CHANGED
|
@@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.PLUGIN_VERSION = void 0;
|
|
7
7
|
// Keep PLUGIN_VERSION in sync with the `version` field in package.json.
|
|
8
8
|
// Phase 1 of RELEASE.md bumps both together.
|
|
9
|
-
const PLUGIN_VERSION = exports.PLUGIN_VERSION = '3.
|
|
9
|
+
const PLUGIN_VERSION = exports.PLUGIN_VERSION = '3.2.0';
|
|
10
10
|
//# sourceMappingURL=version.js.map
|
package/lib/module/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PLUGIN_VERSION = "3.
|
|
1
|
+
export declare const PLUGIN_VERSION = "3.2.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
package/src/version.ts
CHANGED