react-native-applovin-max 4.1.6 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -12
- package/android/gradle.properties +0 -1
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdView.java +85 -23
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdViewManager.java +39 -11
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXModule.java +712 -229
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXNativeAdView.java +107 -39
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXNativeAdViewManager.java +17 -7
- package/ios/AppLovinMAX.h +22 -2
- package/ios/AppLovinMAX.m +587 -187
- package/ios/AppLovinMAXAdView.m +43 -12
- package/ios/AppLovinMAXAdViewManager.m +10 -0
- package/ios/AppLovinMAXNativeAdView.m +86 -41
- package/ios/AppLovinMAXNativeAdViewManager.m +7 -3
- package/package.json +1 -1
- package/react-native-applovin-max.podspec +1 -1
- package/src/AppLovinMAXAdView.js +163 -62
- package/src/AppLovinMAXEventListeners.js +419 -0
- package/src/NativeAdComponents.js +39 -46
- package/src/NativeAdView.js +79 -34
- package/src/TargetingData.js +35 -3
- package/src/index.js +115 -336
package/ios/AppLovinMAXAdView.m
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
#import "AppLovinMAX.h"
|
|
10
10
|
#import "AppLovinMAXAdView.h"
|
|
11
11
|
|
|
12
|
-
@interface AppLovinMAXAdView()<MAAdViewAdDelegate>
|
|
12
|
+
@interface AppLovinMAXAdView()<MAAdViewAdDelegate, MAAdRevenueDelegate>
|
|
13
13
|
|
|
14
14
|
@property (nonatomic, strong, nullable) MAAdView *adView; // nil when unmounted
|
|
15
15
|
|
|
@@ -20,6 +20,16 @@
|
|
|
20
20
|
@property (nonatomic, copy, nullable) NSString *customData;
|
|
21
21
|
@property (nonatomic, assign, readonly, getter=isAdaptiveBannerEnabled) BOOL adaptiveBannerEnabled;
|
|
22
22
|
@property (nonatomic, assign, readonly, getter=isAutoRefresh) BOOL autoRefresh;
|
|
23
|
+
@property (nonatomic, copy, nullable) NSDictionary *extraParameters;
|
|
24
|
+
@property (nonatomic, copy, nullable) NSDictionary *localExtraParameters;
|
|
25
|
+
|
|
26
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdLoadedEvent;
|
|
27
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdLoadFailedEvent;
|
|
28
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdDisplayFailedEvent;
|
|
29
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdClickedEvent;
|
|
30
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdExpandedEvent;
|
|
31
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdCollapsedEvent;
|
|
32
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdRevenuePaidEvent;
|
|
23
33
|
|
|
24
34
|
@end
|
|
25
35
|
|
|
@@ -48,11 +58,11 @@
|
|
|
48
58
|
return;
|
|
49
59
|
}
|
|
50
60
|
|
|
51
|
-
if ( [
|
|
61
|
+
if ( [MAAdFormat.banner.label isEqualToString: adFormat] )
|
|
52
62
|
{
|
|
53
63
|
_adFormat = DEVICE_SPECIFIC_ADVIEW_AD_FORMAT;
|
|
54
64
|
}
|
|
55
|
-
else if ( [
|
|
65
|
+
else if ( [MAAdFormat.mrec.label isEqualToString: adFormat] )
|
|
56
66
|
{
|
|
57
67
|
_adFormat = MAAdFormat.mrec;
|
|
58
68
|
}
|
|
@@ -121,6 +131,12 @@
|
|
|
121
131
|
// Run after 0.25 sec delay to allow all properties to set
|
|
122
132
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
123
133
|
|
|
134
|
+
if ( ![AppLovinMAX shared].sdk )
|
|
135
|
+
{
|
|
136
|
+
[[AppLovinMAX shared] logUninitializedAccessError: @"AppLovinMAXAdview.attachAdViewIfNeeded"];
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
124
140
|
if ( ![adUnitId al_isValidString] )
|
|
125
141
|
{
|
|
126
142
|
[[AppLovinMAX shared] log: @"Attempting to attach MAAdView without Ad Unit ID"];
|
|
@@ -146,13 +162,23 @@
|
|
|
146
162
|
sdk: [AppLovinMAX shared].sdk];
|
|
147
163
|
self.adView.frame = (CGRect) { CGPointZero, self.frame.size };
|
|
148
164
|
self.adView.delegate = self;
|
|
149
|
-
self.adView.revenueDelegate =
|
|
165
|
+
self.adView.revenueDelegate = self;
|
|
150
166
|
self.adView.placement = self.placement;
|
|
151
167
|
self.adView.customData = self.customData;
|
|
152
168
|
[self.adView setExtraParameterForKey: @"adaptive_banner" value: [self isAdaptiveBannerEnabled] ? @"true" : @"false"];
|
|
153
169
|
// Set this extra parameter to work around a SDK bug that ignores calls to stopAutoRefresh()
|
|
154
170
|
[self.adView setExtraParameterForKey: @"allow_pause_auto_refresh_immediately" value: @"true"];
|
|
155
171
|
|
|
172
|
+
for ( NSString *key in self.extraParameters )
|
|
173
|
+
{
|
|
174
|
+
[self.adView setExtraParameterForKey: key value: self.extraParameters[key]];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for ( NSString *key in self.localExtraParameters )
|
|
178
|
+
{
|
|
179
|
+
[self.adView setLocalExtraParameterForKey: key value: self.localExtraParameters[key]];
|
|
180
|
+
}
|
|
181
|
+
|
|
156
182
|
if ( [self isAutoRefresh] )
|
|
157
183
|
{
|
|
158
184
|
[self.adView startAutoRefresh];
|
|
@@ -198,36 +224,41 @@
|
|
|
198
224
|
|
|
199
225
|
- (void)didLoadAd:(MAAd *)ad
|
|
200
226
|
{
|
|
201
|
-
[[AppLovinMAX shared]
|
|
227
|
+
self.onAdLoadedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
|
|
202
228
|
}
|
|
203
229
|
|
|
204
230
|
- (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error
|
|
205
231
|
{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
[[AppLovinMAX shared] sendReactNativeEventForAdLoadFailed: name forAdUnitIdentifier: adUnitIdentifier withError: error];
|
|
232
|
+
self.onAdLoadFailedEvent([[AppLovinMAX shared] adLoadFailedInfoForAd: adUnitIdentifier withError: error]);
|
|
209
233
|
}
|
|
210
234
|
|
|
211
235
|
- (void)didFailToDisplayAd:(MAAd *)ad withError:(MAError *)error
|
|
212
236
|
{
|
|
213
|
-
[[AppLovinMAX shared]
|
|
237
|
+
self.onAdDisplayFailedEvent([[AppLovinMAX shared] adDisplayFailedInfoForAd: ad withError: error]);
|
|
214
238
|
}
|
|
215
239
|
|
|
216
240
|
- (void)didClickAd:(MAAd *)ad
|
|
217
241
|
{
|
|
218
|
-
[[AppLovinMAX shared]
|
|
242
|
+
self.onAdClickedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
|
|
219
243
|
}
|
|
220
244
|
|
|
221
245
|
#pragma mark - MAAdViewAdDelegate Protocol
|
|
222
246
|
|
|
223
247
|
- (void)didExpandAd:(MAAd *)ad
|
|
224
248
|
{
|
|
225
|
-
[[AppLovinMAX shared]
|
|
249
|
+
self.onAdExpandedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
|
|
226
250
|
}
|
|
227
251
|
|
|
228
252
|
- (void)didCollapseAd:(MAAd *)ad
|
|
229
253
|
{
|
|
230
|
-
[[AppLovinMAX shared]
|
|
254
|
+
self.onAdCollapsedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
#pragma mark - MAAdRevenueDelegate Protocol
|
|
258
|
+
|
|
259
|
+
- (void)didPayRevenueForAd:(MAAd *)ad
|
|
260
|
+
{
|
|
261
|
+
self.onAdRevenuePaidEvent([[AppLovinMAX shared] adRevenueInfoForAd: ad]);
|
|
231
262
|
}
|
|
232
263
|
|
|
233
264
|
#pragma mark - Deprecated Callbacks
|
|
@@ -19,6 +19,16 @@ RCT_EXPORT_VIEW_PROPERTY(placement, NSString)
|
|
|
19
19
|
RCT_EXPORT_VIEW_PROPERTY(customData, NSString)
|
|
20
20
|
RCT_EXPORT_VIEW_PROPERTY(adaptiveBannerEnabled, BOOL)
|
|
21
21
|
RCT_EXPORT_VIEW_PROPERTY(autoRefresh, BOOL)
|
|
22
|
+
RCT_EXPORT_VIEW_PROPERTY(extraParameters, NSDictionary)
|
|
23
|
+
RCT_EXPORT_VIEW_PROPERTY(localExtraParameters, NSDictionary)
|
|
24
|
+
|
|
25
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdLoadedEvent, RCTDirectEventBlock)
|
|
26
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdLoadFailedEvent, RCTDirectEventBlock)
|
|
27
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdDisplayFailedEvent, RCTDirectEventBlock)
|
|
28
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdClickedEvent, RCTDirectEventBlock)
|
|
29
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdExpandedEvent, RCTDirectEventBlock)
|
|
30
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdCollapsedEvent, RCTDirectEventBlock)
|
|
31
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdRevenuePaidEvent, RCTDirectEventBlock)
|
|
22
32
|
|
|
23
33
|
+ (BOOL)requiresMainQueueSetup
|
|
24
34
|
{
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
- (void)handleNativeAdViewRenderedForAd:(MAAd *)ad;
|
|
19
19
|
@end
|
|
20
20
|
|
|
21
|
-
@interface AppLovinMAXNativeAdView()<MANativeAdDelegate>
|
|
21
|
+
@interface AppLovinMAXNativeAdView()<MANativeAdDelegate, MAAdRevenueDelegate>
|
|
22
22
|
|
|
23
23
|
@property (nonatomic, weak) RCTBridge *bridge;
|
|
24
24
|
@property (nonatomic, strong, nullable) MANativeAdLoader *adLoader;
|
|
@@ -30,9 +30,13 @@
|
|
|
30
30
|
@property (nonatomic, copy, nullable) NSString *placement;
|
|
31
31
|
@property (nonatomic, copy, nullable) NSString *customData;
|
|
32
32
|
@property (nonatomic, copy, nullable) NSDictionary *extraParameters;
|
|
33
|
+
@property (nonatomic, copy, nullable) NSDictionary *localExtraParameters;
|
|
33
34
|
|
|
34
35
|
// Callback to `AppLovinNativeAdView.js`
|
|
35
|
-
@property (nonatomic, copy) RCTDirectEventBlock
|
|
36
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdLoadedEvent;
|
|
37
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdLoadFailedEvent;
|
|
38
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdClickedEvent;
|
|
39
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAdRevenuePaidEvent;
|
|
36
40
|
|
|
37
41
|
// TODO: Allow publisher to select which views are clickable and which isn't via prop
|
|
38
42
|
@property (nonatomic, strong) NSMutableArray<UIView *> *clickableViews;
|
|
@@ -62,7 +66,7 @@
|
|
|
62
66
|
{
|
|
63
67
|
_adLoader = [[MANativeAdLoader alloc] initWithAdUnitIdentifier: self.adUnitId sdk: [AppLovinMAX shared].sdk];
|
|
64
68
|
_adLoader.nativeAdDelegate = self;
|
|
65
|
-
_adLoader.revenueDelegate =
|
|
69
|
+
_adLoader.revenueDelegate = self;
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
return _adLoader;
|
|
@@ -93,6 +97,12 @@
|
|
|
93
97
|
// Called when Ad Unit ID is set, and via RN layer
|
|
94
98
|
- (void)loadAd
|
|
95
99
|
{
|
|
100
|
+
if ( ![AppLovinMAX shared].sdk )
|
|
101
|
+
{
|
|
102
|
+
[[AppLovinMAX shared] logUninitializedAccessError: @"AppLovinMAXNativeAdview.loadAd"];
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
96
106
|
if ( [self.isLoading compareAndSet: NO update: YES] )
|
|
97
107
|
{
|
|
98
108
|
[[AppLovinMAX shared] log: @"Loading a native ad for Ad Unit ID: %@...", self.adUnitId];
|
|
@@ -105,6 +115,11 @@
|
|
|
105
115
|
[self.adLoader setExtraParameterForKey: key value: self.extraParameters[key]];
|
|
106
116
|
}
|
|
107
117
|
|
|
118
|
+
for ( NSString *key in self.localExtraParameters )
|
|
119
|
+
{
|
|
120
|
+
[self.adLoader setLocalExtraParameterForKey: key value: self.localExtraParameters[key]];
|
|
121
|
+
}
|
|
122
|
+
|
|
108
123
|
[self.adLoader loadAd];
|
|
109
124
|
}
|
|
110
125
|
else
|
|
@@ -171,21 +186,27 @@
|
|
|
171
186
|
[self.clickableViews addObject: view];
|
|
172
187
|
}
|
|
173
188
|
|
|
174
|
-
- (void)
|
|
189
|
+
- (void)setIconView:(NSNumber *)tag
|
|
175
190
|
{
|
|
176
|
-
if ( !self.nativeAd.nativeAd.mediaView ) return;
|
|
177
|
-
|
|
178
191
|
UIView *view = [self.bridge.uiManager viewForReactTag: tag];
|
|
179
|
-
if ( !view )
|
|
192
|
+
if ( ![view isKindOfClass: [RCTImageView class]] )
|
|
180
193
|
{
|
|
181
|
-
[[AppLovinMAX shared] log: @"Cannot find
|
|
194
|
+
[[AppLovinMAX shared] log: @"Cannot find an icon image view with tag \"%@\" for %@", tag, self.adUnitId];
|
|
182
195
|
return;
|
|
183
196
|
}
|
|
184
|
-
|
|
197
|
+
|
|
185
198
|
[self.clickableViews addObject: view];
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
199
|
+
|
|
200
|
+
MANativeAdImage *icon = self.nativeAd.nativeAd.icon;
|
|
201
|
+
if ( icon )
|
|
202
|
+
{
|
|
203
|
+
// Check if "URL" was missing and therefore need to set the image data
|
|
204
|
+
if ( !icon.URL && icon.image )
|
|
205
|
+
{
|
|
206
|
+
RCTImageView *iconImageView = (RCTImageView *) view;
|
|
207
|
+
iconImageView.defaultImage = icon.image;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
189
210
|
}
|
|
190
211
|
|
|
191
212
|
- (void)setOptionsView:(NSNumber *)tag
|
|
@@ -203,27 +224,21 @@
|
|
|
203
224
|
[self.nativeAd.nativeAd.optionsView al_pinToSuperview];
|
|
204
225
|
}
|
|
205
226
|
|
|
206
|
-
- (void)
|
|
227
|
+
- (void)setMediaView:(NSNumber *)tag
|
|
207
228
|
{
|
|
229
|
+
if ( !self.nativeAd.nativeAd.mediaView ) return;
|
|
230
|
+
|
|
208
231
|
UIView *view = [self.bridge.uiManager viewForReactTag: tag];
|
|
209
|
-
if ( !
|
|
232
|
+
if ( !view )
|
|
210
233
|
{
|
|
211
|
-
[[AppLovinMAX shared] log: @"Cannot find
|
|
234
|
+
[[AppLovinMAX shared] log: @"Cannot find a media view with tag \"%@\" for %@", tag, self.adUnitId];
|
|
212
235
|
return;
|
|
213
236
|
}
|
|
214
|
-
|
|
237
|
+
|
|
215
238
|
[self.clickableViews addObject: view];
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
{
|
|
220
|
-
// Check if "URL" was missing and therefore need to set the image data
|
|
221
|
-
if ( !icon.URL && icon.image )
|
|
222
|
-
{
|
|
223
|
-
RCTImageView *iconImageView = (RCTImageView *) view;
|
|
224
|
-
iconImageView.defaultImage = icon.image;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
239
|
+
|
|
240
|
+
[view addSubview: self.nativeAd.nativeAd.mediaView];
|
|
241
|
+
[self.nativeAd.nativeAd.mediaView al_pinToSuperview];
|
|
227
242
|
}
|
|
228
243
|
|
|
229
244
|
#pragma mark - Ad Loader Delegate
|
|
@@ -238,7 +253,7 @@
|
|
|
238
253
|
[self.isLoading set: NO];
|
|
239
254
|
|
|
240
255
|
[[AppLovinMAX shared] log: @"Native ad is of template type, failing ad load..."];
|
|
241
|
-
[[AppLovinMAX shared]
|
|
256
|
+
self.onAdLoadFailedEvent([[AppLovinMAX shared] adLoadFailedInfoForAd: self.adUnitId withError: nil]);
|
|
242
257
|
|
|
243
258
|
return;
|
|
244
259
|
}
|
|
@@ -253,9 +268,6 @@
|
|
|
253
268
|
// After notifying the RN layer - have slight delay to let views bind to this layer in `clickableViews` before registering
|
|
254
269
|
dispatchOnMainQueueAfter(0.5, ^{
|
|
255
270
|
|
|
256
|
-
// Notify publisher
|
|
257
|
-
[[AppLovinMAX shared] didLoadAd: ad];
|
|
258
|
-
|
|
259
271
|
[self.adLoader registerClickableViews: self.clickableViews withContainer: self forAd: ad];
|
|
260
272
|
[self.adLoader handleNativeAdViewRenderedForAd: ad];
|
|
261
273
|
|
|
@@ -265,8 +277,32 @@
|
|
|
265
277
|
|
|
266
278
|
- (void)sendAdLoadedReactNativeEventForAd:(MANativeAd *)ad
|
|
267
279
|
{
|
|
268
|
-
|
|
280
|
+
// 1. AdInfo for publisher to be notified via `onAdLoaded`
|
|
269
281
|
|
|
282
|
+
NSMutableDictionary<NSString *, id> *nativeAdInfo = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
283
|
+
if ( !isnan(ad.mediaContentAspectRatio) )
|
|
284
|
+
{
|
|
285
|
+
// The aspect ratio can be 0.0f when it is not provided by the network.
|
|
286
|
+
if ( fabs(ad.mediaContentAspectRatio) < FLT_EPSILON )
|
|
287
|
+
{
|
|
288
|
+
nativeAdInfo[@"mediaContentAspectRatio"] = @(1.0);
|
|
289
|
+
}
|
|
290
|
+
else
|
|
291
|
+
{
|
|
292
|
+
nativeAdInfo[@"mediaContentAspectRatio"] = @(ad.mediaContentAspectRatio);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
else
|
|
296
|
+
{
|
|
297
|
+
nativeAdInfo[@"mediaContentAspectRatio"] = @(1.0);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
NSMutableDictionary *adInfo = [[AppLovinMAX shared] adInfoForAd: self.nativeAd].mutableCopy;
|
|
301
|
+
adInfo[@"nativeAd"] = nativeAdInfo;
|
|
302
|
+
|
|
303
|
+
// 2. NativeAd for `AppLovinNativeAdView.js` to render the views
|
|
304
|
+
|
|
305
|
+
NSMutableDictionary<NSString *, id> *jsNativeAd = [NSMutableDictionary dictionaryWithCapacity: 5];
|
|
270
306
|
if ( ad.title )
|
|
271
307
|
{
|
|
272
308
|
jsNativeAd[@"title"] = ad.title;
|
|
@@ -294,13 +330,15 @@
|
|
|
294
330
|
jsNativeAd[@"image"] = @(YES);
|
|
295
331
|
}
|
|
296
332
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
333
|
+
jsNativeAd[@"isOptionsViewAvailable"] = ad.optionsView ? @(YES) : @(NO);
|
|
334
|
+
jsNativeAd[@"isMediaViewAvailable"] = ad.mediaView ? @(YES) : @(NO);
|
|
335
|
+
|
|
336
|
+
NSMutableDictionary<NSString *, id> *arg = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
337
|
+
arg[@"adInfo"] = adInfo;
|
|
338
|
+
arg[@"nativeAd"] = jsNativeAd;
|
|
339
|
+
|
|
340
|
+
// Send to `AppLovinNativeAdView.js`
|
|
341
|
+
self.onAdLoadedEvent(arg);
|
|
304
342
|
}
|
|
305
343
|
|
|
306
344
|
- (void)didFailToLoadNativeAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error
|
|
@@ -310,12 +348,19 @@
|
|
|
310
348
|
[[AppLovinMAX shared] log: @"Failed to load native ad for Ad Unit ID %@ with error: %@", self.adUnitId, error];
|
|
311
349
|
|
|
312
350
|
// Notify publisher
|
|
313
|
-
[[AppLovinMAX shared]
|
|
351
|
+
self.onAdLoadFailedEvent([[AppLovinMAX shared] adLoadFailedInfoForAd: adUnitIdentifier withError: error]);
|
|
314
352
|
}
|
|
315
353
|
|
|
316
354
|
- (void)didClickNativeAd:(MAAd *)ad
|
|
317
355
|
{
|
|
318
|
-
[[AppLovinMAX shared]
|
|
356
|
+
self.onAdClickedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
#pragma mark - Ad Revenue Delegate
|
|
360
|
+
|
|
361
|
+
- (void)didPayRevenueForAd:(MAAd *)ad
|
|
362
|
+
{
|
|
363
|
+
self.onAdRevenuePaidEvent([[AppLovinMAX shared] adRevenueInfoForAd: ad]);
|
|
319
364
|
}
|
|
320
365
|
|
|
321
366
|
- (void)destroyCurrentAdIfNeeded
|
|
@@ -18,9 +18,7 @@ RCT_EXPORT_VIEW_PROPERTY(adUnitId, NSString)
|
|
|
18
18
|
RCT_EXPORT_VIEW_PROPERTY(placement, NSString)
|
|
19
19
|
RCT_EXPORT_VIEW_PROPERTY(customData, NSString)
|
|
20
20
|
RCT_EXPORT_VIEW_PROPERTY(extraParameters, NSDictionary)
|
|
21
|
-
|
|
22
|
-
// Callback
|
|
23
|
-
RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTDirectEventBlock)
|
|
21
|
+
RCT_EXPORT_VIEW_PROPERTY(localExtraParameters, NSDictionary)
|
|
24
22
|
|
|
25
23
|
// Asset views
|
|
26
24
|
RCT_EXPORT_VIEW_PROPERTY(titleView, NSNumber)
|
|
@@ -31,6 +29,12 @@ RCT_EXPORT_VIEW_PROPERTY(iconView, NSNumber)
|
|
|
31
29
|
RCT_EXPORT_VIEW_PROPERTY(optionsView, NSNumber)
|
|
32
30
|
RCT_EXPORT_VIEW_PROPERTY(mediaView, NSNumber)
|
|
33
31
|
|
|
32
|
+
// Callback
|
|
33
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdLoadedEvent, RCTDirectEventBlock)
|
|
34
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdLoadFailedEvent, RCTDirectEventBlock)
|
|
35
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdClickedEvent, RCTDirectEventBlock)
|
|
36
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdRevenuePaidEvent, RCTDirectEventBlock)
|
|
37
|
+
|
|
34
38
|
+ (BOOL)requiresMainQueueSetup
|
|
35
39
|
{
|
|
36
40
|
return YES;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-applovin-max",
|
|
3
3
|
"author": "AppLovin Corporation",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "5.0.0",
|
|
5
5
|
"description": "AppLovin MAX React Native Plugin for Android and iOS",
|
|
6
6
|
"homepage": "https://github.com/AppLovin/AppLovin-MAX-React-Native",
|
|
7
7
|
"license": "MIT",
|
|
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
|
|
|
11
11
|
s.authors = package["author"]
|
|
12
12
|
|
|
13
13
|
s.platforms = { :ios => "10.0" }
|
|
14
|
-
s.source = { :git => "https://github.com/AppLovin/AppLovin-MAX-React-Native.git", :tag => "
|
|
14
|
+
s.source = { :git => "https://github.com/AppLovin/AppLovin-MAX-React-Native.git", :tag => "release_5_0_0" }
|
|
15
15
|
|
|
16
16
|
s.source_files = "ios/AppLovinMAX*.{h,m}"
|
|
17
17
|
|
package/src/AppLovinMAXAdView.js
CHANGED
|
@@ -1,85 +1,142 @@
|
|
|
1
|
-
import { NativeModules, requireNativeComponent
|
|
1
|
+
import { NativeModules, requireNativeComponent } from "react-native";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
|
-
import React from "react";
|
|
3
|
+
import React, { useEffect, useState } from "react";
|
|
4
4
|
|
|
5
5
|
const { AppLovinMAX } = NativeModules;
|
|
6
6
|
|
|
7
|
+
const {
|
|
8
|
+
TOP_CENTER_POSITION,
|
|
9
|
+
TOP_LEFT_POSITION,
|
|
10
|
+
TOP_RIGHT_POSITION,
|
|
11
|
+
CENTERED_POSITION,
|
|
12
|
+
CENTER_LEFT_POSITION,
|
|
13
|
+
CENTER_RIGHT_POSITION,
|
|
14
|
+
BOTTOM_LEFT_POSITION,
|
|
15
|
+
BOTTOM_CENTER_POSITION,
|
|
16
|
+
BOTTOM_RIGHT_POSITION,
|
|
17
|
+
|
|
18
|
+
BANNER_AD_FORMAT_LABEL,
|
|
19
|
+
MREC_AD_FORMAT_LABEL,
|
|
20
|
+
} = AppLovinMAX.getConstants();
|
|
21
|
+
|
|
7
22
|
export const AdFormat = {
|
|
8
|
-
BANNER:
|
|
9
|
-
MREC:
|
|
23
|
+
BANNER: BANNER_AD_FORMAT_LABEL,
|
|
24
|
+
MREC: MREC_AD_FORMAT_LABEL,
|
|
10
25
|
};
|
|
11
26
|
|
|
12
27
|
export const AdViewPosition = {
|
|
13
|
-
TOP_CENTER:
|
|
14
|
-
TOP_LEFT:
|
|
15
|
-
TOP_RIGHT:
|
|
16
|
-
CENTERED:
|
|
17
|
-
CENTER_LEFT:
|
|
18
|
-
CENTER_RIGHT:
|
|
19
|
-
BOTTOM_LEFT:
|
|
20
|
-
BOTTOM_CENTER:
|
|
21
|
-
BOTTOM_RIGHT:
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Returns AdView when AppLovinMax has been initialized or returns a black empty View as
|
|
26
|
-
* a placeholder of AdView when AppLovinMax has not been initialized.
|
|
27
|
-
*
|
|
28
|
-
* The purpose of this AdView wrapper is for the application not to access AdView
|
|
29
|
-
* before the completion of the AppLovinMax initialization.
|
|
30
|
-
*
|
|
31
|
-
* Note: this does not re-render itself when the status of the AppLovinMax initialization
|
|
32
|
-
* has changed so that the black view may stay even after the completion of
|
|
33
|
-
* the AppLovinMax initialization.
|
|
34
|
-
*/
|
|
35
|
-
const AdViewWrapper = (props) => {
|
|
36
|
-
const {style, ...rest} = props;
|
|
37
|
-
return (
|
|
38
|
-
AppLovinMAX.isInitialized() ?
|
|
39
|
-
<AdView {...style} {...rest}/>
|
|
40
|
-
:
|
|
41
|
-
<View style={[styles.container, style]} {...rest}>
|
|
42
|
-
{
|
|
43
|
-
console.warn('[AppLovinSdk] [AppLovinMAX] <AdView/> has been mounted before AppLovin initialization')
|
|
44
|
-
}
|
|
45
|
-
</View>
|
|
46
|
-
);
|
|
28
|
+
TOP_CENTER : TOP_CENTER_POSITION,
|
|
29
|
+
TOP_LEFT : TOP_LEFT_POSITION,
|
|
30
|
+
TOP_RIGHT : TOP_RIGHT_POSITION,
|
|
31
|
+
CENTERED : CENTERED_POSITION,
|
|
32
|
+
CENTER_LEFT : CENTER_LEFT_POSITION,
|
|
33
|
+
CENTER_RIGHT : CENTER_RIGHT_POSITION,
|
|
34
|
+
BOTTOM_LEFT : BOTTOM_LEFT_POSITION,
|
|
35
|
+
BOTTOM_CENTER : BOTTOM_CENTER_POSITION,
|
|
36
|
+
BOTTOM_RIGHT : BOTTOM_RIGHT_POSITION,
|
|
47
37
|
};
|
|
48
38
|
|
|
49
|
-
const styles = StyleSheet.create({
|
|
50
|
-
container: {
|
|
51
|
-
flexDirection: 'column',
|
|
52
|
-
justifyContent: 'flex-end',
|
|
53
|
-
alignItems: 'center',
|
|
54
|
-
backgroundColor: 'black',
|
|
55
|
-
borderColor: 'whitesmoke',
|
|
56
|
-
borderWidth: 1,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
39
|
const AdView = (props) => {
|
|
61
|
-
const {style, ...otherProps} = props;
|
|
40
|
+
const {style, extraParameters, localExtraParameters, ...otherProps} = props;
|
|
41
|
+
const [dimensions, setDimensions] = useState({});
|
|
62
42
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
const sizeForBannerFormat = async () => {
|
|
45
|
+
const isTablet = await AppLovinMAX.isTablet();
|
|
46
|
+
const width = isTablet ? 728 : 320;
|
|
66
47
|
let height;
|
|
67
|
-
|
|
68
48
|
if (props.adaptiveBannerEnabled) {
|
|
69
|
-
height = AppLovinMAX.getAdaptiveBannerHeightForWidth(-1);
|
|
49
|
+
height = await AppLovinMAX.getAdaptiveBannerHeightForWidth(-1);
|
|
70
50
|
} else {
|
|
71
|
-
height =
|
|
51
|
+
height = isTablet ? 90 : 50;
|
|
72
52
|
}
|
|
53
|
+
setDimensions({width: (style.width && style.width !== 'auto') ? style.width : width,
|
|
54
|
+
height: (style.height && style.height !== 'auto') ? style.height : height});
|
|
55
|
+
}
|
|
73
56
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
57
|
+
// Check whether or not app specifies both width and height but not with 'auto'
|
|
58
|
+
const isSizeSpecified = ((style.width && style.width !== 'auto') &&
|
|
59
|
+
(style.height && style.height !== 'auto'));
|
|
60
|
+
|
|
61
|
+
if (!isSizeSpecified) {
|
|
62
|
+
if (props.adFormat === AdFormat.BANNER) {
|
|
63
|
+
sizeForBannerFormat();
|
|
64
|
+
} else {
|
|
65
|
+
setDimensions({width: (style.width && style.width !== 'auto') ? style.width : 300,
|
|
66
|
+
height: (style.height && style.height !== 'auto') ? style.height : 250});
|
|
67
|
+
}
|
|
77
68
|
}
|
|
69
|
+
}, []);
|
|
70
|
+
|
|
71
|
+
const onAdLoadedEvent = (event) => {
|
|
72
|
+
if (props.onAdLoaded) props.onAdLoaded(event.nativeEvent);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const onAdLoadFailedEvent = (event) => {
|
|
76
|
+
if (props.onAdLoadFailed) props.onAdLoadFailed(event.nativeEvent);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const onAdDisplayFailedEvent = (event) => {
|
|
80
|
+
if (props.onAdDisplayFailed) props.onAdDisplayFailed(event.nativeEvent);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const onAdClickedEvent = (event) => {
|
|
84
|
+
if (props.onAdClicked) props.onAdClicked(event.nativeEvent);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const onAdExpandedEvent = (event) => {
|
|
88
|
+
if (props.onAdExpanded) props.onAdExpanded(event.nativeEvent);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const onAdCollapsedEvent = (event) => {
|
|
92
|
+
if (props.onAdCollapsed) props.onAdCollapsed(event.nativeEvent);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const onAdRevenuePaidEvent = (event) => {
|
|
96
|
+
if (props.onAdRevenuePaid) props.onAdRevenuePaid(event.nativeEvent);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const sanitizeExtraParameters = (name, params) => {
|
|
100
|
+
if (!params) return params;
|
|
101
|
+
|
|
102
|
+
for (const key in params) {
|
|
103
|
+
const value = params[key];
|
|
104
|
+
|
|
105
|
+
// `null` and `undefined` are valid values (e.g. for clearing previously-set values)
|
|
106
|
+
if (value == null || value == undefined) continue;
|
|
107
|
+
|
|
108
|
+
if (typeof value !== 'string') {
|
|
109
|
+
console.warn("AppLovinMAXAdView only support string values: " + value + ", deleting value for key: " + key);
|
|
110
|
+
delete params[key];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return params;
|
|
78
115
|
};
|
|
79
116
|
|
|
117
|
+
{
|
|
118
|
+
const isSizeSpecified = ((style.width && style.width !== 'auto') &&
|
|
119
|
+
(style.height && style.height !== 'auto'));
|
|
120
|
+
const isDimensionsSet = (Object.keys(dimensions).length > 0);
|
|
121
|
+
|
|
122
|
+
// Not sized yet
|
|
123
|
+
if (!(isSizeSpecified || isDimensionsSet)) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
80
128
|
return (
|
|
81
129
|
<AppLovinMAXAdView
|
|
82
|
-
style={
|
|
130
|
+
style={{...style, ...dimensions}}
|
|
131
|
+
extraParameters={sanitizeExtraParameters('extraParameters', extraParameters)}
|
|
132
|
+
localExtraParameters={sanitizeExtraParameters('localExtraParameters', localExtraParameters)}
|
|
133
|
+
onAdLoadedEvent={onAdLoadedEvent}
|
|
134
|
+
onAdLoadFailedEvent={onAdLoadFailedEvent}
|
|
135
|
+
onAdDisplayFailedEvent={onAdDisplayFailedEvent}
|
|
136
|
+
onAdClickedEvent={onAdClickedEvent}
|
|
137
|
+
onAdExpandedEvent={onAdExpandedEvent}
|
|
138
|
+
onAdCollapsedEvent={onAdCollapsedEvent}
|
|
139
|
+
onAdRevenuePaidEvent={onAdRevenuePaidEvent}
|
|
83
140
|
{...otherProps}
|
|
84
141
|
/>
|
|
85
142
|
);
|
|
@@ -115,6 +172,51 @@ AdView.propTypes = {
|
|
|
115
172
|
* A boolean value representing whether or not to enable auto-refresh. Note that auto-refresh is enabled by default.
|
|
116
173
|
*/
|
|
117
174
|
autoRefresh: PropTypes.bool,
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* A dictionary of extra parameters consisting of key-value string pairs.
|
|
178
|
+
*/
|
|
179
|
+
extraParameters: PropTypes.object,
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* A dictionary of local extra parameters consisting of key-value string pairs.
|
|
183
|
+
*/
|
|
184
|
+
localExtraParameters: PropTypes.object,
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* A callback fuction to be fired when a new ad has been loaded.
|
|
188
|
+
*/
|
|
189
|
+
onAdLoaded: PropTypes.func,
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* A callback fuction to be fired when an ad could not be retrieved.
|
|
193
|
+
*/
|
|
194
|
+
onAdLoadFailed: PropTypes.func,
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* A callback fuction to be fired when the ad failed to display.
|
|
198
|
+
*/
|
|
199
|
+
onAdDisplayFailed: PropTypes.func,
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A callback fuction to be fired when ad is clicked.
|
|
203
|
+
*/
|
|
204
|
+
onAdClicked: PropTypes.func,
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* A callback fuction to be fired when the ad view is expanded.
|
|
208
|
+
*/
|
|
209
|
+
onAdExpanded: PropTypes.func,
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* A callback fuction to be fired when the ad view is collapsed.
|
|
213
|
+
*/
|
|
214
|
+
onAdCollapsed: PropTypes.func,
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* A callback fuction to be fired when the revenue event is detected.
|
|
218
|
+
*/
|
|
219
|
+
onAdRevenuePaid: PropTypes.func,
|
|
118
220
|
};
|
|
119
221
|
|
|
120
222
|
// Defiens default values for the props.
|
|
@@ -123,8 +225,7 @@ AdView.defaultProps = {
|
|
|
123
225
|
autoRefresh: true,
|
|
124
226
|
};
|
|
125
227
|
|
|
126
|
-
|
|
127
228
|
// requireNativeComponent automatically resolves 'AppLovinMAXAdView' to 'AppLovinMAXAdViewManager'
|
|
128
229
|
const AppLovinMAXAdView = requireNativeComponent("AppLovinMAXAdView", AdView);
|
|
129
230
|
|
|
130
|
-
export default
|
|
231
|
+
export default AdView;
|