From f2dd324f28a29b457da4f2feac744f1a558cff74 Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Mon, 20 Jul 2026 12:34:03 -0400 Subject: [PATCH] fix(android): report React Native wrapper type on every selectPlacements call The wrapper SDK type was only reported once at module creation. If MParticle was not started yet, or the Rokt kit had not finished initializing, the call was silently dropped and never retried, so the framework type fell back to android. iOS already re-sends the wrapper type on every placement call; this aligns Android with that behavior. --- .../mparticle/react/rokt/MPRoktModuleImpl.kt | 11 +++++ .../com/mparticle/react/rokt/MPRoktModule.kt | 1 + .../com/mparticle/react/rokt/MPRoktModule.kt | 1 + .../react/rokt/MPRoktModuleImplTest.kt | 43 +++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 android/src/test/java/com/mparticle/react/rokt/MPRoktModuleImplTest.kt diff --git a/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt b/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt index e13f8f1b..80988b3b 100644 --- a/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt +++ b/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt @@ -28,6 +28,17 @@ class MPRoktModuleImpl( private val reactContext: ReactApplicationContext, ) { init { + setWrapperSdk() + } + + /** + * Reports the React Native wrapper SDK type to mParticle so it can be forwarded to kits. + * + * Called before every placement selection (mirroring the iOS implementation) rather than + * only once at module creation, because the one-shot call is silently dropped when + * MParticle has not been started yet or when kits have not finished initializing. + */ + fun setWrapperSdk() { MParticle.getInstance()?.setWrapperSdk(WrapperSdk.WrapperSdkReactNative, "") } diff --git a/android/src/newarch/java/com/mparticle/react/rokt/MPRoktModule.kt b/android/src/newarch/java/com/mparticle/react/rokt/MPRoktModule.kt index d6617cf8..b4f1c540 100644 --- a/android/src/newarch/java/com/mparticle/react/rokt/MPRoktModule.kt +++ b/android/src/newarch/java/com/mparticle/react/rokt/MPRoktModule.kt @@ -33,6 +33,7 @@ class MPRoktModule( Logger.warning("selectPlacements failed. identifier cannot be empty") return } + impl.setWrapperSdk() MParticle.getInstance()?.Rokt()?.events(identifier)?.let { impl.startRoktEventListener(it, reactContext.currentActivity, identifier) } diff --git a/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt b/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt index ad005c30..a4df37d0 100644 --- a/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt +++ b/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt @@ -31,6 +31,7 @@ class MPRoktModule( Logger.warning("selectPlacements failed. identifier cannot be empty") return } + impl.setWrapperSdk() val uiManager = reactContext.getNativeModule(UIManagerModule::class.java) MParticle.getInstance()?.Rokt()?.events(identifier)?.let { impl.startRoktEventListener(it, reactContext.currentActivity, identifier) diff --git a/android/src/test/java/com/mparticle/react/rokt/MPRoktModuleImplTest.kt b/android/src/test/java/com/mparticle/react/rokt/MPRoktModuleImplTest.kt new file mode 100644 index 00000000..ed3498ce --- /dev/null +++ b/android/src/test/java/com/mparticle/react/rokt/MPRoktModuleImplTest.kt @@ -0,0 +1,43 @@ +package com.mparticle.react.rokt + +import com.facebook.react.bridge.ReactApplicationContext +import com.mparticle.MParticle +import com.mparticle.WrapperSdk +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito +import org.mockito.junit.MockitoJUnitRunner + +@RunWith(MockitoJUnitRunner::class) +class MPRoktModuleImplTest { + @Test + fun `setWrapperSdk is reported on module creation`() { + val mParticle = Mockito.mock(MParticle::class.java) + MParticle.setInstance(mParticle) + + MPRoktModuleImpl(Mockito.mock(ReactApplicationContext::class.java)) + + Mockito.verify(mParticle).setWrapperSdk(WrapperSdk.WrapperSdkReactNative, "") + } + + @Test + fun `setWrapperSdk reports wrapper type on each call`() { + val mParticle = Mockito.mock(MParticle::class.java) + MParticle.setInstance(mParticle) + val impl = MPRoktModuleImpl(Mockito.mock(ReactApplicationContext::class.java)) + + impl.setWrapperSdk() + impl.setWrapperSdk() + + Mockito.verify(mParticle, Mockito.times(3)).setWrapperSdk(WrapperSdk.WrapperSdkReactNative, "") + } + + @Test + fun `setWrapperSdk does not crash when MParticle is not started`() { + MParticle.setInstance(null) + + val impl = MPRoktModuleImpl(Mockito.mock(ReactApplicationContext::class.java)) + + impl.setWrapperSdk() + } +}