@advergic-ads/react-native-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AdvergicReactNative.podspec +32 -0
- package/LICENSE +21 -0
- package/README.md +329 -0
- package/android/advergic-bridge/build.gradle +58 -0
- package/android/advergic-bridge/libs/advergic-sdk.aar +0 -0
- package/android/advergic-bridge/src/main/java/com/advergic/reactnative/AdvergicBannerViewManager.kt +194 -0
- package/android/advergic-bridge/src/main/java/com/advergic/reactnative/AdvergicReactNativeModule.java +401 -0
- package/android/advergic-bridge/src/main/java/com/advergic/reactnative/AdvergicReactNativePackage.java +25 -0
- package/android/app/build.gradle +144 -0
- package/android/app/libs/advergic-sdk.aar +0 -0
- package/android/app/src/main/AndroidManifest.xml +30 -0
- package/android/app/src/main/java/com/advergic/reactnative/AdvergicReactNativePackage.java +26 -0
- package/android/app/src/main/java/com/facebook/react/viewmanagers/AdvergicBannerViewManagerInterface.java +8 -0
- package/android/libs/advergic-sdk.aar +0 -0
- package/android/settings.gradle +7 -0
- package/index.d.ts +135 -0
- package/index.js +27 -0
- package/install.js +158 -0
- package/ios/AdvergicBannerView.swift +59 -0
- package/ios/AdvergicBannerViewManager.m +18 -0
- package/ios/AdvergicBannerViewManager.swift +24 -0
- package/ios/AdvergicReactNativeModule.m +36 -0
- package/ios/AdvergicReactNativeModule.swift +363 -0
- package/package.json +57 -0
- package/react-native.config.js +18 -0
- package/src/advergic/AdvergicBannerAd.tsx +51 -0
- package/src/advergic/AdvergicSDK.ts +318 -0
- package/src/advergic/index.ts +11 -0
- package/src/advergic/types.ts +23 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AdvergicReactNativeModule.swift
|
|
3
|
+
// AdvergicReactNative
|
|
4
|
+
//
|
|
5
|
+
// React Native bridge for the Advergic iOS SDK.
|
|
6
|
+
// Exposed to JavaScript as `NativeModules.AdvergicSDK`, mirroring the
|
|
7
|
+
// Android `AdvergicReactNativeModule` so the shared TypeScript layer works
|
|
8
|
+
// identically on both platforms.
|
|
9
|
+
//
|
|
10
|
+
|
|
11
|
+
import Foundation
|
|
12
|
+
import UIKit
|
|
13
|
+
import React
|
|
14
|
+
import AdvergicSDK
|
|
15
|
+
|
|
16
|
+
@objc(AdvergicSDK)
|
|
17
|
+
class AdvergicReactNativeModule: RCTEventEmitter {
|
|
18
|
+
|
|
19
|
+
// The native iOS SDK exposes a single delegate per instance, so we keep one
|
|
20
|
+
// shared instance and act as its delegate, fanning callbacks out to JS.
|
|
21
|
+
static weak var shared: AdvergicReactNativeModule?
|
|
22
|
+
|
|
23
|
+
private let sdk = AdvergicSdk()
|
|
24
|
+
private var hasListeners = false
|
|
25
|
+
|
|
26
|
+
// The iOS SDK callbacks don't echo back the ad unit id, so we remember the
|
|
27
|
+
// last requested id per format to attach it to emitted events.
|
|
28
|
+
private var lastInterstitialAdUnitId = ""
|
|
29
|
+
private var lastRewardedAdUnitId = ""
|
|
30
|
+
private var lastAppOpenAdUnitId = ""
|
|
31
|
+
|
|
32
|
+
// The currently mounted banner view, used to forward click / impression
|
|
33
|
+
// delegate callbacks (which are not tied to a specific banner by the SDK).
|
|
34
|
+
private weak var activeBannerView: AdvergicBannerView?
|
|
35
|
+
|
|
36
|
+
override init() {
|
|
37
|
+
super.init()
|
|
38
|
+
sdk.advergicDelegate = self
|
|
39
|
+
AdvergicReactNativeModule.shared = self
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc
|
|
43
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
override func supportedEvents() -> [String]! {
|
|
48
|
+
return [
|
|
49
|
+
"OnSDKInitialized",
|
|
50
|
+
"OnBotDetectionResult",
|
|
51
|
+
"OnBannerAdLoaded",
|
|
52
|
+
"OnBannerAdFailedToLoad",
|
|
53
|
+
"OnBannerAdClicked",
|
|
54
|
+
"OnBannerAdImpression",
|
|
55
|
+
"OnInterstitialAdLoaded",
|
|
56
|
+
"OnInterstitialAdFailedToLoad",
|
|
57
|
+
"OnInterstitialAdShowed",
|
|
58
|
+
"OnInterstitialAdDismissed",
|
|
59
|
+
"OnInterstitialAdFailedToShow",
|
|
60
|
+
"OnInterstitialAdClicked",
|
|
61
|
+
"OnInterstitialAdImpression",
|
|
62
|
+
"OnRewardedAdLoaded",
|
|
63
|
+
"OnRewardedAdFailedToLoad",
|
|
64
|
+
"OnRewardedAdShowed",
|
|
65
|
+
"OnRewardedAdFailedToShow",
|
|
66
|
+
"OnRewardedAdOpened",
|
|
67
|
+
"OnRewardedAdClicked",
|
|
68
|
+
"OnRewardedAdClosed",
|
|
69
|
+
"OnUserEarnedReward",
|
|
70
|
+
"OnAppOpenAdLoaded",
|
|
71
|
+
"OnAppOpenAdFailedToLoad",
|
|
72
|
+
"OnAppOpenAdShowed",
|
|
73
|
+
"OnAppOpenAdDismissed",
|
|
74
|
+
"OnAppOpenAdFailedToShow",
|
|
75
|
+
"OnAppOpenAdClicked",
|
|
76
|
+
"OnAppOpenAdImpression",
|
|
77
|
+
"OnNativeAdLoaded",
|
|
78
|
+
"OnNativeAdFailedToLoad",
|
|
79
|
+
"OnNativeAdClicked",
|
|
80
|
+
"OnNativeAdImpression",
|
|
81
|
+
"OnNativePrebidAdNotFound",
|
|
82
|
+
"OnNativePrebidAdNotValid",
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
override func startObserving() {
|
|
87
|
+
hasListeners = true
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override func stopObserving() {
|
|
91
|
+
hasListeners = false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private func emit(_ name: String, _ body: [String: Any]) {
|
|
95
|
+
guard hasListeners else { return }
|
|
96
|
+
sendEvent(withName: name, body: body)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func adUnitBody(_ adUnitId: String) -> [String: Any] {
|
|
100
|
+
return ["adUnitId": adUnitId]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private func errorBody(_ adUnitId: String, _ error: String) -> [String: Any] {
|
|
104
|
+
return ["adUnitId": adUnitId, "error": error]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// MARK: - View controller helper
|
|
108
|
+
|
|
109
|
+
static func topViewController() -> UIViewController? {
|
|
110
|
+
var keyWindow: UIWindow?
|
|
111
|
+
keyWindow = UIApplication.shared.connectedScenes
|
|
112
|
+
.compactMap { $0 as? UIWindowScene }
|
|
113
|
+
.flatMap { $0.windows }
|
|
114
|
+
.first { $0.isKeyWindow }
|
|
115
|
+
if keyWindow == nil {
|
|
116
|
+
keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow }
|
|
117
|
+
}
|
|
118
|
+
var top = keyWindow?.rootViewController
|
|
119
|
+
while let presented = top?.presentedViewController {
|
|
120
|
+
top = presented
|
|
121
|
+
}
|
|
122
|
+
return top
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// MARK: - Initialization
|
|
126
|
+
|
|
127
|
+
@objc(initialize:resolver:rejecter:)
|
|
128
|
+
func initialize(_ apiKey: String,
|
|
129
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
130
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
131
|
+
DispatchQueue.main.async {
|
|
132
|
+
self.sdk.Init(apiKey: apiKey)
|
|
133
|
+
// The iOS SDK loads its config asynchronously and exposes no completion
|
|
134
|
+
// callback, so we poll for ad units to mirror the Android contract of
|
|
135
|
+
// resolving `true` once the SDK is ready to serve.
|
|
136
|
+
self.waitForInit(attempt: 0, resolve: resolve)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private func waitForInit(attempt: Int, resolve: @escaping RCTPromiseResolveBlock) {
|
|
141
|
+
let units = sdk.getAdvergicAdUnits()
|
|
142
|
+
if !units.isEmpty {
|
|
143
|
+
emit("OnSDKInitialized", ["initialized": true, "adUnitCount": units.count])
|
|
144
|
+
resolve(true)
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
// ~12s budget (40 * 300ms) before giving up and resolving anyway.
|
|
148
|
+
if attempt >= 40 {
|
|
149
|
+
resolve(true)
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
|
153
|
+
self.waitForInit(attempt: attempt + 1, resolve: resolve)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@objc(canServeAds:rejecter:)
|
|
158
|
+
func canServeAds(_ resolve: @escaping RCTPromiseResolveBlock,
|
|
159
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
160
|
+
resolve(!sdk.getAdvergicAdUnits().isEmpty)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@objc(getAdUnits:rejecter:)
|
|
164
|
+
func getAdUnits(_ resolve: @escaping RCTPromiseResolveBlock,
|
|
165
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
166
|
+
let result: [[String: Any]] = sdk.getAdvergicAdUnits().map { unit in
|
|
167
|
+
return [
|
|
168
|
+
"id": unit.configID,
|
|
169
|
+
"name": unit.configID,
|
|
170
|
+
"type": unit.adUnitType,
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
resolve(result)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@objc(performFollowUpBotDetection)
|
|
177
|
+
func performFollowUpBotDetection() {
|
|
178
|
+
// Bot detection runs automatically inside the iOS SDK after init; there is
|
|
179
|
+
// no public trigger, so this is a no-op for API parity with Android.
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// MARK: - Banner (called by AdvergicBannerView)
|
|
183
|
+
|
|
184
|
+
func loadBanner(adUnitId: String,
|
|
185
|
+
container: UIView,
|
|
186
|
+
onLoaded: @escaping () -> Void,
|
|
187
|
+
onFailed: @escaping (String) -> Void) {
|
|
188
|
+
activeBannerView = container as? AdvergicBannerView
|
|
189
|
+
attemptLoadBanner(adUnitId: adUnitId, container: container, attempt: 0,
|
|
190
|
+
onLoaded: onLoaded, onFailed: onFailed)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private let maxBannerRetries = 10
|
|
194
|
+
|
|
195
|
+
private func attemptLoadBanner(adUnitId: String,
|
|
196
|
+
container: UIView,
|
|
197
|
+
attempt: Int,
|
|
198
|
+
onLoaded: @escaping () -> Void,
|
|
199
|
+
onFailed: @escaping (String) -> Void) {
|
|
200
|
+
// The SDK silently ignores requests before its config is loaded, so retry
|
|
201
|
+
// until ad units are available (mirrors the Android banner retry logic).
|
|
202
|
+
if sdk.getAdvergicAdUnits().isEmpty {
|
|
203
|
+
if attempt >= maxBannerRetries {
|
|
204
|
+
onFailed("AdvergicSDK not initialized")
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3 * Double(attempt + 1)) {
|
|
208
|
+
self.attemptLoadBanner(adUnitId: adUnitId, container: container,
|
|
209
|
+
attempt: attempt + 1, onLoaded: onLoaded, onFailed: onFailed)
|
|
210
|
+
}
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
guard let vc = AdvergicReactNativeModule.topViewController() else {
|
|
215
|
+
onFailed("No view controller available")
|
|
216
|
+
return
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
sdk.showBannerAd(adUnitID: adUnitId, viewController: vc, bannerAdView: container) { bannerView, error in
|
|
220
|
+
if bannerView != nil {
|
|
221
|
+
onLoaded()
|
|
222
|
+
} else {
|
|
223
|
+
onFailed(error?.localizedDescription ?? "Unknown error")
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Low-level banner API (parity with Android's showBannerAd(adUnitId,
|
|
229
|
+
// containerId)). The primary path is the `AdvergicBannerAd` component, which
|
|
230
|
+
// loads automatically; this resolves a container by its React tag and loads
|
|
231
|
+
// into it, emitting global banner events.
|
|
232
|
+
@objc(showBannerAd:containerId:)
|
|
233
|
+
func showBannerAd(_ adUnitId: String, containerId: NSNumber) {
|
|
234
|
+
bridge.uiManager.addUIBlock { [weak self] _, viewRegistry in
|
|
235
|
+
guard let self = self else { return }
|
|
236
|
+
guard let view = viewRegistry?[containerId] else {
|
|
237
|
+
self.emit("OnBannerAdFailedToLoad", self.errorBody(adUnitId, "Container not found"))
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
self.loadBanner(adUnitId: adUnitId, container: view, onLoaded: {
|
|
241
|
+
self.emit("OnBannerAdLoaded", self.adUnitBody(adUnitId))
|
|
242
|
+
}, onFailed: { error in
|
|
243
|
+
self.emit("OnBannerAdFailedToLoad", self.errorBody(adUnitId, error))
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// MARK: - Full-screen formats
|
|
249
|
+
|
|
250
|
+
@objc(showInterstitialAd:)
|
|
251
|
+
func showInterstitialAd(_ adUnitId: String) {
|
|
252
|
+
DispatchQueue.main.async {
|
|
253
|
+
guard let vc = AdvergicReactNativeModule.topViewController() else {
|
|
254
|
+
self.emit("OnInterstitialAdFailedToLoad", self.errorBody(adUnitId, "No view controller available"))
|
|
255
|
+
return
|
|
256
|
+
}
|
|
257
|
+
self.lastInterstitialAdUnitId = adUnitId
|
|
258
|
+
self.sdk.showInterstitialAd(adUnitID: adUnitId, viewController: vc)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@objc(showRewardedAd:)
|
|
263
|
+
func showRewardedAd(_ adUnitId: String) {
|
|
264
|
+
DispatchQueue.main.async {
|
|
265
|
+
guard let vc = AdvergicReactNativeModule.topViewController() else {
|
|
266
|
+
self.emit("OnRewardedAdFailedToLoad", self.errorBody(adUnitId, "No view controller available"))
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
self.lastRewardedAdUnitId = adUnitId
|
|
270
|
+
self.sdk.showRewardedAd(adUnitID: adUnitId, viewController: vc)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@objc(showAppOpenAd:)
|
|
275
|
+
func showAppOpenAd(_ adUnitId: String) {
|
|
276
|
+
DispatchQueue.main.async {
|
|
277
|
+
guard let vc = AdvergicReactNativeModule.topViewController() else {
|
|
278
|
+
self.emit("OnAppOpenAdFailedToLoad", self.errorBody(adUnitId, "No view controller available"))
|
|
279
|
+
return
|
|
280
|
+
}
|
|
281
|
+
self.lastAppOpenAdUnitId = adUnitId
|
|
282
|
+
self.sdk.showAppOpenAd(adUnitID: adUnitId, viewController: vc)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@objc(showNativeAd:containerId:)
|
|
287
|
+
func showNativeAd(_ adUnitId: String, containerId: NSNumber) {
|
|
288
|
+
// Native ads are not supported by the iOS SDK (Android-only). Emit a
|
|
289
|
+
// failure so callers using the shared JS API get a clear signal.
|
|
290
|
+
emit("OnNativeAdFailedToLoad", errorBody(adUnitId, "Native ads are not supported on iOS"))
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// MARK: - AdvergicSdkProtocols
|
|
295
|
+
|
|
296
|
+
extension AdvergicReactNativeModule: AdvergicSdkProtocols {
|
|
297
|
+
|
|
298
|
+
// Banner — loaded / failed are handled via the showBannerAd completion in the
|
|
299
|
+
// banner view; click / impression are only delivered through this delegate,
|
|
300
|
+
// so we forward them to the active banner view's bubbling events.
|
|
301
|
+
func advergicBannerDidRecordImpression() {
|
|
302
|
+
activeBannerView?.dispatchImpression()
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
func advergicBannerAdDidClick() {
|
|
306
|
+
activeBannerView?.dispatchClicked()
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Interstitial
|
|
310
|
+
func advergicInterstitialDidDissmissAd() {
|
|
311
|
+
emit("OnInterstitialAdDismissed", adUnitBody(lastInterstitialAdUnitId))
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
func advergicInterstitialFailToShowFullScreenContent(adError: String) {
|
|
315
|
+
emit("OnInterstitialAdFailedToShow", errorBody(lastInterstitialAdUnitId, adError))
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
func advergicInterstitialDidClickAd() {
|
|
319
|
+
emit("OnInterstitialAdClicked", adUnitBody(lastInterstitialAdUnitId))
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
func advergicInterstitialDidRecordImpressionAd() {
|
|
323
|
+
emit("OnInterstitialAdImpression", adUnitBody(lastInterstitialAdUnitId))
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Rewarded
|
|
327
|
+
func advergicRewardReceived() {
|
|
328
|
+
emit("OnUserEarnedReward", adUnitBody(lastRewardedAdUnitId))
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
func advergicRewardDidDissmissFullScreen() {
|
|
332
|
+
emit("OnRewardedAdClosed", adUnitBody(lastRewardedAdUnitId))
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
func advergicRewardFailToPresentFullScreenContent(adError: String) {
|
|
336
|
+
emit("OnRewardedAdFailedToShow", errorBody(lastRewardedAdUnitId, adError))
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
func advergicRewardDidRecordImpression() {
|
|
340
|
+
emit("OnRewardedAdShowed", adUnitBody(lastRewardedAdUnitId))
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
func advergicRewardDidRecordClick() {
|
|
344
|
+
emit("OnRewardedAdClicked", adUnitBody(lastRewardedAdUnitId))
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// App Open
|
|
348
|
+
func advergicAppOpenDidDissmissFullScreen() {
|
|
349
|
+
emit("OnAppOpenAdDismissed", adUnitBody(lastAppOpenAdUnitId))
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
func advergicAppOpenFailToPresentFullScreenContent(adError: String) {
|
|
353
|
+
emit("OnAppOpenAdFailedToShow", errorBody(lastAppOpenAdUnitId, adError))
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
func advergicAppOpenDidRecordImpression() {
|
|
357
|
+
emit("OnAppOpenAdImpression", adUnitBody(lastAppOpenAdUnitId))
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
func advergicAppOpenDidRecordClick() {
|
|
361
|
+
emit("OnAppOpenAdClicked", adUnitBody(lastAppOpenAdUnitId))
|
|
362
|
+
}
|
|
363
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@advergic-ads/react-native-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Advergic React Native SDK - Integrate Prebid header bidding and mobile advertising into your React Native apps",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"install": "node install.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"react-native",
|
|
12
|
+
"advergic",
|
|
13
|
+
"advertising",
|
|
14
|
+
"ads",
|
|
15
|
+
"banner",
|
|
16
|
+
"interstitial",
|
|
17
|
+
"rewarded",
|
|
18
|
+
"mobile-ads",
|
|
19
|
+
"admob",
|
|
20
|
+
"prebid"
|
|
21
|
+
],
|
|
22
|
+
"author": "Advergic <hello@advergic.com>",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"homepage": "https://advergic.com",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/advergic/react-native-sdk.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/advergic/react-native-sdk/issues"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react-native": "^0.85.3"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"react-native-safe-area-context": "^4.12.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/react-native": "^0.73.0"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"src/",
|
|
43
|
+
"android/",
|
|
44
|
+
"ios/",
|
|
45
|
+
"install.js",
|
|
46
|
+
"index.js",
|
|
47
|
+
"index.d.ts",
|
|
48
|
+
"react-native.config.js",
|
|
49
|
+
"AdvergicReactNative.podspec",
|
|
50
|
+
"SPEC.md",
|
|
51
|
+
"README.md",
|
|
52
|
+
"CHANGELOG.md"
|
|
53
|
+
],
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
project: {
|
|
3
|
+
ios: {},
|
|
4
|
+
android: {},
|
|
5
|
+
},
|
|
6
|
+
dependency: {
|
|
7
|
+
platforms: {
|
|
8
|
+
android: {
|
|
9
|
+
sourceDir: "android/advergic-bridge",
|
|
10
|
+
packageImportPath: "import com.advergic.reactnative.AdvergicReactNativePackage;",
|
|
11
|
+
packageInstance: "new AdvergicReactNativePackage()",
|
|
12
|
+
},
|
|
13
|
+
ios: {
|
|
14
|
+
podspecPath: "AdvergicReactNative.podspec",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { NativeSyntheticEvent, ViewStyle } from 'react-native';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { requireNativeComponent } from 'react-native';
|
|
4
|
+
|
|
5
|
+
interface NativeProps {
|
|
6
|
+
adUnitId?: string;
|
|
7
|
+
style?: ViewStyle;
|
|
8
|
+
onAdLoaded?: () => void;
|
|
9
|
+
onAdFailedToLoad?: (event: NativeSyntheticEvent<{ error: string }>) => void;
|
|
10
|
+
onAdClicked?: () => void;
|
|
11
|
+
onAdImpression?: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const NativeAdvergicBannerView =
|
|
15
|
+
requireNativeComponent<NativeProps>('AdvergicBannerView');
|
|
16
|
+
|
|
17
|
+
interface AdvergicBannerAdProps {
|
|
18
|
+
adUnitId: string;
|
|
19
|
+
style?: ViewStyle;
|
|
20
|
+
onAdLoaded?: () => void;
|
|
21
|
+
onAdFailedToLoad?: (error: string) => void;
|
|
22
|
+
onAdClicked?: () => void;
|
|
23
|
+
onAdImpression?: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function AdvergicBannerAd({
|
|
27
|
+
adUnitId,
|
|
28
|
+
style,
|
|
29
|
+
onAdLoaded,
|
|
30
|
+
onAdFailedToLoad,
|
|
31
|
+
onAdClicked,
|
|
32
|
+
onAdImpression,
|
|
33
|
+
}: AdvergicBannerAdProps) {
|
|
34
|
+
const handleFailedToLoad = React.useCallback(
|
|
35
|
+
(event: NativeSyntheticEvent<{ error: string }>) => {
|
|
36
|
+
onAdFailedToLoad?.(event.nativeEvent.error);
|
|
37
|
+
},
|
|
38
|
+
[onAdFailedToLoad],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<NativeAdvergicBannerView
|
|
43
|
+
adUnitId={adUnitId}
|
|
44
|
+
style={style}
|
|
45
|
+
onAdLoaded={onAdLoaded}
|
|
46
|
+
onAdFailedToLoad={handleFailedToLoad}
|
|
47
|
+
onAdClicked={onAdClicked}
|
|
48
|
+
onAdImpression={onAdImpression}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|