setupad-prebid-react-native 0.1.3 → 0.1.4

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.
@@ -34,6 +34,7 @@ Pod::Spec.new do |s|
34
34
  if ENV['USE_FRAMEWORKS']
35
35
  s.pod_target_xcconfig = {
36
36
  'DEFINES_MODULE' => 'YES',
37
+ 'SWIFT_OBJC_INTERFACE_HEADER_NAME' => 'VeonPrebidReactNative-Swift.h',
37
38
  'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
38
39
  'HEADER_SEARCH_PATHS' => [
39
40
  '"$(PODS_CONFIGURATION_BUILD_DIR)/React-utils/React_utils.framework/Headers"',
@@ -53,6 +54,7 @@ Pod::Spec.new do |s|
53
54
  else
54
55
  s.pod_target_xcconfig = {
55
56
  'DEFINES_MODULE' => 'YES',
57
+ 'SWIFT_OBJC_INTERFACE_HEADER_NAME' => 'VeonPrebidReactNative-Swift.h',
56
58
  'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
57
59
  }
58
60
  end
@@ -1,5 +1,7 @@
1
1
  package com.setupadprebidreactnative
2
2
 
3
+ import android.os.Handler
4
+ import android.os.Looper
3
5
  import android.util.Log
4
6
  import android.view.Gravity
5
7
  import android.view.View
@@ -41,6 +43,9 @@ class VeonPrebidReactNativeView(private val reactContext: ReactContext) : FrameL
41
43
  // Track if parameters are complete
42
44
  private var paramsComplete = false
43
45
 
46
+ // Main thread handler to ensure all Prebid/WebView operations run on UI thread
47
+ private val mainHandler = Handler(Looper.getMainLooper())
48
+
44
49
  // Runnable for forcing layout after programmatic view changes
45
50
  private val measureAndLayout = Runnable {
46
51
  measure(
@@ -108,13 +113,18 @@ class VeonPrebidReactNativeView(private val reactContext: ReactContext) : FrameL
108
113
  return
109
114
  }
110
115
 
111
- if (bannerLoader == null) {
112
- Log.d(TAG, "Banner loader is null, creating new one")
113
- createBannerLoader()
114
- }
116
+ // Ensure banner creation and loading happens on the main thread.
117
+ // Prebid OMID SDK registers a ContentObserver on the calling thread's Looper;
118
+ // if that thread is not main, WebView calls from the observer will crash.
119
+ runOnMainThread {
120
+ if (bannerLoader == null) {
121
+ Log.d(TAG, "Banner loader is null, creating new one")
122
+ createBannerLoader()
123
+ }
115
124
 
116
- Log.d(TAG, "Calling bannerLoader.loadAd()")
117
- bannerLoader?.loadAd()
125
+ Log.d(TAG, "Calling bannerLoader.loadAd()")
126
+ bannerLoader?.loadAd()
127
+ }
118
128
  }
119
129
 
120
130
  fun showBanner() {
@@ -250,19 +260,23 @@ class VeonPrebidReactNativeView(private val reactContext: ReactContext) : FrameL
250
260
  return
251
261
  }
252
262
 
253
- if (interstitialLoader == null) {
254
- createInterstitialLoader()
255
- }
263
+ runOnMainThread {
264
+ if (interstitialLoader == null) {
265
+ createInterstitialLoader()
266
+ }
256
267
 
257
- Log.d(TAG, "Calling interstitialLoader.loadAd()")
258
- interstitialLoader?.loadAd()
268
+ Log.d(TAG, "Calling interstitialLoader.loadAd()")
269
+ interstitialLoader?.loadAd()
270
+ }
259
271
  }
260
272
 
261
273
  fun showInterstitial() {
262
274
  Log.d(TAG, "showInterstitial called")
263
- interstitialLoader?.showAd() ?: run {
264
- Log.w(TAG, "No interstitial to show")
265
- sendEvent("onAdFailed", "No interstitial loaded yet")
275
+ runOnMainThread {
276
+ interstitialLoader?.showAd() ?: run {
277
+ Log.w(TAG, "No interstitial to show")
278
+ sendEvent("onAdFailed", "No interstitial loaded yet")
279
+ }
266
280
  }
267
281
  }
268
282
 
@@ -412,9 +426,27 @@ class VeonPrebidReactNativeView(private val reactContext: ReactContext) : FrameL
412
426
 
413
427
  fun destroy() {
414
428
  Log.d(TAG, "Destroying view")
415
- destroyBannerLoader()
416
- destroyInterstitialLoader()
417
- paramsComplete = false
429
+ runOnMainThread {
430
+ destroyBannerLoader()
431
+ destroyInterstitialLoader()
432
+ paramsComplete = false
433
+ }
434
+ }
435
+
436
+ /**
437
+ * Run a block on the main thread. If already on main, execute immediately.
438
+ * This prevents Prebid OMID SDK from binding ContentObservers to background threads,
439
+ * which would cause WebView calls from non-main threads and crash the app.
440
+ */
441
+ private fun runOnMainThread(block: () -> Unit) {
442
+ val isMainThread = Looper.myLooper() == Looper.getMainLooper()
443
+ if (isMainThread) {
444
+ Log.d(TAG, "runOnMainThread: already on main thread, executing directly")
445
+ block()
446
+ } else {
447
+ Log.w(TAG, "runOnMainThread: called from background thread '${Thread.currentThread().name}', dispatching to main")
448
+ mainHandler.post(block)
449
+ }
418
450
  }
419
451
 
420
452
  override fun onDetachedFromWindow() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "setupad-prebid-react-native",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Prebid SDK for React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",