react-native-pangleads 0.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/LICENSE +20 -0
- package/NitroPangleAds.podspec +26 -0
- package/README.md +80 -0
- package/android/CMakeLists.txt +20 -0
- package/android/build.gradle +129 -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/pangleads/HybridPangleAds.kt +123 -0
- package/android/src/main/java/com/margelo/nitro/pangleads/HybridPangleInterstitialAd.kt +106 -0
- package/android/src/main/java/com/margelo/nitro/pangleads/HybridPangleRewardedAd.kt +139 -0
- package/android/src/main/java/com/margelo/nitro/pangleads/NitroPangleAdsPackage.java +27 -0
- package/android/src/main/java/com/margelo/nitro/pangleads/PangleAdEventEmitter.kt +41 -0
- package/android/src/main/java/com/margelo/nitro/pangleads/PangleAndroidUtils.kt +32 -0
- package/ios/HybridPangleAds.swift +120 -0
- package/ios/HybridPangleInterstitialAd.swift +110 -0
- package/ios/HybridPangleRewardedAd.swift +143 -0
- package/ios/PangleSupport.swift +129 -0
- package/lib/module/index.js +172 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.test.js +201 -0
- package/lib/module/index.test.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/specs/PangleAds.nitro.js +4 -0
- package/lib/module/specs/PangleAds.nitro.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/index.d.ts +68 -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/PangleAds.nitro.d.ts +46 -0
- package/lib/typescript/src/specs/PangleAds.nitro.d.ts.map +1 -0
- package/nitro.json +18 -0
- package/nitrogen/generated/android/NitroPangleAds+autolinking.cmake +85 -0
- package/nitrogen/generated/android/NitroPangleAds+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroPangleAdsOnLoad.cpp +50 -0
- package/nitrogen/generated/android/NitroPangleAdsOnLoad.hpp +25 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_PangleAdEventPayload_.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridPangleAdsSpec.cpp +88 -0
- package/nitrogen/generated/android/c++/JHybridPangleAdsSpec.hpp +69 -0
- package/nitrogen/generated/android/c++/JHybridPangleInterstitialAdSpec.cpp +85 -0
- package/nitrogen/generated/android/c++/JHybridPangleInterstitialAdSpec.hpp +68 -0
- package/nitrogen/generated/android/c++/JHybridPangleRewardedAdSpec.cpp +89 -0
- package/nitrogen/generated/android/c++/JHybridPangleRewardedAdSpec.hpp +68 -0
- package/nitrogen/generated/android/c++/JPangleAdEventPayload.hpp +58 -0
- package/nitrogen/generated/android/c++/JPangleAdEventType.hpp +74 -0
- package/nitrogen/generated/android/c++/JPangleAdVerificationOptions.hpp +58 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/Func_void_std__optional_PangleAdEventPayload_.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/HybridPangleAdsSpec.kt +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/HybridPangleInterstitialAdSpec.kt +73 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/HybridPangleRewardedAdSpec.kt +73 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/NitroPangleAdsOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/PangleAdEventPayload.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/PangleAdEventType.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pangleads/PangleAdVerificationOptions.kt +32 -0
- package/nitrogen/generated/ios/NitroPangleAds+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroPangleAds-Swift-Cxx-Bridge.cpp +90 -0
- package/nitrogen/generated/ios/NitroPangleAds-Swift-Cxx-Bridge.hpp +270 -0
- package/nitrogen/generated/ios/NitroPangleAds-Swift-Cxx-Umbrella.hpp +66 -0
- package/nitrogen/generated/ios/NitroPangleAdsAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroPangleAdsAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridPangleAdsSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridPangleAdsSpecSwift.hpp +114 -0
- package/nitrogen/generated/ios/c++/HybridPangleInterstitialAdSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridPangleInterstitialAdSpecSwift.hpp +107 -0
- package/nitrogen/generated/ios/c++/HybridPangleRewardedAdSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridPangleRewardedAdSpecSwift.hpp +110 -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_PangleAdEventPayload_.swift +54 -0
- package/nitrogen/generated/ios/swift/HybridPangleAdsSpec.swift +54 -0
- package/nitrogen/generated/ios/swift/HybridPangleAdsSpec_cxx.swift +193 -0
- package/nitrogen/generated/ios/swift/HybridPangleInterstitialAdSpec.swift +53 -0
- package/nitrogen/generated/ios/swift/HybridPangleInterstitialAdSpec_cxx.swift +186 -0
- package/nitrogen/generated/ios/swift/HybridPangleRewardedAdSpec.swift +53 -0
- package/nitrogen/generated/ios/swift/HybridPangleRewardedAdSpec_cxx.swift +193 -0
- package/nitrogen/generated/ios/swift/PangleAdEventPayload.swift +77 -0
- package/nitrogen/generated/ios/swift/PangleAdEventType.swift +60 -0
- package/nitrogen/generated/ios/swift/PangleAdVerificationOptions.swift +84 -0
- package/nitrogen/generated/shared/c++/HybridPangleAdsSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridPangleAdsSpec.hpp +74 -0
- package/nitrogen/generated/shared/c++/HybridPangleInterstitialAdSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridPangleInterstitialAdSpec.hpp +73 -0
- package/nitrogen/generated/shared/c++/HybridPangleRewardedAdSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridPangleRewardedAdSpec.hpp +76 -0
- package/nitrogen/generated/shared/c++/PangleAdEventPayload.hpp +72 -0
- package/nitrogen/generated/shared/c++/PangleAdEventType.hpp +96 -0
- package/nitrogen/generated/shared/c++/PangleAdVerificationOptions.hpp +72 -0
- package/package.json +177 -0
- package/react-native.config.js +8 -0
- package/src/index.test.ts +255 -0
- package/src/index.ts +305 -0
- package/src/specs/PangleAds.nitro.ts +66 -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 = "NitroPangleAds"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = "https://github.com/exzos28/react-native-pangleads"
|
|
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/NitroPangleAds+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 "Ads-Global/PangleSDK", "8.2.0.7"
|
|
24
|
+
|
|
25
|
+
install_modules_dependencies(s)
|
|
26
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# react-native-pangleads
|
|
2
|
+
|
|
3
|
+
[Nitro Modules](https://nitro.margelo.com/) bridge for Pangle interstitial
|
|
4
|
+
and rewarded ads.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install react-native-pangleads react-native-nitro-modules
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Pangle's Android SDK lives outside Google's default Maven repos. With Expo
|
|
13
|
+
CNG, enable the bundled config plugin:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"expo": {
|
|
18
|
+
"plugins": ["react-native-pangleads"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Without CNG, add the repo to your app's `android/build.gradle` yourself:
|
|
24
|
+
|
|
25
|
+
```groovy
|
|
26
|
+
allprojects {
|
|
27
|
+
repositories {
|
|
28
|
+
maven { url "https://artifact.bytedance.com/repository/pangle" }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import MobileAds, {
|
|
37
|
+
AdEventType,
|
|
38
|
+
InterstitialAd,
|
|
39
|
+
RewardedAd,
|
|
40
|
+
RewardedAdEventType,
|
|
41
|
+
} from 'react-native-pangleads';
|
|
42
|
+
|
|
43
|
+
await MobileAds().initialize('YOUR_PANGLE_APP_ID');
|
|
44
|
+
MobileAds().setGDPRConsent(true);
|
|
45
|
+
MobileAds().setCCPAConsent(true);
|
|
46
|
+
MobileAds().setCOPPA(false);
|
|
47
|
+
|
|
48
|
+
const interstitial = InterstitialAd.createForAdRequest('YOUR_PLACEMENT_ID');
|
|
49
|
+
interstitial.addAdEventListener(AdEventType.LOADED, () => interstitial.show());
|
|
50
|
+
interstitial.addAdEventListener(AdEventType.CLOSED, () => {
|
|
51
|
+
interstitial.load(); // reuse the same instance for the next impression
|
|
52
|
+
});
|
|
53
|
+
interstitial.load();
|
|
54
|
+
|
|
55
|
+
const rewarded = RewardedAd.createForAdRequest('YOUR_PLACEMENT_ID');
|
|
56
|
+
rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => rewarded.show());
|
|
57
|
+
rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD, () => {
|
|
58
|
+
// grant the reward
|
|
59
|
+
});
|
|
60
|
+
rewarded.load({userId: 'your-user-id'}); // optional, for SSV
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- Ad instances are meant to be reused — call `load()` again on the same
|
|
66
|
+
`InterstitialAd`/`RewardedAd` after `CLOSED` instead of creating a new one.
|
|
67
|
+
- No `AdEventType.PAID` event (unlike Liftoff/Google Mobile Ads).
|
|
68
|
+
- Pangle doesn't report reward type/amount, so `LOADED`/`EARNED_REWARD`
|
|
69
|
+
payloads are always `undefined` — treat them as signals only.
|
|
70
|
+
- Use `RewardedAdEventType.LOADED`, not `AdEventType.LOADED`, on a
|
|
71
|
+
`RewardedAd`.
|
|
72
|
+
- No built-in consent UI (no UMP equivalent) — plug your own and forward the
|
|
73
|
+
result via `setGDPRConsent`/`setCCPAConsent`/`setCOPPA`.
|
|
74
|
+
|
|
75
|
+
See [`src/specs/PangleAds.nitro.ts`](src/specs/PangleAds.nitro.ts) for the
|
|
76
|
+
full native interface and [`example`](example) for a runnable demo.
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
project(NitroPangleAds)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set(PACKAGE_NAME NitroPangleAds)
|
|
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/NitroPangleAds+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,129 @@
|
|
|
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/NitroPangleAds+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["NitroPangleAds_" + name]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def getExtOrIntegerDefault(name) {
|
|
36
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroPangleAds_" + name]).toInteger()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
android {
|
|
40
|
+
namespace "com.margelo.nitro.pangleads"
|
|
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
|
+
maven { url "https://artifact.bytedance.com/repository/pangle" }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
dependencies {
|
|
124
|
+
implementation "com.facebook.react:react-android"
|
|
125
|
+
implementation project(":react-native-nitro-modules")
|
|
126
|
+
|
|
127
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0"
|
|
128
|
+
implementation "com.pangle.global:pag-sdk:8.2.0.4"
|
|
129
|
+
}
|
|
@@ -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,123 @@
|
|
|
1
|
+
package com.margelo.nitro.pangleads
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Keep
|
|
4
|
+
import com.bytedance.sdk.openadsdk.api.PAGConstant.PAGPAConsentType
|
|
5
|
+
import com.bytedance.sdk.openadsdk.api.init.PAGConfig
|
|
6
|
+
import com.bytedance.sdk.openadsdk.api.init.PAGSdk
|
|
7
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
9
|
+
import com.margelo.nitro.NitroModules
|
|
10
|
+
import com.margelo.nitro.core.Promise
|
|
11
|
+
import kotlinx.coroutines.CompletableDeferred
|
|
12
|
+
import kotlinx.coroutines.Dispatchers
|
|
13
|
+
import kotlinx.coroutines.withContext
|
|
14
|
+
|
|
15
|
+
@DoNotStrip
|
|
16
|
+
@Keep
|
|
17
|
+
class HybridPangleAds : HybridPangleAdsSpec() {
|
|
18
|
+
private val context: ReactApplicationContext by lazy {
|
|
19
|
+
NitroModules.applicationContext as? ReactApplicationContext
|
|
20
|
+
?: error("Pangle Ads requires a ReactApplicationContext")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private val stateLock = Any()
|
|
24
|
+
private var initializedAppId: String? = null
|
|
25
|
+
private var initializingAppId: String? = null
|
|
26
|
+
private var initialization: CompletableDeferred<Unit>? = null
|
|
27
|
+
|
|
28
|
+
override fun initialize(appId: String): Promise<Unit> = Promise.async {
|
|
29
|
+
require(appId.isNotBlank()) { "Pangle app ID is empty" }
|
|
30
|
+
|
|
31
|
+
val alreadyInitialized = synchronized(stateLock) {
|
|
32
|
+
val existing = initializedAppId
|
|
33
|
+
if (existing != null && existing != appId) {
|
|
34
|
+
error("Pangle SDK was already initialized with another app ID")
|
|
35
|
+
}
|
|
36
|
+
existing == appId
|
|
37
|
+
}
|
|
38
|
+
if (alreadyInitialized) return@async
|
|
39
|
+
|
|
40
|
+
val (deferred, shouldStart) = synchronized(stateLock) {
|
|
41
|
+
val current = initialization
|
|
42
|
+
if (current != null) {
|
|
43
|
+
if (initializingAppId != appId) {
|
|
44
|
+
error("Pangle SDK is being initialized with another app ID")
|
|
45
|
+
}
|
|
46
|
+
current to false
|
|
47
|
+
} else {
|
|
48
|
+
CompletableDeferred<Unit>().also {
|
|
49
|
+
initialization = it
|
|
50
|
+
initializingAppId = appId
|
|
51
|
+
} to true
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (shouldStart) {
|
|
56
|
+
val config = PAGConfig.Builder().appId(appId).build()
|
|
57
|
+
withContext(Dispatchers.Main) {
|
|
58
|
+
PAGSdk.init(
|
|
59
|
+
context.applicationContext,
|
|
60
|
+
config,
|
|
61
|
+
object : PAGSdk.PAGInitCallback {
|
|
62
|
+
override fun success() {
|
|
63
|
+
synchronized(stateLock) {
|
|
64
|
+
initializedAppId = appId
|
|
65
|
+
initialization = null
|
|
66
|
+
initializingAppId = null
|
|
67
|
+
}
|
|
68
|
+
deferred.complete(Unit)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
override fun fail(code: Int, msg: String) {
|
|
72
|
+
synchronized(stateLock) {
|
|
73
|
+
if (initialization === deferred) initialization = null
|
|
74
|
+
initializingAppId = null
|
|
75
|
+
}
|
|
76
|
+
deferred.completeExceptionally(pangleException("initialize", code, msg))
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
deferred.await()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// pag-sdk 8.x collapsed the separate GDPR/DoNotSell/ChildDirected APIs into a single
|
|
87
|
+
// PAConsent flag, so GDPR/CCPA consent are no longer distinguishable, and there is no
|
|
88
|
+
// longer a public way to flag child-directed (COPPA) traffic to Pangle on Android.
|
|
89
|
+
override fun setGDPRConsent(optIn: Boolean) {
|
|
90
|
+
PAGConfig.setPAConsent(
|
|
91
|
+
if (optIn) PAGPAConsentType.PAG_PA_CONSENT_TYPE_CONSENT
|
|
92
|
+
else PAGPAConsentType.PAG_PA_CONSENT_TYPE_NO_CONSENT,
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
override fun setCCPAConsent(optIn: Boolean) {
|
|
97
|
+
PAGConfig.setPAConsent(
|
|
98
|
+
if (optIn) PAGPAConsentType.PAG_PA_CONSENT_TYPE_CONSENT
|
|
99
|
+
else PAGPAConsentType.PAG_PA_CONSENT_TYPE_NO_CONSENT,
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
override fun setCOPPA(isUserCoppa: Boolean) {}
|
|
104
|
+
|
|
105
|
+
override fun createInterstitialAd(
|
|
106
|
+
placementId: String,
|
|
107
|
+
): HybridPangleInterstitialAdSpec {
|
|
108
|
+
requireInitialized(placementId)
|
|
109
|
+
return HybridPangleInterstitialAd(context, placementId)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override fun createRewardedAd(placementId: String): HybridPangleRewardedAdSpec {
|
|
113
|
+
requireInitialized(placementId)
|
|
114
|
+
return HybridPangleRewardedAd(context, placementId)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private fun requireInitialized(placementId: String) {
|
|
118
|
+
require(synchronized(stateLock) { initializedAppId != null }) {
|
|
119
|
+
"Pangle SDK is not initialized"
|
|
120
|
+
}
|
|
121
|
+
require(placementId.isNotBlank()) { "Pangle placement ID is empty" }
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package com.margelo.nitro.pangleads
|
|
2
|
+
|
|
3
|
+
import android.os.Handler
|
|
4
|
+
import android.os.Looper
|
|
5
|
+
import androidx.annotation.Keep
|
|
6
|
+
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialAd
|
|
7
|
+
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialAdInteractionListener
|
|
8
|
+
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialAdLoadListener
|
|
9
|
+
import com.bytedance.sdk.openadsdk.api.interstitial.PAGInterstitialRequest
|
|
10
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
11
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
12
|
+
import com.margelo.nitro.core.Promise
|
|
13
|
+
import kotlinx.coroutines.Dispatchers
|
|
14
|
+
import kotlinx.coroutines.withContext
|
|
15
|
+
|
|
16
|
+
@DoNotStrip
|
|
17
|
+
@Keep
|
|
18
|
+
class HybridPangleInterstitialAd(
|
|
19
|
+
private val context: ReactApplicationContext,
|
|
20
|
+
private val placementId: String,
|
|
21
|
+
) : HybridPangleInterstitialAdSpec(), PAGInterstitialAdInteractionListener {
|
|
22
|
+
private val events = PangleAdEventEmitter()
|
|
23
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
24
|
+
private var ad: PAGInterstitialAd? = null
|
|
25
|
+
private var showTimeout: Runnable? = null
|
|
26
|
+
|
|
27
|
+
override fun load() {
|
|
28
|
+
context.runOnUiQueueThread {
|
|
29
|
+
PAGInterstitialAd.loadAd(
|
|
30
|
+
placementId,
|
|
31
|
+
PAGInterstitialRequest(),
|
|
32
|
+
object : PAGInterstitialAdLoadListener {
|
|
33
|
+
override fun onError(code: Int, message: String) {
|
|
34
|
+
mainHandler.post {
|
|
35
|
+
events.emit(
|
|
36
|
+
PangleAdEventType.ERROR,
|
|
37
|
+
pangleException("load", code, message).toPangleEventPayload(),
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
override fun onAdLoaded(interstitialAd: PAGInterstitialAd) {
|
|
43
|
+
mainHandler.post {
|
|
44
|
+
interstitialAd.setAdInteractionListener(this@HybridPangleInterstitialAd)
|
|
45
|
+
ad = interstitialAd
|
|
46
|
+
events.emit(PangleAdEventType.LOADED)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
override fun show(): Promise<Unit> = Promise.async {
|
|
55
|
+
withContext(Dispatchers.Main) {
|
|
56
|
+
val activity = context.requireCurrentActivity()
|
|
57
|
+
val current = ad ?: error("Pangle interstitial ad is not ready")
|
|
58
|
+
armShowTimeout()
|
|
59
|
+
current.show(activity)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
override fun addAdEventListener(
|
|
64
|
+
eventType: PangleAdEventType,
|
|
65
|
+
listener: (payload: PangleAdEventPayload?) -> Unit,
|
|
66
|
+
) = events.add(eventType, listener)
|
|
67
|
+
|
|
68
|
+
override fun removeAdEventListener(subscriptionId: Double) {
|
|
69
|
+
events.remove(subscriptionId)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override fun removeAllListeners() {
|
|
73
|
+
events.removeAll()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override fun onAdShowed() {
|
|
77
|
+
disarmShowTimeout()
|
|
78
|
+
events.emit(PangleAdEventType.OPENED)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override fun onAdClicked() {
|
|
82
|
+
events.emit(PangleAdEventType.CLICKED)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun onAdDismissed() {
|
|
86
|
+
disarmShowTimeout()
|
|
87
|
+
ad = null
|
|
88
|
+
events.emit(PangleAdEventType.CLOSED)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private fun armShowTimeout() {
|
|
92
|
+
disarmShowTimeout()
|
|
93
|
+
val runnable = Runnable {
|
|
94
|
+
showTimeout = null
|
|
95
|
+
ad = null
|
|
96
|
+
events.emit(PangleAdEventType.ERROR, pangleShowTimeoutPayload())
|
|
97
|
+
}
|
|
98
|
+
showTimeout = runnable
|
|
99
|
+
mainHandler.postDelayed(runnable, PANGLE_SHOW_TIMEOUT_MS)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private fun disarmShowTimeout() {
|
|
103
|
+
showTimeout?.let(mainHandler::removeCallbacks)
|
|
104
|
+
showTimeout = null
|
|
105
|
+
}
|
|
106
|
+
}
|