setupad-prebid-react-native 0.1.3
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/README.md +325 -0
- package/VeonPrebidReactNative.podspec +59 -0
- package/android/build.gradle +90 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/setupadprebidreactnative/VeonPrebidReactNativeModule.kt +130 -0
- package/android/src/main/java/com/setupadprebidreactnative/VeonPrebidReactNativePackage.kt +20 -0
- package/android/src/main/java/com/setupadprebidreactnative/VeonPrebidReactNativeView.kt +425 -0
- package/android/src/main/java/com/setupadprebidreactnative/VeonPrebidReactNativeViewManager.kt +186 -0
- package/ios/RCTFabricComponentsPlugins.h +12 -0
- package/ios/VeonPrebidReactNative-Bridging-Header.h +9 -0
- package/ios/VeonPrebidReactNativeModule.m +17 -0
- package/ios/VeonPrebidReactNativeModule.swift +108 -0
- package/ios/VeonPrebidReactNativeView+Delegates.swift +217 -0
- package/ios/VeonPrebidReactNativeView.h +5 -0
- package/ios/VeonPrebidReactNativeView.swift +381 -0
- package/ios/VeonPrebidReactNativeViewComponentView.h +13 -0
- package/ios/VeonPrebidReactNativeViewComponentView.mm +166 -0
- package/ios/VeonPrebidReactNativeViewManager.m +49 -0
- package/ios/VeonPrebidReactNativeViewManager.swift +105 -0
- package/lib/module/CodegenTypes.d.js +2 -0
- package/lib/module/CodegenTypes.d.js.map +1 -0
- package/lib/module/Commands.js +14 -0
- package/lib/module/Commands.js.map +1 -0
- package/lib/module/VeonPrebidAd.js +112 -0
- package/lib/module/VeonPrebidAd.js.map +1 -0
- package/lib/module/VeonPrebidModule.js +132 -0
- package/lib/module/VeonPrebidModule.js.map +1 -0
- package/lib/module/VeonPrebidReactNativeViewNativeComponent.ts +50 -0
- package/lib/module/VeonPrebidView.js +14 -0
- package/lib/module/VeonPrebidView.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +8 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/useVeonPrebidAd.js +154 -0
- package/lib/module/useVeonPrebidAd.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/Commands.d.ts +14 -0
- package/lib/typescript/src/Commands.d.ts.map +1 -0
- package/lib/typescript/src/VeonPrebidAd.d.ts +4 -0
- package/lib/typescript/src/VeonPrebidAd.d.ts.map +1 -0
- package/lib/typescript/src/VeonPrebidModule.d.ts +59 -0
- package/lib/typescript/src/VeonPrebidModule.d.ts.map +1 -0
- package/lib/typescript/src/VeonPrebidReactNativeViewNativeComponent.d.ts +40 -0
- package/lib/typescript/src/VeonPrebidReactNativeViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/VeonPrebidView.d.ts +5 -0
- package/lib/typescript/src/VeonPrebidView.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +7 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +89 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/useVeonPrebidAd.d.ts +52 -0
- package/lib/typescript/src/useVeonPrebidAd.d.ts.map +1 -0
- package/package.json +169 -0
- package/src/CodegenTypes.d.ts +16 -0
- package/src/Commands.ts +25 -0
- package/src/VeonPrebidAd.tsx +159 -0
- package/src/VeonPrebidModule.ts +159 -0
- package/src/VeonPrebidReactNativeViewNativeComponent.ts +50 -0
- package/src/VeonPrebidView.tsx +13 -0
- package/src/index.tsx +12 -0
- package/src/types.ts +64 -0
- package/src/useVeonPrebidAd.ts +156 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
package com.setupadprebidreactnative
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import android.view.Gravity
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.widget.FrameLayout
|
|
7
|
+
import com.facebook.react.bridge.Arguments
|
|
8
|
+
import com.facebook.react.bridge.ReactContext
|
|
9
|
+
import com.facebook.react.bridge.WritableMap
|
|
10
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
11
|
+
import org.prebid.mobile.AdSize
|
|
12
|
+
import org.prebid.mobile.api.data.SdkType
|
|
13
|
+
import org.prebid.mobile.api.multiadloader.MultiBannerLoader
|
|
14
|
+
import org.prebid.mobile.api.multiadloader.MultiInterstitialAdLoader
|
|
15
|
+
import org.prebid.mobile.api.multiadloader.listeners.MultiBannerViewListener
|
|
16
|
+
import org.prebid.mobile.api.multiadloader.listeners.MultiInterstitialAdListener
|
|
17
|
+
import org.prebid.mobile.api.rendering.BannerView
|
|
18
|
+
|
|
19
|
+
class VeonPrebidReactNativeView(private val reactContext: ReactContext) : FrameLayout(reactContext) {
|
|
20
|
+
private val TAG = "VeonPrebidRN"
|
|
21
|
+
|
|
22
|
+
// Ad loaders
|
|
23
|
+
private var bannerLoader: MultiBannerLoader? = null
|
|
24
|
+
private var interstitialLoader: MultiInterstitialAdLoader? = null
|
|
25
|
+
|
|
26
|
+
// Ad parameters - stored individually for compatibility with ViewManager
|
|
27
|
+
private var adType: String? = null
|
|
28
|
+
private var configId: String? = null
|
|
29
|
+
private var adUnitId: String? = null
|
|
30
|
+
private var width: Int = 0
|
|
31
|
+
private var height: Int = 0
|
|
32
|
+
private var refreshInterval: Int = 30
|
|
33
|
+
|
|
34
|
+
// Banner view reference
|
|
35
|
+
private var bannerView: BannerView? = null
|
|
36
|
+
private var adView: View? = null
|
|
37
|
+
|
|
38
|
+
// Track banner display state (survives SDK removing old view on refresh)
|
|
39
|
+
private var isBannerShowing = false
|
|
40
|
+
|
|
41
|
+
// Track if parameters are complete
|
|
42
|
+
private var paramsComplete = false
|
|
43
|
+
|
|
44
|
+
// Runnable for forcing layout after programmatic view changes
|
|
45
|
+
private val measureAndLayout = Runnable {
|
|
46
|
+
measure(
|
|
47
|
+
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
|
|
48
|
+
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY)
|
|
49
|
+
)
|
|
50
|
+
layout(left, top, right, bottom)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
init {
|
|
54
|
+
Log.d(TAG, "VeonPrebidReactNativeView initialized")
|
|
55
|
+
|
|
56
|
+
// Set layout params for the container
|
|
57
|
+
val params = LayoutParams(
|
|
58
|
+
LayoutParams.MATCH_PARENT,
|
|
59
|
+
LayoutParams.WRAP_CONTENT
|
|
60
|
+
)
|
|
61
|
+
params.gravity = Gravity.CENTER
|
|
62
|
+
layoutParams = params
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Override requestLayout to force React Native to re-render programmatically added children
|
|
66
|
+
override fun requestLayout() {
|
|
67
|
+
super.requestLayout()
|
|
68
|
+
post(measureAndLayout)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Individual setters for React Native props
|
|
72
|
+
fun setAdType(type: String) {
|
|
73
|
+
this.adType = type
|
|
74
|
+
Log.d(TAG, "AdType set: $type")
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fun setConfigId(id: String) {
|
|
78
|
+
this.configId = id
|
|
79
|
+
Log.d(TAG, "ConfigId set: $id")
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fun setAdUnitId(id: String) {
|
|
83
|
+
this.adUnitId = id
|
|
84
|
+
Log.d(TAG, "AdUnitId set: $id")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fun setAdWidth(w: Int) {
|
|
88
|
+
this.width = w
|
|
89
|
+
Log.d(TAG, "Width set: $w")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fun setAdHeight(h: Int) {
|
|
93
|
+
this.height = h
|
|
94
|
+
Log.d(TAG, "Height set: $h")
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fun setRefreshInterval(interval: Int) {
|
|
98
|
+
this.refreshInterval = interval
|
|
99
|
+
Log.d(TAG, "RefreshInterval set: $interval")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fun loadBanner() {
|
|
103
|
+
Log.d(TAG, "loadBanner called - configId=$configId, adUnitId=$adUnitId")
|
|
104
|
+
|
|
105
|
+
if (configId == null || adUnitId == null) {
|
|
106
|
+
Log.e(TAG, "Cannot load banner: configId or adUnitId is null")
|
|
107
|
+
sendEvent("onAdFailed", "Config ID or Ad Unit ID is null")
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (bannerLoader == null) {
|
|
112
|
+
Log.d(TAG, "Banner loader is null, creating new one")
|
|
113
|
+
createBannerLoader()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
Log.d(TAG, "Calling bannerLoader.loadAd()")
|
|
117
|
+
bannerLoader?.loadAd()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
fun showBanner() {
|
|
121
|
+
Log.d(TAG, "showBanner called - adView=$adView, size before: ${adView?.width}x${adView?.height}")
|
|
122
|
+
|
|
123
|
+
adView?.let { view ->
|
|
124
|
+
// Remove all existing children first to avoid stale views
|
|
125
|
+
if (childCount > 0) {
|
|
126
|
+
removeAllViews()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (view.parent != null) {
|
|
130
|
+
Log.d(TAG, "Removing view from old parent: ${view.parent}")
|
|
131
|
+
(view.parent as? FrameLayout)?.removeView(view)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Log.d(TAG, "Adding banner view to container - size: ${width}x${height}dp")
|
|
135
|
+
|
|
136
|
+
// Convert dp to pixels for layout
|
|
137
|
+
val density = resources.displayMetrics.density
|
|
138
|
+
val widthPx = (width * density).toInt()
|
|
139
|
+
val heightPx = (height * density).toInt()
|
|
140
|
+
|
|
141
|
+
// Set layout params on the ad view itself
|
|
142
|
+
view.layoutParams = LayoutParams(widthPx, heightPx)
|
|
143
|
+
|
|
144
|
+
val params = LayoutParams(widthPx, heightPx)
|
|
145
|
+
params.gravity = Gravity.CENTER
|
|
146
|
+
addView(view, params)
|
|
147
|
+
|
|
148
|
+
visibility = View.VISIBLE
|
|
149
|
+
isBannerShowing = true
|
|
150
|
+
|
|
151
|
+
// Force layout and measure
|
|
152
|
+
view.measure(
|
|
153
|
+
View.MeasureSpec.makeMeasureSpec(widthPx, View.MeasureSpec.EXACTLY),
|
|
154
|
+
View.MeasureSpec.makeMeasureSpec(heightPx, View.MeasureSpec.EXACTLY)
|
|
155
|
+
)
|
|
156
|
+
view.layout(0, 0, widthPx, heightPx)
|
|
157
|
+
view.requestLayout()
|
|
158
|
+
requestLayout()
|
|
159
|
+
|
|
160
|
+
Log.d(TAG, "Banner view added - pixels: ${widthPx}x${heightPx}px, view size: ${view.width}x${view.height}, childCount=$childCount")
|
|
161
|
+
} ?: run {
|
|
162
|
+
Log.w(TAG, "No banner view to show - adView is null. Try calling loadBanner first.")
|
|
163
|
+
sendEvent("onAdFailed", "No banner loaded yet")
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
fun hideBanner() {
|
|
168
|
+
Log.d(TAG, "hideBanner called")
|
|
169
|
+
isBannerShowing = false
|
|
170
|
+
adView?.let { view ->
|
|
171
|
+
removeView(view)
|
|
172
|
+
visibility = View.GONE
|
|
173
|
+
Log.d(TAG, "Banner view removed and hidden")
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private fun createBannerLoader() {
|
|
178
|
+
Log.d(TAG, "Creating banner loader - size: ${width}x${height}, configId: $configId, adUnitId: $adUnitId, refresh: $refreshInterval")
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
bannerLoader = MultiBannerLoader(
|
|
182
|
+
context = context,
|
|
183
|
+
adSize = AdSize(width, height),
|
|
184
|
+
configId = configId!!,
|
|
185
|
+
gamAdUnitId = adUnitId!!,
|
|
186
|
+
autoRefreshDelay = refreshInterval
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
Log.d(TAG, "MultiBannerLoader created successfully")
|
|
190
|
+
|
|
191
|
+
bannerLoader?.setListener(object : MultiBannerViewListener {
|
|
192
|
+
override fun onAdLoaded(view: View, sdk: SdkType) {
|
|
193
|
+
Log.d(TAG, "Banner LOADED from ${sdk.name}, isBannerShowing=$isBannerShowing")
|
|
194
|
+
adView = view
|
|
195
|
+
sendEvent("onAdLoaded", sdk)
|
|
196
|
+
|
|
197
|
+
// Auto-refresh: if banner was already displayed, replace old view with new one
|
|
198
|
+
if (isBannerShowing) {
|
|
199
|
+
Log.d(TAG, "Banner refresh detected - auto-replacing displayed view")
|
|
200
|
+
post {
|
|
201
|
+
showBanner()
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
override fun onAdFailed(bannerView: BannerView?, error: String?, sdk: SdkType?) {
|
|
207
|
+
val errorMsg = error ?: "Unknown error"
|
|
208
|
+
val sdkName = sdk?.name ?: "unknown"
|
|
209
|
+
Log.e(TAG, "Banner FAILED: $errorMsg (SDK: $sdkName)")
|
|
210
|
+
sendEvent("onAdFailed", errorMsg, sdk)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
override fun onAdClicked(bannerView: BannerView?, sdk: SdkType) {
|
|
214
|
+
Log.d(TAG, "Banner clicked from ${sdk.name}")
|
|
215
|
+
sendEvent("onAdClicked", sdk)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
override fun onAdClosed(bannerView: BannerView?, sdk: SdkType) {
|
|
219
|
+
Log.d(TAG, "Banner closed from ${sdk.name}")
|
|
220
|
+
sendEvent("onAdClosed", sdk)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
override fun onAdDisplayed(bannerAdView: BannerView?, sdk: SdkType) {
|
|
224
|
+
this@VeonPrebidReactNativeView.bannerView = bannerAdView
|
|
225
|
+
Log.d(TAG, "Banner DISPLAYED from ${sdk.name}")
|
|
226
|
+
sendEvent("onAdDisplayed", sdk)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
override fun onImpression(sdk: SdkType) {
|
|
230
|
+
Log.d(TAG, "Banner impression from ${sdk.name}")
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
override fun onAdOpened(sdk: SdkType) {
|
|
234
|
+
Log.d(TAG, "Banner opened from ${sdk.name}")
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
Log.d(TAG, "Banner listener set successfully")
|
|
239
|
+
} catch (e: Exception) {
|
|
240
|
+
Log.e(TAG, "Error creating banner loader", e)
|
|
241
|
+
sendEvent("onAdFailed", "Error creating banner: ${e.message}")
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
fun loadInterstitial() {
|
|
246
|
+
Log.d(TAG, "loadInterstitial called")
|
|
247
|
+
if (configId == null || adUnitId == null) {
|
|
248
|
+
Log.e(TAG, "Cannot load interstitial: configId or adUnitId is null")
|
|
249
|
+
sendEvent("onAdFailed", "Config ID or Ad Unit ID is null")
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (interstitialLoader == null) {
|
|
254
|
+
createInterstitialLoader()
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
Log.d(TAG, "Calling interstitialLoader.loadAd()")
|
|
258
|
+
interstitialLoader?.loadAd()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
fun showInterstitial() {
|
|
262
|
+
Log.d(TAG, "showInterstitial called")
|
|
263
|
+
interstitialLoader?.showAd() ?: run {
|
|
264
|
+
Log.w(TAG, "No interstitial to show")
|
|
265
|
+
sendEvent("onAdFailed", "No interstitial loaded yet")
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
fun hideInterstitial() {
|
|
270
|
+
Log.d(TAG, "hideInterstitial called")
|
|
271
|
+
destroyInterstitialLoader()
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private fun createInterstitialLoader() {
|
|
275
|
+
Log.d(TAG, "Creating interstitial loader")
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
interstitialLoader = MultiInterstitialAdLoader(
|
|
279
|
+
context = reactContext.currentActivity ?: reactContext,
|
|
280
|
+
configId = configId!!,
|
|
281
|
+
gamAdUnitId = adUnitId!!
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
Log.d(TAG, "MultiInterstitialAdLoader created successfully")
|
|
285
|
+
|
|
286
|
+
interstitialLoader?.setListener(object : MultiInterstitialAdListener {
|
|
287
|
+
override fun onAdLoaded(sdk: SdkType) {
|
|
288
|
+
Log.d(TAG, "Interstitial LOADED from ${sdk.name}")
|
|
289
|
+
sendEvent("onAdLoaded", sdk)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
override fun onAdDisplayed(sdk: SdkType) {
|
|
293
|
+
Log.d(TAG, "Interstitial DISPLAYED from ${sdk.name}")
|
|
294
|
+
sendEvent("onAdDisplayed", sdk)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
override fun onAdFailed(error: String?, sdk: SdkType?) {
|
|
298
|
+
val errorMsg = error ?: "Unknown error"
|
|
299
|
+
val sdkName = sdk?.name ?: "unknown"
|
|
300
|
+
Log.e(TAG, "Interstitial FAILED: $errorMsg (SDK: $sdkName)")
|
|
301
|
+
sendEvent("onAdFailed", errorMsg, sdk)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
override fun onAdFailedToShow(error: String?, sdk: SdkType?) {
|
|
305
|
+
val errorMsg = error ?: "Unknown error"
|
|
306
|
+
val sdkName = sdk?.name ?: "unknown"
|
|
307
|
+
Log.e(TAG, "Interstitial FAILED TO SHOW: $errorMsg (SDK: $sdkName)")
|
|
308
|
+
sendEvent("onAdFailed", errorMsg, sdk)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
override fun onAdClicked(sdk: SdkType) {
|
|
312
|
+
Log.d(TAG, "Interstitial clicked from ${sdk.name}")
|
|
313
|
+
sendEvent("onAdClicked", sdk)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
override fun onAdClosed(sdk: SdkType) {
|
|
317
|
+
Log.d(TAG, "Interstitial closed from ${sdk.name}")
|
|
318
|
+
sendEvent("onAdClosed", sdk)
|
|
319
|
+
}
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
Log.d(TAG, "Interstitial listener set successfully")
|
|
323
|
+
} catch (e: Exception) {
|
|
324
|
+
Log.e(TAG, "Error creating interstitial loader", e)
|
|
325
|
+
sendEvent("onAdFailed", "Error creating interstitial: ${e.message}")
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Pause/Resume/Destroy methods for compatibility
|
|
330
|
+
fun pauseAuction() {
|
|
331
|
+
Log.d(TAG, "pauseAuction called")
|
|
332
|
+
bannerView?.stopRefresh()
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
fun resumeAuction() {
|
|
336
|
+
Log.d(TAG, "resumeAuction called")
|
|
337
|
+
bannerView?.setAutoRefreshDelay(refreshInterval)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
fun destroyAuction() {
|
|
341
|
+
Log.d(TAG, "destroyAuction called")
|
|
342
|
+
destroy()
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
private fun getSdkTypeName(sdk: SdkType?): String {
|
|
346
|
+
return sdk?.name?.lowercase() ?: "unknown"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Send event with SDK type (for successful events)
|
|
350
|
+
private fun sendEvent(eventName: String, sdk: SdkType) {
|
|
351
|
+
val event: WritableMap = Arguments.createMap()
|
|
352
|
+
event.putString("configId", configId)
|
|
353
|
+
event.putString("adUnitId", adUnitId)
|
|
354
|
+
event.putString("sdkType", getSdkTypeName(sdk))
|
|
355
|
+
|
|
356
|
+
try {
|
|
357
|
+
reactContext
|
|
358
|
+
.getJSModule(RCTEventEmitter::class.java)
|
|
359
|
+
.receiveEvent(id, eventName, event)
|
|
360
|
+
Log.d(TAG, "Event sent: $eventName - SDK: ${sdk.name}")
|
|
361
|
+
} catch (e: Exception) {
|
|
362
|
+
Log.e(TAG, "Error sending event: $eventName", e)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Send event with error message (for failed events)
|
|
367
|
+
private fun sendEvent(eventName: String, error: String, sdk: SdkType? = null) {
|
|
368
|
+
val event: WritableMap = Arguments.createMap()
|
|
369
|
+
event.putString("configId", configId)
|
|
370
|
+
event.putString("adUnitId", adUnitId)
|
|
371
|
+
event.putString("error", error)
|
|
372
|
+
if (sdk != null) {
|
|
373
|
+
event.putString("sdkType", getSdkTypeName(sdk))
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
reactContext
|
|
378
|
+
.getJSModule(RCTEventEmitter::class.java)
|
|
379
|
+
.receiveEvent(id, eventName, event)
|
|
380
|
+
Log.d(TAG, "Event sent: $eventName - Error: $error")
|
|
381
|
+
} catch (e: Exception) {
|
|
382
|
+
Log.e(TAG, "Error sending event: $eventName", e)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private fun destroyBannerLoader() {
|
|
387
|
+
try {
|
|
388
|
+
removeAllViews()
|
|
389
|
+
bannerView?.destroy()
|
|
390
|
+
bannerLoader?.destroy()
|
|
391
|
+
Log.d(TAG, "Banner loader destroyed")
|
|
392
|
+
} catch (e: Exception) {
|
|
393
|
+
Log.w(TAG, "Error destroying banner: $e")
|
|
394
|
+
} finally {
|
|
395
|
+
bannerView = null
|
|
396
|
+
bannerLoader = null
|
|
397
|
+
adView = null
|
|
398
|
+
isBannerShowing = false
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
private fun destroyInterstitialLoader() {
|
|
403
|
+
try {
|
|
404
|
+
interstitialLoader?.destroy()
|
|
405
|
+
Log.d(TAG, "Interstitial loader destroyed")
|
|
406
|
+
} catch (e: Exception) {
|
|
407
|
+
Log.w(TAG, "Error destroying interstitial: $e")
|
|
408
|
+
} finally {
|
|
409
|
+
interstitialLoader = null
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
fun destroy() {
|
|
414
|
+
Log.d(TAG, "Destroying view")
|
|
415
|
+
destroyBannerLoader()
|
|
416
|
+
destroyInterstitialLoader()
|
|
417
|
+
paramsComplete = false
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
override fun onDetachedFromWindow() {
|
|
421
|
+
super.onDetachedFromWindow()
|
|
422
|
+
Log.d(TAG, "View detached from window")
|
|
423
|
+
destroy()
|
|
424
|
+
}
|
|
425
|
+
}
|
package/android/src/main/java/com/setupadprebidreactnative/VeonPrebidReactNativeViewManager.kt
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
package com.setupadprebidreactnative
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.bridge.Arguments
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.bridge.ReadableArray
|
|
8
|
+
import com.facebook.react.bridge.WritableMap
|
|
9
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
10
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
11
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
12
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
13
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ViewManager for Prebid ad views
|
|
17
|
+
* Handles creation and management of banner and interstitial ads
|
|
18
|
+
*/
|
|
19
|
+
@ReactModule(name = VeonPrebidReactNativeViewManager.NAME)
|
|
20
|
+
class VeonPrebidReactNativeViewManager(
|
|
21
|
+
private val reactContext: ReactApplicationContext
|
|
22
|
+
) : SimpleViewManager<VeonPrebidReactNativeView>() {
|
|
23
|
+
|
|
24
|
+
private val TAG = "VeonPrebidViewManager"
|
|
25
|
+
|
|
26
|
+
override fun getName(): String = NAME
|
|
27
|
+
|
|
28
|
+
override fun createViewInstance(context: ThemedReactContext): VeonPrebidReactNativeView {
|
|
29
|
+
Log.d(TAG, "Creating VeonPrebidReactNativeView instance")
|
|
30
|
+
return VeonPrebidReactNativeView(context)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Set ad type (banner, interstitial, rewardVideo)
|
|
35
|
+
*/
|
|
36
|
+
@ReactProp(name = "adType")
|
|
37
|
+
fun setAdType(view: VeonPrebidReactNativeView, adType: String) {
|
|
38
|
+
Log.d(TAG, "Setting ad type: $adType")
|
|
39
|
+
view.setAdType(adType)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Set Prebid config ID
|
|
44
|
+
*/
|
|
45
|
+
@ReactProp(name = "configId")
|
|
46
|
+
fun setConfigId(view: VeonPrebidReactNativeView, configId: String) {
|
|
47
|
+
Log.d(TAG, "Setting config ID: $configId")
|
|
48
|
+
view.setConfigId(configId)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set Google Ad Manager ad unit ID
|
|
53
|
+
*/
|
|
54
|
+
@ReactProp(name = "adUnitId")
|
|
55
|
+
fun setAdUnitId(view: VeonPrebidReactNativeView, adUnitId: String) {
|
|
56
|
+
Log.d(TAG, "Setting ad unit ID: $adUnitId")
|
|
57
|
+
view.setAdUnitId(adUnitId)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Set ad width
|
|
62
|
+
*/
|
|
63
|
+
@ReactProp(name = "width")
|
|
64
|
+
fun setWidth(view: VeonPrebidReactNativeView, width: Int) {
|
|
65
|
+
Log.d(TAG, "Setting width: $width")
|
|
66
|
+
view.setAdWidth(width)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Set ad height
|
|
71
|
+
*/
|
|
72
|
+
@ReactProp(name = "height")
|
|
73
|
+
fun setHeight(view: VeonPrebidReactNativeView, height: Int) {
|
|
74
|
+
Log.d(TAG, "Setting height: $height")
|
|
75
|
+
view.setAdHeight(height)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Set refresh interval in seconds (for banners)
|
|
80
|
+
*/
|
|
81
|
+
@ReactProp(name = "refreshInterval")
|
|
82
|
+
fun setRefreshInterval(view: VeonPrebidReactNativeView, refreshInterval: Int) {
|
|
83
|
+
Log.d(TAG, "Setting refresh interval: $refreshInterval seconds")
|
|
84
|
+
view.setRefreshInterval(refreshInterval)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Define commands that can be called from JavaScript
|
|
89
|
+
*/
|
|
90
|
+
override fun getCommandsMap(): Map<String, Int> = mapOf(
|
|
91
|
+
"loadBanner" to COMMAND_LOAD_BANNER,
|
|
92
|
+
"showBanner" to COMMAND_SHOW_BANNER,
|
|
93
|
+
"hideBanner" to COMMAND_HIDE_BANNER,
|
|
94
|
+
"loadInterstitial" to COMMAND_LOAD_INTERSTITIAL,
|
|
95
|
+
"showInterstitial" to COMMAND_SHOW_INTERSTITIAL,
|
|
96
|
+
"hideInterstitial" to COMMAND_HIDE_INTERSTITIAL,
|
|
97
|
+
"pauseAuction" to COMMAND_PAUSE_AUCTION,
|
|
98
|
+
"resumeAuction" to COMMAND_RESUME_AUCTION,
|
|
99
|
+
"destroyAuction" to COMMAND_DESTROY_AUCTION
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Handle commands from JavaScript (new architecture - String command)
|
|
104
|
+
*/
|
|
105
|
+
override fun receiveCommand(
|
|
106
|
+
view: VeonPrebidReactNativeView,
|
|
107
|
+
commandId: String,
|
|
108
|
+
args: ReadableArray?
|
|
109
|
+
) {
|
|
110
|
+
Log.d(TAG, "Received command (String): $commandId")
|
|
111
|
+
|
|
112
|
+
when (commandId.toIntOrNull()) {
|
|
113
|
+
COMMAND_LOAD_BANNER -> view.loadBanner()
|
|
114
|
+
COMMAND_SHOW_BANNER -> view.showBanner()
|
|
115
|
+
COMMAND_HIDE_BANNER -> view.hideBanner()
|
|
116
|
+
COMMAND_LOAD_INTERSTITIAL -> view.loadInterstitial()
|
|
117
|
+
COMMAND_SHOW_INTERSTITIAL -> view.showInterstitial()
|
|
118
|
+
COMMAND_HIDE_INTERSTITIAL -> view.hideInterstitial()
|
|
119
|
+
COMMAND_PAUSE_AUCTION -> view.pauseAuction()
|
|
120
|
+
COMMAND_RESUME_AUCTION -> view.resumeAuction()
|
|
121
|
+
COMMAND_DESTROY_AUCTION -> view.destroyAuction()
|
|
122
|
+
else -> Log.w(TAG, "Unknown command: $commandId")
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Handle commands from JavaScript (old architecture - Int command)
|
|
128
|
+
*/
|
|
129
|
+
override fun receiveCommand(
|
|
130
|
+
view: VeonPrebidReactNativeView,
|
|
131
|
+
commandId: Int,
|
|
132
|
+
args: ReadableArray?
|
|
133
|
+
) {
|
|
134
|
+
Log.d(TAG, "Received command (Int): $commandId")
|
|
135
|
+
|
|
136
|
+
when (commandId) {
|
|
137
|
+
COMMAND_LOAD_BANNER -> view.loadBanner()
|
|
138
|
+
COMMAND_SHOW_BANNER -> view.showBanner()
|
|
139
|
+
COMMAND_HIDE_BANNER -> view.hideBanner()
|
|
140
|
+
COMMAND_LOAD_INTERSTITIAL -> view.loadInterstitial()
|
|
141
|
+
COMMAND_SHOW_INTERSTITIAL -> view.showInterstitial()
|
|
142
|
+
COMMAND_HIDE_INTERSTITIAL -> view.hideInterstitial()
|
|
143
|
+
COMMAND_PAUSE_AUCTION -> view.pauseAuction()
|
|
144
|
+
COMMAND_RESUME_AUCTION -> view.resumeAuction()
|
|
145
|
+
COMMAND_DESTROY_AUCTION -> view.destroyAuction()
|
|
146
|
+
else -> Log.w(TAG, "Unknown command: $commandId")
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Export event names for JavaScript
|
|
152
|
+
*/
|
|
153
|
+
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
|
|
154
|
+
return mapOf(
|
|
155
|
+
"onAdLoaded" to mapOf("registrationName" to "onAdLoaded"),
|
|
156
|
+
"onAdDisplayed" to mapOf("registrationName" to "onAdDisplayed"),
|
|
157
|
+
"onAdFailed" to mapOf("registrationName" to "onAdFailed"),
|
|
158
|
+
"onAdClicked" to mapOf("registrationName" to "onAdClicked"),
|
|
159
|
+
"onAdClosed" to mapOf("registrationName" to "onAdClosed")
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Cleanup when view is dropped
|
|
165
|
+
*/
|
|
166
|
+
override fun onDropViewInstance(view: VeonPrebidReactNativeView) {
|
|
167
|
+
Log.d(TAG, "Dropping view instance")
|
|
168
|
+
view.destroyAuction()
|
|
169
|
+
super.onDropViewInstance(view)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
companion object {
|
|
173
|
+
const val NAME = "VeonPrebidReactNativeView"
|
|
174
|
+
|
|
175
|
+
// Command constants (starts from 0 to match iOS Old Architecture)
|
|
176
|
+
private const val COMMAND_LOAD_BANNER = 0
|
|
177
|
+
private const val COMMAND_SHOW_BANNER = 1
|
|
178
|
+
private const val COMMAND_HIDE_BANNER = 2
|
|
179
|
+
private const val COMMAND_LOAD_INTERSTITIAL = 3
|
|
180
|
+
private const val COMMAND_SHOW_INTERSTITIAL = 4
|
|
181
|
+
private const val COMMAND_HIDE_INTERSTITIAL = 5
|
|
182
|
+
private const val COMMAND_PAUSE_AUCTION = 6
|
|
183
|
+
private const val COMMAND_RESUME_AUCTION = 7
|
|
184
|
+
private const val COMMAND_DESTROY_AUCTION = 8
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTViewManager.h>
|
|
3
|
+
#import <React/RCTEventEmitter.h>
|
|
4
|
+
|
|
5
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
6
|
+
#import "VeonPrebidReactNativeViewComponentView.h"
|
|
7
|
+
#import <React/RCTViewComponentView.h>
|
|
8
|
+
#import <React/RCTConversions.h>
|
|
9
|
+
#endif
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(VeonPrebidReactNativeModule, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(initializeSDK:(NSString *)prebidHost
|
|
7
|
+
configHost:(NSString *)configHost
|
|
8
|
+
accountId:(NSString *)accountId
|
|
9
|
+
timeoutMillis:(nonnull NSNumber *)timeoutMillis
|
|
10
|
+
pbsDebug:(BOOL)pbsDebug
|
|
11
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
12
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
13
|
+
|
|
14
|
+
RCT_EXTERN_METHOD(getSDKVersion:(RCTPromiseResolveBlock)resolve
|
|
15
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
16
|
+
|
|
17
|
+
@end
|