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.
@@ -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 ( [@"banner" isEqualToString: adFormat] )
61
+ if ( [MAAdFormat.banner.label isEqualToString: adFormat] )
52
62
  {
53
63
  _adFormat = DEVICE_SPECIFIC_ADVIEW_AD_FORMAT;
54
64
  }
55
- else if ( [@"mrec" isEqualToString: adFormat] )
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 = [AppLovinMAX shared];
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] didLoadAd: ad];
227
+ self.onAdLoadedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
202
228
  }
203
229
 
204
230
  - (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error
205
231
  {
206
- NSString *name = ( MAAdFormat.mrec == self.adFormat ) ? @"OnMRecAdLoadFailedEvent" : @"OnBannerAdLoadFailedEvent";
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] didFailToDisplayAd: ad withError: error];
237
+ self.onAdDisplayFailedEvent([[AppLovinMAX shared] adDisplayFailedInfoForAd: ad withError: error]);
214
238
  }
215
239
 
216
240
  - (void)didClickAd:(MAAd *)ad
217
241
  {
218
- [[AppLovinMAX shared] didClickAd: ad];
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] didExpandAd: ad];
249
+ self.onAdExpandedEvent([[AppLovinMAX shared] adInfoForAd: ad]);
226
250
  }
227
251
 
228
252
  - (void)didCollapseAd:(MAAd *)ad
229
253
  {
230
- [[AppLovinMAX shared] didCollapseAd: ad];
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 onAdLoaded;
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 = [AppLovinMAX shared];
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)setMediaView:(NSNumber *)tag
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 a media view with tag \"%@\" for %@", tag, self.adUnitId];
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
- [view addSubview: self.nativeAd.nativeAd.mediaView];
188
- [self.nativeAd.nativeAd.mediaView al_pinToSuperview];
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)setIconView:(NSNumber *)tag
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 ( ![view isKindOfClass: [RCTImageView class]] )
232
+ if ( !view )
210
233
  {
211
- [[AppLovinMAX shared] log: @"Cannot find an icon image view with tag \"%@\" for %@", tag, self.adUnitId];
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
- MANativeAdImage *icon = self.nativeAd.nativeAd.icon;
218
- if ( icon )
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] sendReactNativeEventForAdLoadFailed: @"OnNativeAdLoadFailedEvent" forAdUnitIdentifier: self.adUnitId withError: nil];
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
- NSMutableDictionary<NSString *, id> *jsNativeAd = [NSMutableDictionary dictionaryWithCapacity: 6];
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
- if ( !isnan(ad.mediaContentAspectRatio) )
298
- {
299
- jsNativeAd[@"mediaContentAspectRatio"] = @(ad.mediaContentAspectRatio);
300
- }
301
-
302
- // Send to `AppLovinNativeAdView.js` to render the views
303
- self.onAdLoaded(jsNativeAd);
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] sendReactNativeEventForAdLoadFailed: @"OnNativeAdLoadFailedEvent" forAdUnitIdentifier: self.adUnitId withError: error];
351
+ self.onAdLoadFailedEvent([[AppLovinMAX shared] adLoadFailedInfoForAd: adUnitIdentifier withError: error]);
314
352
  }
315
353
 
316
354
  - (void)didClickNativeAd:(MAAd *)ad
317
355
  {
318
- [[AppLovinMAX shared] didClickAd: ad];
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.1.6",
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 => "release_4_1_6" }
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
 
@@ -1,85 +1,142 @@
1
- import { NativeModules, requireNativeComponent, UIManager, findNodeHandle, View, Text, StyleSheet } from "react-native";
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: "banner",
9
- MREC: "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: "top_center",
14
- TOP_LEFT: "top_left",
15
- TOP_RIGHT: "top_right",
16
- CENTERED: "centered",
17
- CENTER_LEFT: "center_left",
18
- CENTER_RIGHT: "center_right",
19
- BOTTOM_LEFT: "bottom_left",
20
- BOTTOM_CENTER: "bottom_center",
21
- BOTTOM_RIGHT: "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
- const sizeForAdFormat = () => {
64
- if (props.adFormat === AdFormat.BANNER) {
65
- let width = AppLovinMAX.isTablet() ? 728 : 320;
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 = AppLovinMAX.isTablet() ? 90 : 50;
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
- return { width: width, height: height }
75
- } else {
76
- return { width: 300, height: 250 }
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={[sizeForAdFormat(), 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 AdViewWrapper;
231
+ export default AdView;