react-native-applovin-max 9.0.0 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdView.java +1 -1
- package/android/src/main/java/com/applovin/reactnative/AppLovinMAXModuleImpl.java +2 -1
- package/ios/AppLovinMAX.mm +2 -1
- package/lib/commonjs/AdView.js +60 -76
- package/lib/commonjs/AdView.js.map +1 -1
- package/lib/commonjs/AppLovinMAX.js +43 -29
- package/lib/commonjs/AppLovinMAX.js.map +1 -1
- package/lib/commonjs/ErrorCode.js +24 -31
- package/lib/commonjs/ErrorCode.js.map +1 -1
- package/lib/commonjs/EventEmitter.js +22 -1
- package/lib/commonjs/EventEmitter.js.map +1 -1
- package/lib/commonjs/Utils.js +22 -4
- package/lib/commonjs/Utils.js.map +1 -1
- package/lib/commonjs/nativeAd/NativeAdView.js +33 -22
- package/lib/commonjs/nativeAd/NativeAdView.js.map +1 -1
- package/lib/commonjs/nativeAd/NativeAdViewComponents.js +84 -41
- package/lib/commonjs/nativeAd/NativeAdViewComponents.js.map +1 -1
- package/lib/commonjs/nativeAd/NativeAdViewProvider.js +29 -0
- package/lib/commonjs/nativeAd/NativeAdViewProvider.js.map +1 -1
- package/lib/commonjs/specs/AppLovinMAXAdViewNativeComponent.js +27 -0
- package/lib/commonjs/specs/AppLovinMAXAdViewNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/AppLovinMAXNativeAdViewNativeComponent.js +23 -0
- package/lib/commonjs/specs/AppLovinMAXNativeAdViewNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/NativeAppLovinMAXModule.js +7 -0
- package/lib/commonjs/specs/NativeAppLovinMAXModule.js.map +1 -1
- package/lib/commonjs/types/AdInfo.js +13 -16
- package/lib/commonjs/types/AdInfo.js.map +1 -1
- package/lib/module/AdView.js +60 -76
- package/lib/module/AdView.js.map +1 -1
- package/lib/module/AppLovinMAX.js +44 -29
- package/lib/module/AppLovinMAX.js.map +1 -1
- package/lib/module/ErrorCode.js +24 -31
- package/lib/module/ErrorCode.js.map +1 -1
- package/lib/module/EventEmitter.js +22 -1
- package/lib/module/EventEmitter.js.map +1 -1
- package/lib/module/Utils.js +22 -4
- package/lib/module/Utils.js.map +1 -1
- package/lib/module/nativeAd/NativeAdView.js +34 -21
- package/lib/module/nativeAd/NativeAdView.js.map +1 -1
- package/lib/module/nativeAd/NativeAdViewComponents.js +87 -40
- package/lib/module/nativeAd/NativeAdViewComponents.js.map +1 -1
- package/lib/module/nativeAd/NativeAdViewProvider.js +30 -0
- package/lib/module/nativeAd/NativeAdViewProvider.js.map +1 -1
- package/lib/module/specs/AppLovinMAXAdViewNativeComponent.js +28 -0
- package/lib/module/specs/AppLovinMAXAdViewNativeComponent.js.map +1 -1
- package/lib/module/specs/AppLovinMAXNativeAdViewNativeComponent.js +24 -0
- package/lib/module/specs/AppLovinMAXNativeAdViewNativeComponent.js.map +1 -1
- package/lib/module/specs/NativeAppLovinMAXModule.js +9 -0
- package/lib/module/specs/NativeAppLovinMAXModule.js.map +1 -1
- package/lib/module/types/AdInfo.js +13 -16
- package/lib/module/types/AdInfo.js.map +1 -1
- package/lib/typescript/src/AdView.d.ts +27 -21
- package/lib/typescript/src/AdView.d.ts.map +1 -1
- package/lib/typescript/src/AppLovinMAX.d.ts +22 -21
- package/lib/typescript/src/AppLovinMAX.d.ts.map +1 -1
- package/lib/typescript/src/ErrorCode.d.ts +24 -31
- package/lib/typescript/src/ErrorCode.d.ts.map +1 -1
- package/lib/typescript/src/EventEmitter.d.ts +16 -0
- package/lib/typescript/src/EventEmitter.d.ts.map +1 -1
- package/lib/typescript/src/Utils.d.ts +15 -0
- package/lib/typescript/src/Utils.d.ts.map +1 -1
- package/lib/typescript/src/nativeAd/NativeAdView.d.ts +15 -7
- package/lib/typescript/src/nativeAd/NativeAdView.d.ts.map +1 -1
- package/lib/typescript/src/nativeAd/NativeAdViewComponents.d.ts +65 -1
- package/lib/typescript/src/nativeAd/NativeAdViewComponents.d.ts.map +1 -1
- package/lib/typescript/src/nativeAd/NativeAdViewProvider.d.ts +17 -0
- package/lib/typescript/src/nativeAd/NativeAdViewProvider.d.ts.map +1 -1
- package/lib/typescript/src/specs/AppLovinMAXAdViewNativeComponent.d.ts +45 -1
- package/lib/typescript/src/specs/AppLovinMAXAdViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/specs/AppLovinMAXNativeAdViewNativeComponent.d.ts +57 -6
- package/lib/typescript/src/specs/AppLovinMAXNativeAdViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeAppLovinMAXModule.d.ts +10 -0
- package/lib/typescript/src/specs/NativeAppLovinMAXModule.d.ts.map +1 -1
- package/lib/typescript/src/types/AdEvent.d.ts +10 -4
- package/lib/typescript/src/types/AdEvent.d.ts.map +1 -1
- package/lib/typescript/src/types/AdInfo.d.ts +78 -85
- package/lib/typescript/src/types/AdInfo.d.ts.map +1 -1
- package/lib/typescript/src/types/AdProps.d.ts +14 -15
- package/lib/typescript/src/types/AdProps.d.ts.map +1 -1
- package/lib/typescript/src/types/AdViewProps.d.ts +28 -29
- package/lib/typescript/src/types/AdViewProps.d.ts.map +1 -1
- package/lib/typescript/src/types/AppLovinMAX.d.ts +50 -53
- package/lib/typescript/src/types/AppLovinMAX.d.ts.map +1 -1
- package/lib/typescript/src/types/BannerAd.d.ts +22 -17
- package/lib/typescript/src/types/BannerAd.d.ts.map +1 -1
- package/lib/typescript/src/types/CMPError.d.ts +7 -4
- package/lib/typescript/src/types/CMPError.d.ts.map +1 -1
- package/lib/typescript/src/types/Configuration.d.ts +12 -14
- package/lib/typescript/src/types/Configuration.d.ts.map +1 -1
- package/lib/typescript/src/types/FullscreenAd.d.ts +39 -46
- package/lib/typescript/src/types/FullscreenAd.d.ts.map +1 -1
- package/lib/typescript/src/types/MRecAd.d.ts +7 -3
- package/lib/typescript/src/types/MRecAd.d.ts.map +1 -1
- package/lib/typescript/src/types/NativeAd.d.ts +12 -11
- package/lib/typescript/src/types/NativeAd.d.ts.map +1 -1
- package/lib/typescript/src/types/NativeAdViewProps.d.ts +4 -3
- package/lib/typescript/src/types/NativeAdViewProps.d.ts.map +1 -1
- package/lib/typescript/src/types/Privacy.d.ts +13 -6
- package/lib/typescript/src/types/Privacy.d.ts.map +1 -1
- package/lib/typescript/src/types/RewardedAd.d.ts +7 -5
- package/lib/typescript/src/types/RewardedAd.d.ts.map +1 -1
- package/lib/typescript/src/types/ViewAd.d.ts +46 -50
- package/lib/typescript/src/types/ViewAd.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native-applovin-max.podspec +2 -2
- package/src/AdView.tsx +62 -80
- package/src/AppLovinMAX.ts +39 -29
- package/src/ErrorCode.ts +24 -31
- package/src/EventEmitter.ts +20 -2
- package/src/Utils.ts +20 -1
- package/src/nativeAd/NativeAdView.tsx +31 -21
- package/src/nativeAd/NativeAdViewComponents.tsx +97 -38
- package/src/nativeAd/NativeAdViewProvider.tsx +23 -0
- package/src/specs/AppLovinMAXAdViewNativeComponent.ts +62 -1
- package/src/specs/AppLovinMAXNativeAdViewNativeComponent.ts +70 -6
- package/src/specs/NativeAppLovinMAXModule.ts +75 -55
- package/src/types/AdEvent.ts +10 -4
- package/src/types/AdInfo.ts +78 -85
- package/src/types/AdProps.ts +14 -15
- package/src/types/AdViewProps.ts +28 -29
- package/src/types/AppLovinMAX.ts +50 -53
- package/src/types/BannerAd.ts +22 -17
- package/src/types/CMPError.ts +7 -4
- package/src/types/Configuration.ts +12 -14
- package/src/types/FullscreenAd.ts +39 -46
- package/src/types/MRecAd.ts +7 -3
- package/src/types/NativeAd.ts +12 -11
- package/src/types/NativeAdViewProps.ts +4 -3
- package/src/types/Privacy.ts +13 -6
- package/src/types/RewardedAd.ts +7 -5
- package/src/types/ViewAd.ts +46 -50
package/src/AppLovinMAX.ts
CHANGED
|
@@ -2,93 +2,100 @@ import type { AppLovinMAXType } from './types/AppLovinMAX';
|
|
|
2
2
|
import type { Configuration } from './types/Configuration';
|
|
3
3
|
import NativeAppLovinMAX from './specs/NativeAppLovinMAXModule';
|
|
4
4
|
|
|
5
|
-
const VERSION = '9.
|
|
5
|
+
const VERSION = '9.1.0';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* user.
|
|
8
|
+
* Represents the user's geography, used to determine which type of consent flow to display.
|
|
10
9
|
*/
|
|
11
10
|
export enum ConsentFlowUserGeography {
|
|
12
11
|
/**
|
|
13
|
-
*
|
|
12
|
+
* The user's geography could not be determined.
|
|
14
13
|
*/
|
|
15
14
|
UNKNOWN = 'U',
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
|
-
* The user is in GDPR region.
|
|
17
|
+
* The user is located in a GDPR region.
|
|
19
18
|
*/
|
|
20
19
|
GDPR = 'G',
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
* The user is in a
|
|
22
|
+
* The user is not in a GDPR region.
|
|
24
23
|
*/
|
|
25
24
|
OTHER = 'O',
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* App tracking transparency status values as defined by the AppLovin SDK.
|
|
29
|
+
*
|
|
30
|
+
* These values are based on Apple's AppTrackingTransparency framework (iOS 14+).
|
|
31
31
|
*/
|
|
32
32
|
export enum AppTrackingStatus {
|
|
33
33
|
/**
|
|
34
|
-
* Device is
|
|
34
|
+
* Device is running an iOS version prior to iOS 14.
|
|
35
|
+
* AppTrackingTransparency is not available.
|
|
35
36
|
*/
|
|
36
37
|
UNAVAILABLE = 'U',
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
|
-
* The user has not yet
|
|
40
|
-
* data that can be used for tracking the user or the device.
|
|
40
|
+
* The user has not yet responded to the tracking authorization prompt.
|
|
41
41
|
*/
|
|
42
42
|
NOT_DETERMINED = 'N',
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
46
|
-
* is restricted.
|
|
45
|
+
* Tracking is restricted (e.g. due to parental controls).
|
|
47
46
|
*/
|
|
48
47
|
RESTRICTED = 'R',
|
|
49
48
|
|
|
50
49
|
/**
|
|
51
|
-
* The user
|
|
52
|
-
* user or the device.
|
|
50
|
+
* The user denied authorization for tracking.
|
|
53
51
|
*/
|
|
54
52
|
DENIED = 'D',
|
|
55
53
|
|
|
56
54
|
/**
|
|
57
|
-
* The user
|
|
58
|
-
* device.
|
|
55
|
+
* The user authorized tracking access.
|
|
59
56
|
*/
|
|
60
57
|
AUTHORIZED = 'A',
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
/**
|
|
64
|
-
*
|
|
61
|
+
* Error codes returned from the Consent Management Platform (CMP) flow.
|
|
65
62
|
*/
|
|
66
63
|
export enum CMPErrorCode {
|
|
67
64
|
/**
|
|
68
|
-
*
|
|
65
|
+
* An unspecified error occurred.
|
|
69
66
|
*/
|
|
70
67
|
UNSPECIFIED = -1,
|
|
71
68
|
|
|
72
69
|
/**
|
|
73
|
-
*
|
|
70
|
+
* The CMP was not integrated correctly.
|
|
74
71
|
*/
|
|
75
72
|
INTEGRATION_ERROR = 1,
|
|
76
73
|
|
|
77
74
|
/**
|
|
78
|
-
*
|
|
75
|
+
* The CMP form is unavailable.
|
|
79
76
|
*/
|
|
80
77
|
FORM_UNAVAILABLE = 2,
|
|
81
78
|
|
|
82
79
|
/**
|
|
83
|
-
*
|
|
80
|
+
* The CMP form is not required for this user.
|
|
84
81
|
*/
|
|
85
82
|
FORM_NOT_REQUIRED = 3,
|
|
86
83
|
}
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Initializes the AppLovin MAX SDK with the provided SDK key.
|
|
87
|
+
*
|
|
88
|
+
* @param sdkKey - Your AppLovin SDK key.
|
|
89
|
+
* @returns A promise that resolves with the SDK configuration.
|
|
90
|
+
*/
|
|
91
|
+
const initialize = (sdkKey: string): Promise<Configuration> => NativeAppLovinMAX.initialize(VERSION, sdkKey);
|
|
91
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Retrieves the user segments.
|
|
95
|
+
*
|
|
96
|
+
* @returns A promise resolving to a Map of segment IDs to arrays of group IDs,
|
|
97
|
+
* or `null` if no segments are available.
|
|
98
|
+
*/
|
|
92
99
|
const getSegments = async (): Promise<Map<number, number[]> | null> => {
|
|
93
100
|
const segments = await NativeAppLovinMAX.getSegments();
|
|
94
101
|
|
|
@@ -98,10 +105,8 @@ const getSegments = async (): Promise<Map<number, number[]> | null> => {
|
|
|
98
105
|
|
|
99
106
|
const map = new Map<number, number[]>();
|
|
100
107
|
|
|
101
|
-
for (const key
|
|
102
|
-
//
|
|
103
|
-
// integer as a key, but the Map object can have keys of any data type.
|
|
104
|
-
const value = segments[key];
|
|
108
|
+
for (const [key, value] of Object.entries(segments)) {
|
|
109
|
+
// In JavaScript, object keys are always strings, so we convert them to numbers for the Map.
|
|
105
110
|
if (value) {
|
|
106
111
|
map.set(Number(key), value);
|
|
107
112
|
}
|
|
@@ -110,10 +115,15 @@ const getSegments = async (): Promise<Map<number, number[]> | null> => {
|
|
|
110
115
|
return map;
|
|
111
116
|
};
|
|
112
117
|
|
|
118
|
+
// All native methods except those overridden here
|
|
113
119
|
type NativeAppLovinMAXType = Omit<AppLovinMAXType, 'initialize' | 'getSegments'>;
|
|
114
120
|
|
|
115
121
|
const nativeMethods: NativeAppLovinMAXType = NativeAppLovinMAX;
|
|
116
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Main AppLovin MAX module interface exposed to JavaScript.
|
|
125
|
+
* Wraps the native module and overrides `initialize()` and `getSegments()` for custom handling.
|
|
126
|
+
*/
|
|
117
127
|
export const AppLovinMAX: AppLovinMAXType = Object.create(nativeMethods, {
|
|
118
128
|
initialize: {
|
|
119
129
|
value: initialize,
|
package/src/ErrorCode.ts
CHANGED
|
@@ -16,85 +16,78 @@ const {
|
|
|
16
16
|
} = AppLovinMAX.getConstants();
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
* display.
|
|
19
|
+
* Error codes returned by the AppLovin MAX SDK when an ad fails to load or display.
|
|
21
20
|
*/
|
|
22
21
|
export enum ErrorCode {
|
|
23
22
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* An unspecified error occurred.
|
|
24
|
+
* See the `message` field for more details.
|
|
26
25
|
*/
|
|
27
26
|
UNSPECIFIED = MAX_ERROR_CODE_UNSPECIFIED,
|
|
28
27
|
|
|
29
28
|
/**
|
|
30
|
-
*
|
|
31
|
-
* app/device.
|
|
29
|
+
* No eligible ads were returned from any mediated networks.
|
|
32
30
|
*/
|
|
33
31
|
NO_FILL = MAX_ERROR_CODE_NO_FILL,
|
|
34
32
|
|
|
35
33
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
34
|
+
* Eligible ads were returned but all failed to load.
|
|
35
|
+
* See `adLoadFailureInfo` for more details.
|
|
38
36
|
*/
|
|
39
37
|
AD_LOAD_FAILED = MAX_ERROR_CODE_AD_LOAD_FAILED,
|
|
40
38
|
|
|
41
39
|
/**
|
|
42
|
-
*
|
|
40
|
+
* An error occurred while attempting to display the ad.
|
|
43
41
|
*/
|
|
44
42
|
AD_DISPLAY_FAILED = MAX_ERROR_CODE_AD_DISPLAY_FAILED,
|
|
45
43
|
|
|
46
44
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
* The ad request failed due to a general network issue.
|
|
46
|
+
* See the `message` field for details.
|
|
49
47
|
*/
|
|
50
48
|
NETWORK_ERROR = MAX_ERROR_CODE_NETWORK_ERROR,
|
|
51
49
|
|
|
52
50
|
/**
|
|
53
|
-
*
|
|
51
|
+
* The ad request timed out, likely due to a slow internet connection.
|
|
54
52
|
*/
|
|
55
53
|
NETWORK_TIMEOUT = MAX_ERROR_CODE_NETWORK_TIMEOUT,
|
|
56
54
|
|
|
57
55
|
/**
|
|
58
|
-
*
|
|
59
|
-
* internet.
|
|
56
|
+
* The ad request failed because the device was offline.
|
|
60
57
|
*/
|
|
61
58
|
NO_NETWORK = MAX_ERROR_CODE_NO_NETWORK,
|
|
62
59
|
|
|
63
60
|
/**
|
|
64
|
-
*
|
|
65
|
-
* is still showing.
|
|
61
|
+
* A fullscreen ad was requested while another one was already showing.
|
|
66
62
|
*/
|
|
67
63
|
FULLSCREEN_AD_ALREADY_SHOWING = MAX_ERROR_CODE_FULLSCREEN_AD_ALREADY_SHOWING,
|
|
68
64
|
|
|
69
65
|
/**
|
|
70
|
-
*
|
|
71
|
-
* loaded.
|
|
66
|
+
* A fullscreen ad was requested before it had finished loading.
|
|
72
67
|
*/
|
|
73
68
|
FULLSCREEN_AD_NOT_READY = MAX_ERROR_CODE_FULLSCREEN_AD_NOT_READY,
|
|
74
69
|
|
|
75
70
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* **iOS ONLY**.
|
|
71
|
+
* The ad was presented from an invalid view controller.
|
|
72
|
+
* **iOS only**.
|
|
79
73
|
*/
|
|
80
74
|
FULLSCREEN_AD_INVALID_VIEW_CONTROLLER = MAX_ERROR_CODE_FULLSCREEN_AD_INVALID_VIEW_CONTROLLER,
|
|
81
75
|
|
|
82
76
|
/**
|
|
83
|
-
*
|
|
84
|
-
* "Don't Keep Activities" developer setting enabled.
|
|
85
|
-
* **Android
|
|
77
|
+
* The SDK was unable to display the ad because the
|
|
78
|
+
* "Don't Keep Activities" developer setting is enabled.
|
|
79
|
+
* **Android only**.
|
|
86
80
|
*/
|
|
87
81
|
DONT_KEEP_ACTIVITIES_ENABLED = MAX_ERROR_CODE_DONT_KEEP_ACTIVITIES_ENABLED,
|
|
88
82
|
|
|
89
83
|
/**
|
|
90
|
-
*
|
|
91
|
-
* invalid ad unit identifier.
|
|
84
|
+
* The ad failed to load due to an invalid ad unit identifier.
|
|
92
85
|
*
|
|
93
|
-
* Possible
|
|
94
|
-
* 1.
|
|
95
|
-
* 2.
|
|
96
|
-
* 3.
|
|
97
|
-
* 4.
|
|
86
|
+
* Possible causes:
|
|
87
|
+
* 1. The ad unit ID is malformed or does not exist.
|
|
88
|
+
* 2. The ad unit is disabled.
|
|
89
|
+
* 3. The ad unit is not linked to the current app’s package name.
|
|
90
|
+
* 4. The ad unit was recently created (less than ~30–60 minutes ago).
|
|
98
91
|
*/
|
|
99
92
|
INVALID_AD_UNIT_ID = MAX_ERROR_CODE_INVALID_AD_UNIT_ID,
|
|
100
93
|
}
|
package/src/EventEmitter.ts
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages AppLovin MAX ad event listeners using a shared NativeEventEmitter.
|
|
3
|
+
* Ensures only one active subscription per event type at any given time.
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
import { NativeEventEmitter } from 'react-native';
|
|
2
7
|
import type { EventSubscription } from 'react-native';
|
|
3
8
|
import type { AdEventObject, AdEventListener } from './types/AdEvent';
|
|
4
9
|
import AppLovinMAX from './specs/NativeAppLovinMAXModule';
|
|
5
10
|
|
|
6
|
-
//
|
|
11
|
+
// Singleton event emitter for AppLovin MAX native events.
|
|
7
12
|
const emitter = new NativeEventEmitter(AppLovinMAX);
|
|
8
13
|
|
|
14
|
+
// Tracks active subscriptions by event type.
|
|
9
15
|
const subscriptions: Record<string, EventSubscription> = {};
|
|
10
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Subscribes to a specific ad event.
|
|
19
|
+
* If a listener already exists for the event, it will be replaced.
|
|
20
|
+
*
|
|
21
|
+
* @param event - The event name to listen for.
|
|
22
|
+
* @param handler - The callback to handle the event.
|
|
23
|
+
*/
|
|
11
24
|
export const addEventListener = <T extends AdEventObject>(event: string, handler: AdEventListener<T>): void => {
|
|
12
|
-
const subscription
|
|
25
|
+
const subscription = emitter.addListener(event, handler);
|
|
13
26
|
const currentSubscription = subscriptions[event];
|
|
14
27
|
if (currentSubscription) {
|
|
15
28
|
currentSubscription.remove();
|
|
@@ -17,6 +30,11 @@ export const addEventListener = <T extends AdEventObject>(event: string, handler
|
|
|
17
30
|
subscriptions[event] = subscription;
|
|
18
31
|
};
|
|
19
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Unsubscribes from a specific ad event, if a listener exists.
|
|
35
|
+
*
|
|
36
|
+
* @param event - The event name to unsubscribe from.
|
|
37
|
+
*/
|
|
20
38
|
export const removeEventListener = (event: string): void => {
|
|
21
39
|
const currentSubscription = subscriptions[event];
|
|
22
40
|
if (currentSubscription) {
|
package/src/Utils.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { LocalExtraParameterValue } from './types/AdProps';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Converts a record of string-based extra parameters into an array of `{ key, value }` objects.
|
|
5
|
+
* Used for sending extra parameters to the native SDK.
|
|
6
|
+
*
|
|
7
|
+
* @param input - An optional map of key-value string pairs (or null values).
|
|
8
|
+
* @returns An array of `{ key, value }` objects. Returns an empty array if input is undefined.
|
|
9
|
+
*/
|
|
10
|
+
export const makeExtraParametersArray = (input?: Record<string, string | null>): { key: string; value: string | null }[] => {
|
|
11
|
+
if (!input) return [];
|
|
12
|
+
|
|
13
|
+
return Object.entries(input).map(([key, value]) => ({ key, value }));
|
|
14
|
+
};
|
|
4
15
|
|
|
5
16
|
type LocalExtraParameterType = 'str' | 'bool';
|
|
6
17
|
|
|
@@ -9,6 +20,14 @@ type LocalExtraParameterValueMap = {
|
|
|
9
20
|
bool: boolean | null;
|
|
10
21
|
};
|
|
11
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Converts a map of local extra parameters into a filtered array of `{ key, value }` pairs.
|
|
25
|
+
* Only values matching the specified type (`'str'` or `'bool'`) are included.
|
|
26
|
+
*
|
|
27
|
+
* @param input - A record of local extra parameters (string, boolean, or null).
|
|
28
|
+
* @param type - The expected type of each value: `'str'` for strings, `'bool'` for booleans.
|
|
29
|
+
* @returns A filtered array of `{ key, value }` objects, cast to the specified type.
|
|
30
|
+
*/
|
|
12
31
|
export const makeLocalExtraParametersArray = <T extends LocalExtraParameterType>(
|
|
13
32
|
input: Record<string, LocalExtraParameterValue> | undefined,
|
|
14
33
|
type: T
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides the NativeAdView component, which manages loading and rendering of native ads using the
|
|
3
|
+
* AppLovin MAX SDK in React Native.
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
import * as React from 'react';
|
|
2
7
|
import { forwardRef, useContext, useImperativeHandle, useRef, useState, useEffect, useCallback } from 'react';
|
|
3
8
|
import { findNodeHandle, View } from 'react-native';
|
|
@@ -11,8 +16,7 @@ import type { NativeAdViewHandler, NativeAdViewProps } from '../types/NativeAdVi
|
|
|
11
16
|
import { makeExtraParametersArray, makeLocalExtraParametersArray } from '../Utils';
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
|
-
* The {@link NativeAdView} component
|
|
15
|
-
* renders it with the asset views:
|
|
19
|
+
* The {@link NativeAdView} component renders a native ad and binds it to asset views:
|
|
16
20
|
*
|
|
17
21
|
* - {@link IconView}
|
|
18
22
|
* - {@link TitleView}
|
|
@@ -22,19 +26,21 @@ import { makeExtraParametersArray, makeLocalExtraParametersArray } from '../Util
|
|
|
22
26
|
* - {@link MediaView}
|
|
23
27
|
* - {@link CallToActionView}
|
|
24
28
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
29
|
+
* Each asset view must be manually laid out and styled.
|
|
30
|
+
* The component automatically populates content once an ad is loaded.
|
|
31
|
+
* You can reload the ad using the component’s ref via `loadAd()`.
|
|
32
|
+
*
|
|
33
|
+
* **Note:** The AppLovin SDK must be initialized before using this component.
|
|
28
34
|
*
|
|
29
35
|
* ### Example:
|
|
30
|
-
* ```
|
|
36
|
+
* ```tsx
|
|
31
37
|
* <NativeAdView
|
|
32
38
|
* ref={nativeAdViewHandler}
|
|
33
39
|
* adUnitId={adUnitId}
|
|
34
40
|
* style={styles.nativead}
|
|
35
41
|
* onAdLoaded={(adInfo: AdInfo) => { ... }}
|
|
36
42
|
* >
|
|
37
|
-
* <View style={
|
|
43
|
+
* <View style={...}>
|
|
38
44
|
* <IconView style={styles.icon} />
|
|
39
45
|
* <TitleView style={styles.title} />
|
|
40
46
|
* <AdvertiserView style={styles.advertiser} />
|
|
@@ -46,6 +52,9 @@ import { makeExtraParametersArray, makeLocalExtraParametersArray } from '../Util
|
|
|
46
52
|
* </View>
|
|
47
53
|
* </NativeAdView>
|
|
48
54
|
* ```
|
|
55
|
+
*
|
|
56
|
+
* For a complete implementation example, see:
|
|
57
|
+
* https://github.com/AppLovin/AppLovin-MAX-React-Native/blob/master/example/src/NativeAdViewExample.tsx
|
|
49
58
|
*/
|
|
50
59
|
export const NativeAdView = forwardRef<NativeAdViewHandler, NativeAdViewProps & ViewProps>(function NativeAdView(props, ref) {
|
|
51
60
|
const [isInitialized, setIsInitialized] = useState<boolean>(false);
|
|
@@ -72,21 +81,13 @@ export const NativeAdView = forwardRef<NativeAdViewHandler, NativeAdViewProps &
|
|
|
72
81
|
);
|
|
73
82
|
});
|
|
74
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Extracts native ad info from a synthetic event and invokes the provided callback, if any.
|
|
86
|
+
* Ensures optional native ad fields have fallback defaults.
|
|
87
|
+
*/
|
|
75
88
|
const handleNativeAdViewEvent = <T extends AdInfoEvent | AdLoadFailedEvent>(event: NativeSyntheticEvent<T>, callback?: (adInfo: T) => void) => {
|
|
76
89
|
if (!callback) return;
|
|
77
|
-
|
|
78
|
-
let adInfo: any = { ...event.nativeEvent };
|
|
79
|
-
|
|
80
|
-
if ('nativeAd' in event.nativeEvent) {
|
|
81
|
-
adInfo.nativeAd = {
|
|
82
|
-
...event.nativeEvent.nativeAd,
|
|
83
|
-
isIconImageAvailable: event.nativeEvent.nativeAd?.isIconImageAvailable ?? false,
|
|
84
|
-
isOptionsViewAvailable: event.nativeEvent.nativeAd?.isOptionsViewAvailable ?? false,
|
|
85
|
-
isMediaViewAvailable: event.nativeEvent.nativeAd?.isMediaViewAvailable ?? false,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
callback(adInfo);
|
|
90
|
+
callback(event.nativeEvent);
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
const NativeAdViewImpl = forwardRef<NativeAdViewHandler, NativeAdViewProps & ViewProps>(function NativeAdViewImpl(
|
|
@@ -98,13 +99,16 @@ const NativeAdViewImpl = forwardRef<NativeAdViewHandler, NativeAdViewProps & Vie
|
|
|
98
99
|
|
|
99
100
|
const nativeAdViewRef = useRef<React.ElementRef<typeof NativeAdViewComponent> | undefined>();
|
|
100
101
|
|
|
101
|
-
//
|
|
102
|
+
// Triggers a native ad load via the native command
|
|
102
103
|
const loadAd = useCallback(() => {
|
|
103
104
|
nativeAdViewRef.current && Commands.loadAd(nativeAdViewRef.current);
|
|
104
105
|
}, []);
|
|
105
106
|
|
|
106
107
|
useImperativeHandle(ref, () => ({ loadAd }), [loadAd]);
|
|
107
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Updates the native asset view binding for a given view type (e.g., TitleView, MediaView).
|
|
111
|
+
*/
|
|
108
112
|
const updateAssetView = useCallback((assetViewRef: React.RefObject<View>, type: string) => {
|
|
109
113
|
if (!nativeAdViewRef.current || !assetViewRef.current) return;
|
|
110
114
|
|
|
@@ -114,6 +118,12 @@ const NativeAdViewImpl = forwardRef<NativeAdViewHandler, NativeAdViewProps & Vie
|
|
|
114
118
|
}
|
|
115
119
|
}, []);
|
|
116
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Handles native ad load event:
|
|
123
|
+
* - Updates context with the new native ad data
|
|
124
|
+
* - Notifies native module of updated asset view mappings
|
|
125
|
+
* - Triggers native rendering after all asset views are registered
|
|
126
|
+
*/
|
|
117
127
|
const onAdLoadedEvent = useCallback(
|
|
118
128
|
(event: NativeSyntheticEvent<AdInfoEvent>) => {
|
|
119
129
|
const nativeAdImpl = event.nativeEvent.nativeAdImpl;
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides pre-styled React Native components for each native ad asset view:
|
|
3
|
+
*
|
|
4
|
+
* - TitleView
|
|
5
|
+
* - AdvertiserView
|
|
6
|
+
* - BodyView
|
|
7
|
+
* - CallToActionView
|
|
8
|
+
* - IconView
|
|
9
|
+
* - OptionsView
|
|
10
|
+
* - MediaView
|
|
11
|
+
* - StarRatingView
|
|
12
|
+
*
|
|
13
|
+
* Each component pulls ad content and view refs from NativeAdView context,
|
|
14
|
+
* and must be rendered inside a {@link NativeAdView}.
|
|
15
|
+
*/
|
|
16
|
+
|
|
1
17
|
import * as React from 'react';
|
|
2
18
|
import { useContext, useMemo } from 'react';
|
|
3
19
|
import { Text, Image, View, TouchableOpacity, StyleSheet, Platform } from 'react-native';
|
|
4
|
-
import type { ViewProps, ImageProps,
|
|
20
|
+
import type { ViewProps, ImageProps, TextProps } from 'react-native';
|
|
5
21
|
import { NativeAdViewContext } from './NativeAdViewProvider';
|
|
6
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Renders the native ad’s title.
|
|
25
|
+
*/
|
|
7
26
|
export const TitleView = (props: TextProps) => {
|
|
8
27
|
const { titleRef, nativeAd } = useContext(NativeAdViewContext);
|
|
9
28
|
return (
|
|
@@ -13,6 +32,9 @@ export const TitleView = (props: TextProps) => {
|
|
|
13
32
|
);
|
|
14
33
|
};
|
|
15
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Renders the advertiser name.
|
|
37
|
+
*/
|
|
16
38
|
export const AdvertiserView = (props: TextProps) => {
|
|
17
39
|
const { advertiserRef, nativeAd } = useContext(NativeAdViewContext);
|
|
18
40
|
return (
|
|
@@ -22,6 +44,9 @@ export const AdvertiserView = (props: TextProps) => {
|
|
|
22
44
|
);
|
|
23
45
|
};
|
|
24
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Renders the ad’s body text (description).
|
|
49
|
+
*/
|
|
25
50
|
export const BodyView = (props: TextProps) => {
|
|
26
51
|
const { bodyRef, nativeAd } = useContext(NativeAdViewContext);
|
|
27
52
|
return (
|
|
@@ -31,31 +56,39 @@ export const BodyView = (props: TextProps) => {
|
|
|
31
56
|
);
|
|
32
57
|
};
|
|
33
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Renders the call-to-action label.
|
|
61
|
+
* On iOS, wraps the text with a TouchableOpacity for better click behavior.
|
|
62
|
+
*/
|
|
34
63
|
export const CallToActionView = (props: TextProps) => {
|
|
35
64
|
const { callToActionRef, nativeAd } = useContext(NativeAdViewContext);
|
|
36
|
-
|
|
65
|
+
|
|
37
66
|
if (Platform.OS === 'android') {
|
|
38
67
|
return (
|
|
39
68
|
<Text {...props} ref={callToActionRef}>
|
|
40
69
|
{nativeAd.callToAction ?? ''}
|
|
41
70
|
</Text>
|
|
42
71
|
);
|
|
43
|
-
} else {
|
|
44
|
-
return (
|
|
45
|
-
<TouchableOpacity>
|
|
46
|
-
<Text {...props} ref={callToActionRef}>
|
|
47
|
-
{nativeAd.callToAction ?? ''}
|
|
48
|
-
</Text>
|
|
49
|
-
</TouchableOpacity>
|
|
50
|
-
);
|
|
51
72
|
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<TouchableOpacity>
|
|
76
|
+
<Text {...props} ref={callToActionRef}>
|
|
77
|
+
{nativeAd.callToAction ?? ''}
|
|
78
|
+
</Text>
|
|
79
|
+
</TouchableOpacity>
|
|
80
|
+
);
|
|
52
81
|
};
|
|
53
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Renders the icon image for the native ad.
|
|
85
|
+
* Falls back to a blank placeholder if not available.
|
|
86
|
+
*/
|
|
54
87
|
export const IconView = (props: Omit<ImageProps, 'source'>) => {
|
|
55
88
|
const { imageRef, nativeAd } = useContext(NativeAdViewContext);
|
|
56
89
|
const defaultIcon = require('./img/blank_icon.png');
|
|
57
90
|
|
|
58
|
-
const imageSource = (() => {
|
|
91
|
+
const imageSource = useMemo(() => {
|
|
59
92
|
if (nativeAd?.url) {
|
|
60
93
|
return { uri: nativeAd.url };
|
|
61
94
|
}
|
|
@@ -63,60 +96,86 @@ export const IconView = (props: Omit<ImageProps, 'source'>) => {
|
|
|
63
96
|
return { uri: `data:image/jpeg;base64,${nativeAd.imageSource}` };
|
|
64
97
|
}
|
|
65
98
|
return defaultIcon;
|
|
66
|
-
})
|
|
99
|
+
}, [nativeAd.url, nativeAd.imageSource, defaultIcon]);
|
|
67
100
|
|
|
68
101
|
return <Image {...props} ref={imageRef} source={imageSource} />;
|
|
69
102
|
};
|
|
70
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Renders the native ad’s options view.
|
|
106
|
+
*/
|
|
71
107
|
export const OptionsView = (props: ViewProps) => {
|
|
72
108
|
const { optionViewRef } = useContext(NativeAdViewContext);
|
|
73
109
|
return <View {...props} ref={optionViewRef} />;
|
|
74
110
|
};
|
|
75
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Renders the native ad’s media content.
|
|
114
|
+
*/
|
|
76
115
|
export const MediaView = (props: ViewProps) => {
|
|
77
116
|
const { mediaViewRef } = useContext(NativeAdViewContext);
|
|
78
117
|
return <View {...props} ref={mediaViewRef} />;
|
|
79
118
|
};
|
|
80
119
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Props for the {@link StarRatingView} component, which displays a star rating
|
|
122
|
+
* using Unicode stars (★ and ☆) styled with color, shadow, and size.
|
|
123
|
+
*/
|
|
124
|
+
type StarRatingViewProps = ViewProps & {
|
|
125
|
+
/**
|
|
126
|
+
* The color used for filled (active) stars.
|
|
127
|
+
* Defaults to gold (#ffe234).
|
|
128
|
+
*/
|
|
129
|
+
color?: string;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The color used for empty (inactive) stars.
|
|
133
|
+
* Defaults to light gray (#dedede).
|
|
134
|
+
*/
|
|
135
|
+
shadowColor?: string;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The size of each star, which also determines their visual size.
|
|
139
|
+
* Defaults to 10.
|
|
140
|
+
*/
|
|
141
|
+
size?: number;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Renders the star rating of the ad, using Unicode stars (★ and ☆).
|
|
146
|
+
* Filled stars are rendered over hollow stars using a clipped view.
|
|
147
|
+
*/
|
|
148
|
+
export const StarRatingView = ({ color = '#ffe234', shadowColor = '#dedede', size = 10, style }: StarRatingViewProps) => {
|
|
87
149
|
const { nativeAd } = useContext(NativeAdViewContext);
|
|
150
|
+
const maxStarCount = 5;
|
|
151
|
+
|
|
152
|
+
const containerStyle = useMemo(() => StyleSheet.flatten([style, styles.starRatingContainer]), [style]);
|
|
88
153
|
|
|
89
|
-
// Memoize the star rendering process
|
|
90
154
|
const stars = useMemo(() => {
|
|
91
|
-
|
|
92
|
-
return Array.from({ length: maxStarCount }).map((_, index) => (
|
|
93
|
-
<Text key={index} style={{ fontSize: starSize }}>
|
|
94
|
-
{' '}
|
|
95
|
-
</Text>
|
|
96
|
-
));
|
|
97
|
-
}
|
|
155
|
+
const starRating = Math.max(0, Math.min(maxStarCount, nativeAd.starRating ?? 0));
|
|
98
156
|
|
|
99
157
|
return Array.from({ length: maxStarCount }).map((_, index) => {
|
|
100
|
-
const
|
|
101
|
-
const width = (starRating - index) *
|
|
158
|
+
const isFull = starRating > index;
|
|
159
|
+
const width = Math.min(size, Math.max(0, (starRating - index) * size));
|
|
160
|
+
|
|
102
161
|
return (
|
|
103
162
|
<View key={index}>
|
|
104
|
-
<Text style={{ fontSize:
|
|
105
|
-
{
|
|
106
|
-
<View style={[{ width
|
|
107
|
-
<Text style={{ fontSize:
|
|
163
|
+
<Text style={{ fontSize: size, color: isFull ? color : shadowColor }}>{String.fromCodePoint(0x2606)}</Text>
|
|
164
|
+
{isFull && (
|
|
165
|
+
<View style={[{ width }, styles.starRating]}>
|
|
166
|
+
<Text style={{ fontSize: size, color }}>{String.fromCodePoint(0x2605)}</Text>
|
|
108
167
|
</View>
|
|
109
168
|
)}
|
|
110
169
|
</View>
|
|
111
170
|
);
|
|
112
171
|
});
|
|
113
|
-
}, [nativeAd.starRating,
|
|
172
|
+
}, [nativeAd.starRating, color, shadowColor, size]);
|
|
114
173
|
|
|
115
|
-
|
|
116
|
-
<View
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
174
|
+
if (!nativeAd.starRating) {
|
|
175
|
+
return <View style={containerStyle} />;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return <View style={containerStyle}>{stars}</View>;
|
|
120
179
|
};
|
|
121
180
|
|
|
122
181
|
const styles = StyleSheet.create({
|