react-native-liftoffads 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/NitroLiftoffAds.podspec +26 -0
- package/README.md +61 -0
- package/android/CMakeLists.txt +20 -0
- package/android/build.gradle +132 -0
- package/android/consumer-rules.pro +2 -0
- package/android/fix-prefab.gradle +46 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/cpp-adapter.cpp +7 -0
- package/android/src/main/java/com/margelo/nitro/liftoffads/HybridLiftoffAds.kt +121 -0
- package/android/src/main/java/com/margelo/nitro/liftoffads/HybridLiftoffInterstitialAd.kt +96 -0
- package/android/src/main/java/com/margelo/nitro/liftoffads/HybridLiftoffRewardedAd.kt +104 -0
- package/android/src/main/java/com/margelo/nitro/liftoffads/LiftoffAdEventEmitter.kt +51 -0
- package/android/src/main/java/com/margelo/nitro/liftoffads/LiftoffAndroidUtils.kt +54 -0
- package/android/src/main/java/com/margelo/nitro/liftoffads/NitroLiftoffAdsPackage.java +27 -0
- package/ios/HybridLiftoffAds.swift +113 -0
- package/ios/HybridLiftoffInterstitialAd.swift +98 -0
- package/ios/HybridLiftoffRewardedAd.swift +100 -0
- package/ios/LiftoffSupport.swift +106 -0
- package/lib/module/index.js +169 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.test.js +205 -0
- package/lib/module/index.test.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/specs/LiftoffAds.nitro.js +4 -0
- package/lib/module/specs/LiftoffAds.nitro.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/index.d.ts +72 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/index.test.d.ts +2 -0
- package/lib/typescript/src/index.test.d.ts.map +1 -0
- package/lib/typescript/src/specs/LiftoffAds.nitro.d.ts +46 -0
- package/lib/typescript/src/specs/LiftoffAds.nitro.d.ts.map +1 -0
- package/nitro.json +18 -0
- package/nitrogen/generated/android/NitroLiftoffAds+autolinking.cmake +85 -0
- package/nitrogen/generated/android/NitroLiftoffAds+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroLiftoffAdsOnLoad.cpp +50 -0
- package/nitrogen/generated/android/NitroLiftoffAdsOnLoad.hpp +25 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_LiftoffAdEventPayload_.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridLiftoffAdsSpec.cpp +88 -0
- package/nitrogen/generated/android/c++/JHybridLiftoffAdsSpec.hpp +69 -0
- package/nitrogen/generated/android/c++/JHybridLiftoffInterstitialAdSpec.cpp +89 -0
- package/nitrogen/generated/android/c++/JHybridLiftoffInterstitialAdSpec.hpp +68 -0
- package/nitrogen/generated/android/c++/JHybridLiftoffRewardedAdSpec.cpp +93 -0
- package/nitrogen/generated/android/c++/JHybridLiftoffRewardedAdSpec.hpp +69 -0
- package/nitrogen/generated/android/c++/JLiftoffAdEventPayload.hpp +58 -0
- package/nitrogen/generated/android/c++/JLiftoffAdEventType.hpp +77 -0
- package/nitrogen/generated/android/c++/JLiftoffAdShowOptions.hpp +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/Func_void_std__optional_LiftoffAdEventPayload_.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/HybridLiftoffAdsSpec.kt +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/HybridLiftoffInterstitialAdSpec.kt +73 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/HybridLiftoffRewardedAdSpec.kt +77 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/LiftoffAdEventPayload.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/LiftoffAdEventType.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/LiftoffAdShowOptions.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/liftoffads/NitroLiftoffAdsOnLoad.kt +35 -0
- package/nitrogen/generated/ios/NitroLiftoffAds+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroLiftoffAds-Swift-Cxx-Bridge.cpp +90 -0
- package/nitrogen/generated/ios/NitroLiftoffAds-Swift-Cxx-Bridge.hpp +285 -0
- package/nitrogen/generated/ios/NitroLiftoffAds-Swift-Cxx-Umbrella.hpp +66 -0
- package/nitrogen/generated/ios/NitroLiftoffAdsAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroLiftoffAdsAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridLiftoffAdsSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridLiftoffAdsSpecSwift.hpp +114 -0
- package/nitrogen/generated/ios/c++/HybridLiftoffInterstitialAdSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridLiftoffInterstitialAdSpecSwift.hpp +110 -0
- package/nitrogen/generated/ios/c++/HybridLiftoffRewardedAdSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridLiftoffRewardedAdSpecSwift.hpp +116 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_LiftoffAdEventPayload_.swift +54 -0
- package/nitrogen/generated/ios/swift/HybridLiftoffAdsSpec.swift +54 -0
- package/nitrogen/generated/ios/swift/HybridLiftoffAdsSpec_cxx.swift +193 -0
- package/nitrogen/generated/ios/swift/HybridLiftoffInterstitialAdSpec.swift +53 -0
- package/nitrogen/generated/ios/swift/HybridLiftoffInterstitialAdSpec_cxx.swift +193 -0
- package/nitrogen/generated/ios/swift/HybridLiftoffRewardedAdSpec.swift +54 -0
- package/nitrogen/generated/ios/swift/HybridLiftoffRewardedAdSpec_cxx.swift +204 -0
- package/nitrogen/generated/ios/swift/LiftoffAdEventPayload.swift +77 -0
- package/nitrogen/generated/ios/swift/LiftoffAdEventType.swift +64 -0
- package/nitrogen/generated/ios/swift/LiftoffAdShowOptions.swift +47 -0
- package/nitrogen/generated/shared/c++/HybridLiftoffAdsSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridLiftoffAdsSpec.hpp +74 -0
- package/nitrogen/generated/shared/c++/HybridLiftoffInterstitialAdSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridLiftoffInterstitialAdSpec.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridLiftoffRewardedAdSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridLiftoffRewardedAdSpec.hpp +78 -0
- package/nitrogen/generated/shared/c++/LiftoffAdEventPayload.hpp +72 -0
- package/nitrogen/generated/shared/c++/LiftoffAdEventType.hpp +100 -0
- package/nitrogen/generated/shared/c++/LiftoffAdShowOptions.hpp +67 -0
- package/package.json +173 -0
- package/react-native.config.js +8 -0
- package/src/index.test.ts +257 -0
- package/src/index.ts +307 -0
- package/src/specs/LiftoffAds.nitro.ts +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 exzos
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "NitroLiftoffAds"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = "https://github.com/exzos28/react-native-liftoffads"
|
|
10
|
+
s.license = { :type => "MIT" }
|
|
11
|
+
s.authors = { "exzos" => "oleksandr.kurinnyi.work@gmail.com" }
|
|
12
|
+
s.platforms = { :ios => "15.1" }
|
|
13
|
+
s.source = { :path => "." }
|
|
14
|
+
|
|
15
|
+
s.source_files = ["ios/**/*.{swift,m,mm}"]
|
|
16
|
+
|
|
17
|
+
load "nitrogen/generated/ios/NitroLiftoffAds+autolinking.rb"
|
|
18
|
+
add_nitrogen_files(s)
|
|
19
|
+
|
|
20
|
+
s.dependency "React-Core"
|
|
21
|
+
s.dependency "React-jsi"
|
|
22
|
+
s.dependency "React-callinvoker"
|
|
23
|
+
s.dependency "VungleAds", "7.7.5"
|
|
24
|
+
|
|
25
|
+
install_modules_dependencies(s)
|
|
26
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# react-native-liftoffads
|
|
2
|
+
|
|
3
|
+
[Nitro Modules](https://nitro.margelo.com/) bridge for Liftoff Monetize
|
|
4
|
+
(Vungle) interstitial and rewarded ads.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install react-native-liftoffads react-native-nitro-modules
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import MobileAds, {
|
|
16
|
+
AdEventType,
|
|
17
|
+
InterstitialAd,
|
|
18
|
+
RewardedAd,
|
|
19
|
+
RewardedAdEventType,
|
|
20
|
+
} from 'react-native-liftoffads';
|
|
21
|
+
|
|
22
|
+
await MobileAds().initialize('YOUR_LIFTOFF_APP_ID');
|
|
23
|
+
MobileAds().setGDPRConsent(true, '1.0');
|
|
24
|
+
MobileAds().setCCPAConsent(true);
|
|
25
|
+
MobileAds().setCOPPA(false);
|
|
26
|
+
|
|
27
|
+
const interstitial = InterstitialAd.createForAdRequest('YOUR_PLACEMENT_ID');
|
|
28
|
+
interstitial.addAdEventListener(AdEventType.LOADED, () => {
|
|
29
|
+
interstitial.show({immersiveModeEnabled: true});
|
|
30
|
+
});
|
|
31
|
+
interstitial.addAdEventListener(AdEventType.CLOSED, () => {
|
|
32
|
+
interstitial.load(); // reuse the same instance for the next impression
|
|
33
|
+
});
|
|
34
|
+
interstitial.load();
|
|
35
|
+
|
|
36
|
+
const rewarded = RewardedAd.createForAdRequest('YOUR_PLACEMENT_ID');
|
|
37
|
+
rewarded.setUserId('your-user-id'); // optional, for SSV
|
|
38
|
+
rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => rewarded.show());
|
|
39
|
+
rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD, () => {
|
|
40
|
+
// grant the reward
|
|
41
|
+
});
|
|
42
|
+
rewarded.load();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
- Ad instances are meant to be reused — call `load()` again on the same
|
|
48
|
+
`InterstitialAd`/`RewardedAd` after `CLOSED` instead of creating a new one.
|
|
49
|
+
- Liftoff doesn't report reward type/amount, so `LOADED`/`EARNED_REWARD`
|
|
50
|
+
payloads are always `undefined` — treat them as signals only.
|
|
51
|
+
- Use `RewardedAdEventType.LOADED`, not `AdEventType.LOADED`, on a
|
|
52
|
+
`RewardedAd`.
|
|
53
|
+
- No built-in consent UI (no UMP equivalent) — plug your own and forward the
|
|
54
|
+
result via `setGDPRConsent`/`setCCPAConsent`/`setCOPPA`.
|
|
55
|
+
|
|
56
|
+
See [`src/specs/LiftoffAds.nitro.ts`](src/specs/LiftoffAds.nitro.ts) for the
|
|
57
|
+
full native interface and [`example`](example) for a runnable demo.
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
project(NitroLiftoffAds)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set(PACKAGE_NAME NitroLiftoffAds)
|
|
5
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
7
|
+
|
|
8
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
9
|
+
src/main/cpp/cpp-adapter.cpp
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroLiftoffAds+autolinking.cmake)
|
|
13
|
+
|
|
14
|
+
find_library(LOG_LIB log)
|
|
15
|
+
|
|
16
|
+
target_link_libraries(
|
|
17
|
+
${PACKAGE_NAME}
|
|
18
|
+
${LOG_LIB}
|
|
19
|
+
android
|
|
20
|
+
)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.12.1"
|
|
9
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def reactNativeArchitectures() {
|
|
14
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
15
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
def isNewArchitectureEnabled() {
|
|
19
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
apply plugin: "com.android.library"
|
|
23
|
+
apply plugin: "org.jetbrains.kotlin.android"
|
|
24
|
+
|
|
25
|
+
def nitroAutolinkingFile = file("../nitrogen/generated/android/NitroLiftoffAds+autolinking.gradle")
|
|
26
|
+
if (nitroAutolinkingFile.exists()) {
|
|
27
|
+
apply from: nitroAutolinkingFile
|
|
28
|
+
}
|
|
29
|
+
apply from: "./fix-prefab.gradle"
|
|
30
|
+
|
|
31
|
+
def getExtOrDefault(name) {
|
|
32
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroLiftoffAds_" + name]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def getExtOrIntegerDefault(name) {
|
|
36
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroLiftoffAds_" + name]).toInteger()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
android {
|
|
40
|
+
namespace "com.margelo.nitro.liftoffads"
|
|
41
|
+
|
|
42
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
43
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
44
|
+
|
|
45
|
+
defaultConfig {
|
|
46
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
47
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
48
|
+
consumerProguardFiles "consumer-rules.pro"
|
|
49
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
50
|
+
|
|
51
|
+
externalNativeBuild {
|
|
52
|
+
cmake {
|
|
53
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
54
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
55
|
+
abiFilters (*reactNativeArchitectures())
|
|
56
|
+
|
|
57
|
+
buildTypes {
|
|
58
|
+
debug {
|
|
59
|
+
cppFlags "-O1 -g"
|
|
60
|
+
}
|
|
61
|
+
release {
|
|
62
|
+
cppFlags "-O2"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
externalNativeBuild {
|
|
70
|
+
cmake {
|
|
71
|
+
path "CMakeLists.txt"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
packagingOptions {
|
|
76
|
+
excludes = [
|
|
77
|
+
"META-INF",
|
|
78
|
+
"META-INF/**",
|
|
79
|
+
"**/libc++_shared.so",
|
|
80
|
+
"**/libfbjni.so",
|
|
81
|
+
"**/libjsi.so",
|
|
82
|
+
"**/libfolly_json.so",
|
|
83
|
+
"**/libfolly_runtime.so",
|
|
84
|
+
"**/libglog.so",
|
|
85
|
+
"**/libhermes.so",
|
|
86
|
+
"**/libreactnative.so",
|
|
87
|
+
"**/libreactnativejni.so"
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
buildFeatures {
|
|
92
|
+
buildConfig true
|
|
93
|
+
prefab true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
buildTypes {
|
|
97
|
+
release {
|
|
98
|
+
minifyEnabled false
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
lintOptions {
|
|
103
|
+
disable "GradleCompatible"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
compileOptions {
|
|
107
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
108
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
kotlinOptions {
|
|
112
|
+
jvmTarget = "17"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
repositories {
|
|
118
|
+
google()
|
|
119
|
+
mavenCentral()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
dependencies {
|
|
123
|
+
implementation "com.facebook.react:react-android"
|
|
124
|
+
implementation project(":react-native-nitro-modules")
|
|
125
|
+
|
|
126
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0"
|
|
127
|
+
implementation "com.vungle:vungle-ads:7.7.7"
|
|
128
|
+
implementation "com.google.android.gms:play-services-tasks:18.2.1"
|
|
129
|
+
implementation "com.google.android.gms:play-services-appset:16.1.0"
|
|
130
|
+
implementation "com.google.android.gms:play-services-basement:18.6.0"
|
|
131
|
+
implementation "com.google.android.gms:play-services-ads-identifier:18.2.0"
|
|
132
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
tasks.configureEach { task ->
|
|
2
|
+
def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/
|
|
3
|
+
def matcher = task.name =~ prefabConfigurePattern
|
|
4
|
+
if (matcher.matches()) {
|
|
5
|
+
def variantName = matcher[0][1]
|
|
6
|
+
task.outputs.upToDateWhen { false }
|
|
7
|
+
task.dependsOn("externalNativeBuild${variantName}")
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
afterEvaluate {
|
|
12
|
+
def abis = reactNativeArchitectures()
|
|
13
|
+
rootProject.allprojects.each { proj ->
|
|
14
|
+
if (proj === rootProject) return
|
|
15
|
+
|
|
16
|
+
def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->
|
|
17
|
+
config.dependencies.any { dep ->
|
|
18
|
+
dep.group == project.group && dep.name == project.name
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (!dependsOnThisLib && proj != project) return
|
|
22
|
+
|
|
23
|
+
if (!proj.plugins.hasPlugin("com.android.application") &&
|
|
24
|
+
!proj.plugins.hasPlugin("com.android.library")) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def variants = proj.android.hasProperty("applicationVariants") ?
|
|
29
|
+
proj.android.applicationVariants : proj.android.libraryVariants
|
|
30
|
+
variants.all { variant ->
|
|
31
|
+
def variantName = variant.name
|
|
32
|
+
abis.each { abi ->
|
|
33
|
+
def searchDir = new File(proj.projectDir, ".cxx/${variantName}")
|
|
34
|
+
if (!searchDir.exists()) return
|
|
35
|
+
def matches = []
|
|
36
|
+
searchDir.eachDir { randomDir ->
|
|
37
|
+
def prefabFile = new File(randomDir, "${abi}/prefab_config.json")
|
|
38
|
+
if (prefabFile.exists()) matches << prefabFile
|
|
39
|
+
}
|
|
40
|
+
matches.each { prefabConfig ->
|
|
41
|
+
prefabConfig.setLastModified(System.currentTimeMillis())
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
package com.margelo.nitro.liftoffads
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Keep
|
|
4
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.margelo.nitro.NitroModules
|
|
7
|
+
import com.margelo.nitro.core.Promise
|
|
8
|
+
import com.vungle.ads.InitializationListener
|
|
9
|
+
import com.vungle.ads.VungleAds
|
|
10
|
+
import com.vungle.ads.VungleError
|
|
11
|
+
import com.vungle.ads.VunglePrivacySettings
|
|
12
|
+
import kotlinx.coroutines.CompletableDeferred
|
|
13
|
+
import kotlinx.coroutines.Dispatchers
|
|
14
|
+
import kotlinx.coroutines.withContext
|
|
15
|
+
|
|
16
|
+
@DoNotStrip
|
|
17
|
+
@Keep
|
|
18
|
+
class HybridLiftoffAds : HybridLiftoffAdsSpec() {
|
|
19
|
+
private val context: ReactApplicationContext by lazy {
|
|
20
|
+
NitroModules.applicationContext as? ReactApplicationContext
|
|
21
|
+
?: error("Liftoff Ads requires a ReactApplicationContext")
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private val stateLock = Any()
|
|
25
|
+
private var initializedAppId: String? = null
|
|
26
|
+
private var initializingAppId: String? = null
|
|
27
|
+
private var initialization: CompletableDeferred<Unit>? = null
|
|
28
|
+
|
|
29
|
+
override fun initialize(appId: String): Promise<Unit> = Promise.async {
|
|
30
|
+
require(appId.isNotBlank()) { "Liftoff app ID is empty" }
|
|
31
|
+
|
|
32
|
+
val alreadyInitialized = synchronized(stateLock) {
|
|
33
|
+
if (VungleAds.isInitialized()) {
|
|
34
|
+
val existing = initializedAppId
|
|
35
|
+
if (existing != null && existing != appId) {
|
|
36
|
+
error("Liftoff SDK was already initialized with another app ID")
|
|
37
|
+
}
|
|
38
|
+
initializedAppId = appId
|
|
39
|
+
true
|
|
40
|
+
} else {
|
|
41
|
+
false
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (alreadyInitialized) return@async
|
|
45
|
+
|
|
46
|
+
val (deferred, shouldStart) = synchronized(stateLock) {
|
|
47
|
+
val current = initialization
|
|
48
|
+
if (current != null) {
|
|
49
|
+
if (initializingAppId != appId) {
|
|
50
|
+
error("Liftoff SDK is being initialized with another app ID")
|
|
51
|
+
}
|
|
52
|
+
current to false
|
|
53
|
+
} else {
|
|
54
|
+
CompletableDeferred<Unit>().also {
|
|
55
|
+
initialization = it
|
|
56
|
+
initializingAppId = appId
|
|
57
|
+
} to true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (shouldStart) {
|
|
62
|
+
withContext(Dispatchers.Main) {
|
|
63
|
+
VungleAds.init(
|
|
64
|
+
context.applicationContext,
|
|
65
|
+
appId,
|
|
66
|
+
object : InitializationListener {
|
|
67
|
+
override fun onSuccess() {
|
|
68
|
+
synchronized(stateLock) {
|
|
69
|
+
initializedAppId = appId
|
|
70
|
+
initialization = null
|
|
71
|
+
initializingAppId = null
|
|
72
|
+
}
|
|
73
|
+
deferred.complete(Unit)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override fun onError(vungleError: VungleError) {
|
|
77
|
+
synchronized(stateLock) {
|
|
78
|
+
if (initialization === deferred) initialization = null
|
|
79
|
+
initializingAppId = null
|
|
80
|
+
}
|
|
81
|
+
deferred.completeExceptionally(
|
|
82
|
+
liftoffException("initialize", vungleError),
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
deferred.await()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override fun setGDPRConsent(optIn: Boolean, consentMessageVersion: String) {
|
|
94
|
+
VunglePrivacySettings.setGDPRStatus(optIn, consentMessageVersion)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
override fun setCCPAConsent(optIn: Boolean) {
|
|
98
|
+
VunglePrivacySettings.setCCPAStatus(optIn)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
override fun setCOPPA(isUserCoppa: Boolean) {
|
|
102
|
+
VunglePrivacySettings.setCOPPAStatus(isUserCoppa)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
override fun createInterstitialAd(
|
|
106
|
+
placementId: String,
|
|
107
|
+
): HybridLiftoffInterstitialAdSpec {
|
|
108
|
+
requireInitialized(placementId)
|
|
109
|
+
return HybridLiftoffInterstitialAd(context, placementId)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override fun createRewardedAd(placementId: String): HybridLiftoffRewardedAdSpec {
|
|
113
|
+
requireInitialized(placementId)
|
|
114
|
+
return HybridLiftoffRewardedAd(context, placementId)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private fun requireInitialized(placementId: String) {
|
|
118
|
+
require(VungleAds.isInitialized()) { "Liftoff SDK is not initialized" }
|
|
119
|
+
require(placementId.isNotBlank()) { "Liftoff placement ID is empty" }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
package com.margelo.nitro.liftoffads
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Keep
|
|
4
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.margelo.nitro.core.Promise
|
|
7
|
+
import com.vungle.ads.AdConfig
|
|
8
|
+
import com.vungle.ads.BaseAd
|
|
9
|
+
import com.vungle.ads.InterstitialAd
|
|
10
|
+
import com.vungle.ads.InterstitialAdListener
|
|
11
|
+
import com.vungle.ads.VungleError
|
|
12
|
+
import kotlinx.coroutines.Dispatchers
|
|
13
|
+
import kotlinx.coroutines.withContext
|
|
14
|
+
|
|
15
|
+
@DoNotStrip
|
|
16
|
+
@Keep
|
|
17
|
+
class HybridLiftoffInterstitialAd(
|
|
18
|
+
private val context: ReactApplicationContext,
|
|
19
|
+
placementId: String,
|
|
20
|
+
) : HybridLiftoffInterstitialAdSpec(), InterstitialAdListener {
|
|
21
|
+
private val events = LiftoffAdEventEmitter()
|
|
22
|
+
private val immersiveMode = ImmersiveModeController()
|
|
23
|
+
private val ad = InterstitialAd(context, placementId, AdConfig())
|
|
24
|
+
|
|
25
|
+
init {
|
|
26
|
+
ad.adListener = this
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun load() {
|
|
30
|
+
context.runOnUiQueueThread { ad.load() }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun show(options: LiftoffAdShowOptions?): Promise<Unit> = Promise.async {
|
|
34
|
+
try {
|
|
35
|
+
withContext(Dispatchers.Main) {
|
|
36
|
+
val activity = context.requireCurrentActivity()
|
|
37
|
+
if (!ad.canPlayAd()) error("Liftoff interstitial ad is not ready")
|
|
38
|
+
if (options?.immersiveModeEnabled == true) immersiveMode.enable(activity)
|
|
39
|
+
ad.play(activity)
|
|
40
|
+
}
|
|
41
|
+
} catch (error: Throwable) {
|
|
42
|
+
immersiveMode.restore()
|
|
43
|
+
events.emit(LiftoffAdEventType.ERROR, error.toLiftoffEventPayload())
|
|
44
|
+
throw error
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override fun addAdEventListener(
|
|
49
|
+
eventType: LiftoffAdEventType,
|
|
50
|
+
listener: (payload: LiftoffAdEventPayload?) -> Unit,
|
|
51
|
+
) = events.add(eventType, listener)
|
|
52
|
+
|
|
53
|
+
override fun removeAdEventListener(subscriptionId: Double) {
|
|
54
|
+
events.remove(subscriptionId)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override fun removeAllListeners() {
|
|
58
|
+
events.removeAll()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
override fun onAdLoaded(baseAd: BaseAd) {
|
|
62
|
+
events.emit(LiftoffAdEventType.LOADED)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override fun onAdStart(baseAd: BaseAd) {
|
|
66
|
+
events.emit(LiftoffAdEventType.OPENED)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override fun onAdImpression(baseAd: BaseAd) = Unit
|
|
70
|
+
|
|
71
|
+
override fun onAdClicked(baseAd: BaseAd) {
|
|
72
|
+
events.emit(LiftoffAdEventType.CLICKED)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override fun onAdLeftApplication(baseAd: BaseAd) = Unit
|
|
76
|
+
|
|
77
|
+
override fun onAdEnd(baseAd: BaseAd) {
|
|
78
|
+
immersiveMode.restore()
|
|
79
|
+
events.emit(LiftoffAdEventType.CLOSED)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
override fun onAdFailedToLoad(baseAd: BaseAd, adError: VungleError) {
|
|
83
|
+
events.emit(
|
|
84
|
+
LiftoffAdEventType.ERROR,
|
|
85
|
+
liftoffException("load", adError).toLiftoffEventPayload(),
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override fun onAdFailedToPlay(baseAd: BaseAd, adError: VungleError) {
|
|
90
|
+
immersiveMode.restore()
|
|
91
|
+
events.emit(
|
|
92
|
+
LiftoffAdEventType.ERROR,
|
|
93
|
+
liftoffException("show", adError).toLiftoffEventPayload(),
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
package com.margelo.nitro.liftoffads
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Keep
|
|
4
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.margelo.nitro.core.Promise
|
|
7
|
+
import com.vungle.ads.AdConfig
|
|
8
|
+
import com.vungle.ads.BaseAd
|
|
9
|
+
import com.vungle.ads.RewardedAd
|
|
10
|
+
import com.vungle.ads.RewardedAdListener
|
|
11
|
+
import com.vungle.ads.VungleError
|
|
12
|
+
import kotlinx.coroutines.Dispatchers
|
|
13
|
+
import kotlinx.coroutines.withContext
|
|
14
|
+
|
|
15
|
+
@DoNotStrip
|
|
16
|
+
@Keep
|
|
17
|
+
class HybridLiftoffRewardedAd(
|
|
18
|
+
private val context: ReactApplicationContext,
|
|
19
|
+
placementId: String,
|
|
20
|
+
) : HybridLiftoffRewardedAdSpec(), RewardedAdListener {
|
|
21
|
+
private val events = LiftoffAdEventEmitter()
|
|
22
|
+
private val immersiveMode = ImmersiveModeController()
|
|
23
|
+
private val ad = RewardedAd(context, placementId, AdConfig())
|
|
24
|
+
|
|
25
|
+
init {
|
|
26
|
+
ad.adListener = this
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun load() {
|
|
30
|
+
context.runOnUiQueueThread { ad.load() }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun setUserId(userId: String) {
|
|
34
|
+
context.runOnUiQueueThread { ad.setUserId(userId) }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
override fun show(options: LiftoffAdShowOptions?): Promise<Unit> = Promise.async {
|
|
38
|
+
try {
|
|
39
|
+
withContext(Dispatchers.Main) {
|
|
40
|
+
val activity = context.requireCurrentActivity()
|
|
41
|
+
if (!ad.canPlayAd()) error("Liftoff rewarded ad is not ready")
|
|
42
|
+
if (options?.immersiveModeEnabled == true) immersiveMode.enable(activity)
|
|
43
|
+
ad.play(activity)
|
|
44
|
+
}
|
|
45
|
+
} catch (error: Throwable) {
|
|
46
|
+
immersiveMode.restore()
|
|
47
|
+
events.emit(LiftoffAdEventType.ERROR, error.toLiftoffEventPayload())
|
|
48
|
+
throw error
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override fun addAdEventListener(
|
|
53
|
+
eventType: LiftoffAdEventType,
|
|
54
|
+
listener: (payload: LiftoffAdEventPayload?) -> Unit,
|
|
55
|
+
) = events.add(eventType, listener)
|
|
56
|
+
|
|
57
|
+
override fun removeAdEventListener(subscriptionId: Double) {
|
|
58
|
+
events.remove(subscriptionId)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
override fun removeAllListeners() {
|
|
62
|
+
events.removeAll()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override fun onAdLoaded(baseAd: BaseAd) {
|
|
66
|
+
events.emit(LiftoffAdEventType.REWARDED_LOADED)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override fun onAdStart(baseAd: BaseAd) {
|
|
70
|
+
events.emit(LiftoffAdEventType.OPENED)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
override fun onAdImpression(baseAd: BaseAd) = Unit
|
|
74
|
+
|
|
75
|
+
override fun onAdClicked(baseAd: BaseAd) {
|
|
76
|
+
events.emit(LiftoffAdEventType.CLICKED)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun onAdLeftApplication(baseAd: BaseAd) = Unit
|
|
80
|
+
|
|
81
|
+
override fun onAdRewarded(baseAd: BaseAd) {
|
|
82
|
+
events.emit(LiftoffAdEventType.REWARDED_EARNED_REWARD)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun onAdEnd(baseAd: BaseAd) {
|
|
86
|
+
immersiveMode.restore()
|
|
87
|
+
events.emit(LiftoffAdEventType.CLOSED)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override fun onAdFailedToLoad(baseAd: BaseAd, adError: VungleError) {
|
|
91
|
+
events.emit(
|
|
92
|
+
LiftoffAdEventType.ERROR,
|
|
93
|
+
liftoffException("load", adError).toLiftoffEventPayload(),
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
override fun onAdFailedToPlay(baseAd: BaseAd, adError: VungleError) {
|
|
98
|
+
immersiveMode.restore()
|
|
99
|
+
events.emit(
|
|
100
|
+
LiftoffAdEventType.ERROR,
|
|
101
|
+
liftoffException("show", adError).toLiftoffEventPayload(),
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}
|