diff --git a/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java b/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java index f26e4f3b0..f6d7bc933 100644 --- a/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java +++ b/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java @@ -722,6 +722,22 @@ public void prepareAttributesAsync(@NonNull Map attributes) { } } + @Override + public void setSessionId(@NonNull String sessionId) { + if (mKitManager != null) { + mKitManager.setSessionId(sessionId); + } + } + + @Override + @Nullable + public String getSessionId() { + if (mKitManager != null) { + return mKitManager.getSessionId(); + } + return null; + } + static class CoreCallbacksImpl implements CoreCallbacks { KitFrameworkWrapper mKitFrameworkWrapper; ConfigManager mConfigManager; diff --git a/android-core/src/main/java/com/mparticle/internal/KitManager.java b/android-core/src/main/java/com/mparticle/internal/KitManager.java index 716f526d2..ad5c9808d 100644 --- a/android-core/src/main/java/com/mparticle/internal/KitManager.java +++ b/android-core/src/main/java/com/mparticle/internal/KitManager.java @@ -148,6 +148,21 @@ void execute(@NonNull String identifier, void close(); + /** + * Set the session id to use for the next execute call. + * + * @param sessionId The session id to be set. Must be a non-empty string. + */ + void setSessionId(@NonNull String sessionId); + + /** + * Get the session id to use within a non-native integration e.g. WebView. + * + * @return The session id or null if no session is present. + */ + @Nullable + String getSessionId(); + void prepareAttributesAsync(@NonNull Map attributes); enum KitStatus { diff --git a/android-core/src/main/kotlin/com/mparticle/Rokt.kt b/android-core/src/main/kotlin/com/mparticle/Rokt.kt index 58a70543e..6b095b5e0 100644 --- a/android-core/src/main/kotlin/com/mparticle/Rokt.kt +++ b/android-core/src/main/kotlin/com/mparticle/Rokt.kt @@ -43,4 +43,31 @@ class Rokt internal constructor(private val mConfigManager: ConfigManager, priva mKitManager.close() } } + + /** + * Set the session id to use for the next execute call. + * + * This is useful for cases where you have a session id from a non-native integration, + * e.g. WebView, and you want the session to be consistent across integrations. + * + * **Note:** Empty strings are ignored and will not update the session. + * + * @param sessionId The session id to be set. Must be a non-empty string. + */ + fun setSessionId(sessionId: String) { + if (mConfigManager.isEnabled) { + mKitManager.setSessionId(sessionId) + } + } + + /** + * Get the session id to use within a non-native integration e.g. WebView. + * + * @return The session id or null if no session is present or SDK is not initialized. + */ + fun getSessionId(): String? = if (mConfigManager.isEnabled) { + mKitManager.getSessionId() + } else { + null + } } diff --git a/android-core/src/test/kotlin/com/mparticle/RoktTest.kt b/android-core/src/test/kotlin/com/mparticle/RoktTest.kt index eac5c3d2b..aa2878fa6 100644 --- a/android-core/src/test/kotlin/com/mparticle/RoktTest.kt +++ b/android-core/src/test/kotlin/com/mparticle/RoktTest.kt @@ -24,6 +24,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.modules.junit4.PowerMockRunner import java.lang.ref.WeakReference import kotlin.test.assertEquals +import kotlin.test.assertNull import kotlin.test.assertTrue @RunWith(PowerMockRunner::class) @@ -169,4 +170,35 @@ class RoktTest { assertTrue(elements.isEmpty()) } } + + @Test + fun testSetSessionId_whenEnabled_delegatesToKitManager() { + `when`(configManager.isEnabled).thenReturn(true) + rokt.setSessionId("test-session-id") + verify(kitManager).setSessionId("test-session-id") + } + + @Test + fun testSetSessionId_whenDisabled_doesNotCallKitManager() { + `when`(configManager.isEnabled).thenReturn(false) + rokt.setSessionId("test-session-id") + verify(kitManager, never()).setSessionId(any()) + } + + @Test + fun testGetSessionId_whenEnabled_delegatesToKitManager() { + `when`(configManager.isEnabled).thenReturn(true) + `when`(kitManager.getSessionId()).thenReturn("expected-session-id") + val result = rokt.getSessionId() + verify(kitManager).getSessionId() + assertEquals("expected-session-id", result) + } + + @Test + fun testGetSessionId_whenDisabled_returnsNull() { + `when`(configManager.isEnabled).thenReturn(false) + val result = rokt.getSessionId() + verify(kitManager, never()).getSessionId() + assertNull(result) + } } diff --git a/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java b/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java index 878889e1d..a542373e1 100644 --- a/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java +++ b/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java @@ -641,5 +641,22 @@ void enrichAttributes( void purchaseFinalized(@NonNull String placementId, @NonNull String catalogItemId, boolean status); void close(); + + /** + * Set the session id to use for the next execute call. + * This is useful for cases where you have a session id from a non-native integration, + * e.g. WebView, and you want the session to be consistent across integrations. + * + * @param sessionId The session id to be set. Must be a non-empty string. + */ + void setSessionId(@NonNull String sessionId); + + /** + * Get the session id to use within a non-native integration e.g. WebView. + * + * @return The session id or null if no session is present. + */ + @Nullable + String getSessionId(); } } diff --git a/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java b/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java index 9c95e62d4..cb9922da0 100644 --- a/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java +++ b/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java @@ -1484,6 +1484,34 @@ public void close() { } } + @Override + public void setSessionId(@NonNull String sessionId) { + for (KitIntegration provider : providers.values()) { + try { + if (provider instanceof KitIntegration.RoktListener && !provider.isDisabled()) { + ((KitIntegration.RoktListener) provider).setSessionId(sessionId); + } + } catch (Exception e) { + Logger.warning("Failed to call setSessionId for kit: " + provider.getName() + ": " + e.getMessage()); + } + } + } + + @Override + @Nullable + public String getSessionId() { + for (KitIntegration provider : providers.values()) { + try { + if (provider instanceof KitIntegration.RoktListener && !provider.isDisabled()) { + return ((KitIntegration.RoktListener) provider).getSessionId(); + } + } catch (Exception e) { + Logger.warning("Failed to call getSessionId for kit: " + provider.getName() + ": " + e.getMessage()); + } + } + return null; + } + @Override public void prepareAttributesAsync(@NonNull Map attributes) { diff --git a/android-kit-base/src/test/kotlin/com/mparticle/kits/KitManagerImplTest.kt b/android-kit-base/src/test/kotlin/com/mparticle/kits/KitManagerImplTest.kt index 699ac3b1a..1f1251038 100644 --- a/android-kit-base/src/test/kotlin/com/mparticle/kits/KitManagerImplTest.kt +++ b/android-kit-base/src/test/kotlin/com/mparticle/kits/KitManagerImplTest.kt @@ -2292,6 +2292,15 @@ class KitManagerImplTest { override fun close() { Logger.info("close called") } + + override fun setSessionId(sessionId: String) { + Logger.info("setSessionId called with $sessionId") + } + + override fun getSessionId(): String? { + Logger.info("getSessionId called") + return null + } } internal inner class KitManagerEventCounter : MockKitManagerImpl() {