From b1e4e35c17eb8afe521eea0aff4f10c1b2f53c2c Mon Sep 17 00:00:00 2001 From: James Newman Date: Mon, 18 May 2026 17:45:50 -0400 Subject: [PATCH 1/3] feat: migrate Rokt kit to Rokt SDK 5.x and remove MpRoktEventCallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps com.rokt:roktsdk 4.14.0 → 5.1.0 and adopts the 5.x event-driven API: - Rokt.execute(...) → Rokt.selectPlacements(...) - RoktEvent.id renamed to identifier; SDK-side CartItemInstantPurchase.placementId renamed to identifier - com.rokt.roktsdk.RoktLayout switched to onEvent: (RoktEvent) -> Unit - Drops removed Rokt.RoktCallback / Rokt.RoktInitCallback / Rokt.UnloadReasons and RoktWidgetDimensionCallBack.onMarginChanged Removes the legacy callback surface from the mParticle public API, since 5.x customers consume Rokt.events(identifier): Flow instead: - Delete MpRoktEventCallback and UnloadReasons - Drop callbacks param from com.mparticle.Rokt.selectPlacements - Drop mpRoktEventCallback from RoktKitApi, RoktKitApiImpl, KitIntegration.RoktListener, and RoktKit.selectPlacements - Rename RoktKit.runComposableWithCallback to prepareComposableAttributes; RoktLayout composable no longer takes a callback parameter BREAKING CHANGE: MpRoktEventCallback and UnloadReasons are removed and the callbacks parameter has been dropped from Rokt.selectPlacements and the mParticle RoktLayout composable. Use Rokt.events(identifier) to observe placement events as a Flow. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../com/mparticle/MpRoktEventCallback.kt | 88 ------------------ .../src/main/kotlin/com/mparticle/Rokt.kt | 4 +- .../com/mparticle/internal/RoktKitApi.kt | 3 - .../src/test/kotlin/com/mparticle/RoktTest.kt | 24 +---- .../com/mparticle/kits/KitIntegration.java | 2 - .../com/mparticle/kits/RoktKitApiImpl.kt | 3 - .../com/mparticle/kits/KitManagerImplTest.kt | 8 +- .../com/mparticle/kits/RoktKitApiImplTest.kt | 6 +- kits/rokt/rokt/build.gradle | 2 +- .../main/kotlin/com/mparticle/kits/RoktKit.kt | 91 +++++-------------- .../kotlin/com/mparticle/kits/RoktLayout.kt | 29 ++---- .../kotlin/com/mparticle/kits/RoktKitTests.kt | 85 ++++++++--------- 12 files changed, 82 insertions(+), 263 deletions(-) delete mode 100644 android-core/src/main/kotlin/com/mparticle/MpRoktEventCallback.kt diff --git a/android-core/src/main/kotlin/com/mparticle/MpRoktEventCallback.kt b/android-core/src/main/kotlin/com/mparticle/MpRoktEventCallback.kt deleted file mode 100644 index 92318642c..000000000 --- a/android-core/src/main/kotlin/com/mparticle/MpRoktEventCallback.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.mparticle - -/** - * ### Optional callback events for when the view loads and unloads. - */ -interface MpRoktEventCallback { - /** - * onLoad Callback will be triggered immediately when the View displays. - */ - fun onLoad() - - /** - * onUnLoad Callback will be triggered if the View failed to show or it closed. - */ - fun onUnload(reason: UnloadReasons) - - /** - * onShouldShowLoadingIndicator callback will be triggered if View starts processing. - */ - fun onShouldShowLoadingIndicator() - - /** - * onShouldHideLoadingIndicator callback will be triggered if View ends processing. - */ - fun onShouldHideLoadingIndicator() -} - -/** - * Enum representing the reasons for unloading. - */ -enum class UnloadReasons { - /** - * Called when there are no offers to display so the view does not get loaded in. - */ - NO_OFFERS, - - /** - * View has been rendered and has been completed. - */ - FINISHED, - - /** - * Operation to fetch view took too long to resolve. - */ - TIMEOUT, - - /** - * Some error has occurred regarding the network. - */ - NETWORK_ERROR, - - /** - * View is empty. - */ - NO_WIDGET, - - /** - * Init request was not successful. - */ - INIT_FAILED, - - /** - * Placeholder string mismatch. - */ - UNKNOWN_PLACEHOLDER, - - /** - * Catch-all for all issues. - */ - UNKNOWN, - - ; - - companion object { - /** - * Returns the enum constant matching the provided string. - * If no match is found, UNKNOWN is returned. - * - * @param value the name of the enum constant to look up - * @return the corresponding UnloadReasons constant or UNKNOWN if no match is found - */ - fun from(value: String): UnloadReasons = try { - valueOf(value) - } catch (e: IllegalArgumentException) { - UNKNOWN - } - } -} diff --git a/android-core/src/main/kotlin/com/mparticle/Rokt.kt b/android-core/src/main/kotlin/com/mparticle/Rokt.kt index e531b7f44..9e39928af 100644 --- a/android-core/src/main/kotlin/com/mparticle/Rokt.kt +++ b/android-core/src/main/kotlin/com/mparticle/Rokt.kt @@ -20,7 +20,6 @@ class Rokt internal constructor(private val mConfigManager: ConfigManager, priva * * @param identifier The placement identifier * @param attributes User attributes to pass to Rokt - * @param callbacks Optional callback for Rokt events * @param embeddedViews Optional map of embedded view placeholders * @param fontTypefaces Optional map of font typefaces * @param config Optional Rokt configuration @@ -29,7 +28,6 @@ class Rokt internal constructor(private val mConfigManager: ConfigManager, priva fun selectPlacements( identifier: String, attributes: Map, - callbacks: MpRoktEventCallback? = null, embeddedViews: Map>? = null, fontTypefaces: Map>? = null, config: RoktConfig? = null, @@ -37,7 +35,7 @@ class Rokt internal constructor(private val mConfigManager: ConfigManager, priva if (mConfigManager.isEnabled) { val roktApi = mKitManager.roktKitApi if (roktApi != null) { - roktApi.selectPlacements(identifier, HashMap(attributes), callbacks, embeddedViews, fontTypefaces, config, buildPlacementOptions()) + roktApi.selectPlacements(identifier, HashMap(attributes), embeddedViews, fontTypefaces, config, buildPlacementOptions()) } else { Logger.warning("Rokt Kit is not available. Make sure the Rokt Kit is included in your app.") } diff --git a/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt b/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt index 68f9c628d..af5d05e13 100644 --- a/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt +++ b/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt @@ -1,7 +1,6 @@ package com.mparticle.internal import android.graphics.Typeface -import com.mparticle.MpRoktEventCallback import com.mparticle.RoktEvent import com.mparticle.rokt.PlacementOptions import com.mparticle.rokt.RoktConfig @@ -21,7 +20,6 @@ interface RoktKitApi { * * @param viewName The identifier for the placement view * @param attributes User attributes to pass to Rokt - * @param mpRoktEventCallback Optional callback for Rokt events * @param placeHolders Optional map of embedded view placeholders * @param fontTypefaces Optional map of font typefaces * @param config Optional Rokt configuration @@ -30,7 +28,6 @@ interface RoktKitApi { fun selectPlacements( viewName: String, attributes: Map, - mpRoktEventCallback: MpRoktEventCallback?, placeHolders: Map>?, fontTypefaces: Map>?, config: RoktConfig?, diff --git a/android-core/src/test/kotlin/com/mparticle/RoktTest.kt b/android-core/src/test/kotlin/com/mparticle/RoktTest.kt index 317f58626..fb299d5c1 100644 --- a/android-core/src/test/kotlin/com/mparticle/RoktTest.kt +++ b/android-core/src/test/kotlin/com/mparticle/RoktTest.kt @@ -84,28 +84,9 @@ class RoktTest { val config = RoktConfig.Builder().colorMode(RoktConfig.ColorMode.DARK).build() - val callbacks = - object : MpRoktEventCallback { - override fun onLoad() { - println("View loaded") - } - - override fun onUnload(reason: UnloadReasons) { - println("View unloaded due to: $reason") - } - - override fun onShouldShowLoadingIndicator() { - println("Show loading indicator") - } - - override fun onShouldHideLoadingIndicator() { - println("Hide loading indicator") - } - } rokt.selectPlacements( identifier = "testView", attributes = attributes, - callbacks = callbacks, embeddedViews = placeholders, fontTypefaces = fonts, config = config, @@ -118,7 +99,6 @@ class RoktTest { any(), any(), any(), - any(), ) } @@ -138,7 +118,6 @@ class RoktTest { isNull(), isNull(), isNull(), - isNull(), any(), ) } @@ -153,7 +132,7 @@ class RoktTest { attributes = HashMap(), ) - verify(roktKitApi, never()).selectPlacements(any(), any(), any(), any(), any(), any(), any()) + verify(roktKitApi, never()).selectPlacements(any(), any(), any(), any(), any(), any()) } @Test @@ -279,7 +258,6 @@ class RoktTest { isNull(), isNull(), isNull(), - isNull(), capture(optionsCaptor), ) assertTrue(optionsCaptor.value.jointSdkSelectPlacements >= currentTimeMillis) 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 c7b35f924..aa5be243f 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 @@ -15,7 +15,6 @@ import com.mparticle.BaseEvent; import com.mparticle.MPEvent; import com.mparticle.MParticle; -import com.mparticle.MpRoktEventCallback; import com.mparticle.RoktEvent; import com.mparticle.WrapperSdkVersion; import com.mparticle.commerce.CommerceEvent; @@ -601,7 +600,6 @@ public interface RoktListener { void selectPlacements(@NonNull String viewName, @NonNull Map attributes, - @Nullable MpRoktEventCallback mpRoktEventCallback, @Nullable Map> placeHolders, @Nullable Map> fontTypefaces, @Nullable FilteredMParticleUser user, diff --git a/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt b/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt index 68fd73d4c..ecf5e78ce 100644 --- a/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt +++ b/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt @@ -2,7 +2,6 @@ package com.mparticle.kits import android.graphics.Typeface import com.mparticle.MParticle -import com.mparticle.MpRoktEventCallback import com.mparticle.RoktEvent import com.mparticle.identity.IdentityApi import com.mparticle.identity.IdentityApiRequest @@ -31,7 +30,6 @@ internal class RoktKitApiImpl(private val roktListener: KitIntegration.RoktListe override fun selectPlacements( viewName: String, attributes: Map, - mpRoktEventCallback: MpRoktEventCallback?, placeHolders: Map>?, fontTypefaces: Map>?, config: RoktConfig?, @@ -54,7 +52,6 @@ internal class RoktKitApiImpl(private val roktListener: KitIntegration.RoktListe roktListener.selectPlacements( viewName, finalAttributes, - mpRoktEventCallback, placeHolders, fontTypefaces, FilteredMParticleUser.getInstance(user?.id ?: 0L, kitIntegration), 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 95de0b0c5..f74066d64 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 @@ -8,7 +8,6 @@ import com.mparticle.BaseEvent import com.mparticle.MPEvent import com.mparticle.MParticle import com.mparticle.MParticleOptions -import com.mparticle.MpRoktEventCallback import com.mparticle.RoktEvent import com.mparticle.WrapperSdk import com.mparticle.WrapperSdkVersion @@ -1317,7 +1316,7 @@ class KitManagerImplTest { val roktApi = manager.getRoktKitApi() Assert.assertNotNull(roktApi) - roktApi!!.selectPlacements("Test", attributes, null, null, null, null, placementOptions) + roktApi!!.selectPlacements("Test", attributes, null, null, null, placementOptions) val optionsCaptor = ArgumentCaptor.forClass(PlacementOptions::class.java) verify(roktListener as KitIntegration.RoktListener).selectPlacements( @@ -1327,7 +1326,6 @@ class KitManagerImplTest { any(), any(), any(), - any(), optionsCaptor.capture(), ) assertSame(placementOptions, optionsCaptor.value) @@ -1354,7 +1352,7 @@ class KitManagerImplTest { val roktApi = manager.getRoktKitApi() Assert.assertNotNull(roktApi) - roktApi!!.selectPlacements("Test", attributes, null, null, null, null) + roktApi!!.selectPlacements("Test", attributes, null, null, null) val optionsCaptor = ArgumentCaptor.forClass(PlacementOptions::class.java) verify(roktListener as KitIntegration.RoktListener).selectPlacements( @@ -1364,7 +1362,6 @@ class KitManagerImplTest { any(), any(), any(), - any(), optionsCaptor.capture(), ) assertNull(optionsCaptor.value) @@ -1809,7 +1806,6 @@ class KitManagerImplTest { override fun selectPlacements( viewName: String, attributes: MutableMap, - mpRoktEventCallback: MpRoktEventCallback?, placeHolders: MutableMap>?, fontTypefaces: MutableMap>?, user: FilteredMParticleUser?, diff --git a/android-kit-base/src/test/kotlin/com/mparticle/kits/RoktKitApiImplTest.kt b/android-kit-base/src/test/kotlin/com/mparticle/kits/RoktKitApiImplTest.kt index 65643eba5..0e9302eba 100644 --- a/android-kit-base/src/test/kotlin/com/mparticle/kits/RoktKitApiImplTest.kt +++ b/android-kit-base/src/test/kotlin/com/mparticle/kits/RoktKitApiImplTest.kt @@ -61,7 +61,7 @@ class RoktKitApiImplTest { "country" to "US", ) - roktApi.selectPlacements("Test", attributes, null, null, null, null, null) + roktApi.selectPlacements("Test", attributes, null, null, null, null) @Suppress("UNCHECKED_CAST") val attributesCaptor = ArgumentCaptor.forClass(Map::class.java) as ArgumentCaptor> @@ -73,7 +73,6 @@ class RoktKitApiImplTest { any(), any(), any(), - any(), ) val captured = attributesCaptor.value assertEquals("(123) 456-9898", captured["no"]) @@ -96,7 +95,7 @@ class RoktKitApiImplTest { val placementOptions = PlacementOptions(jointSdkSelectPlacements = 123L) - roktApi.selectPlacements("Test", emptyMap(), null, null, null, null, placementOptions) + roktApi.selectPlacements("Test", emptyMap(), null, null, null, placementOptions) val optionsCaptor = ArgumentCaptor.forClass(PlacementOptions::class.java) verify(roktListener).selectPlacements( @@ -106,7 +105,6 @@ class RoktKitApiImplTest { any(), any(), any(), - any(), optionsCaptor.capture(), ) assertEquals(placementOptions, optionsCaptor.value) diff --git a/kits/rokt/rokt/build.gradle b/kits/rokt/rokt/build.gradle index 4d49a2422..d3724b07a 100644 --- a/kits/rokt/rokt/build.gradle +++ b/kits/rokt/rokt/build.gradle @@ -75,7 +75,7 @@ dependencies { implementation 'androidx.annotation:annotation:1.5.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' implementation 'androidx.compose.runtime:runtime' - api 'com.rokt:roktsdk:4.14.0' + api 'com.rokt:roktsdk:5.1.0' testImplementation files('libs/java-json.jar') testImplementation 'com.squareup.assertj:assertj-android:1.2.0' diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt index 091ba6356..18d392741 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt @@ -10,8 +10,6 @@ import com.mparticle.BuildConfig import com.mparticle.MPEvent import com.mparticle.MParticle import com.mparticle.MParticle.IdentityType -import com.mparticle.MpRoktEventCallback -import com.mparticle.UnloadReasons import com.mparticle.WrapperSdk import com.mparticle.WrapperSdkVersion import com.mparticle.commerce.CommerceEvent @@ -24,7 +22,6 @@ import com.mparticle.rokt.PlacementOptions import com.mparticle.rokt.RoktConfig import com.mparticle.rokt.RoktEmbeddedView import com.rokt.roktsdk.Rokt -import com.rokt.roktsdk.Rokt.RoktCallback import com.rokt.roktsdk.Rokt.SdkFrameworkType.Android import com.rokt.roktsdk.Rokt.SdkFrameworkType.Cordova import com.rokt.roktsdk.Rokt.SdkFrameworkType.Flutter @@ -55,10 +52,8 @@ class RoktKit : KitIntegration(), CommerceListener, IdentityListener, - RoktListener, - Rokt.RoktCallback { + RoktListener { private var applicationContext: Context? = null - private var mpRoktEventCallback: MpRoktEventCallback? = null private var hashedEmailUserIdentityType: String? = null override fun getName(): String = NAME @@ -96,11 +91,6 @@ class RoktKit : application = application, fontPostScriptNames = fontPostScriptNames, fontFilePathMap = fontFilePathMap, - callback = object : Rokt.RoktInitCallback { - override fun onInitComplete(success: Boolean) { - Logger.verbose("Rokt Kit Initialization success: $success") - } - }, mParticleSdkVersion = mparticleVersion, mParticleKitVersion = mparticleVersion, ) @@ -183,7 +173,6 @@ class RoktKit : override fun selectPlacements( viewName: String, attributes: Map, - mpRoktEventCallback: MpRoktEventCallback?, placeHolders: MutableMap>?, fontTypefaces: MutableMap>?, filterUser: FilteredMParticleUser?, @@ -200,28 +189,24 @@ class RoktKit : override fun onHeightChanged(height: Int) { it.onHeightChanged(height) } - - override fun onMarginChanged(start: Int, top: Int, end: Int, bottom: Int) { - it.onMarginChanged(start, top, end, bottom) - } }, ) } entry.key to WeakReference(widget) }?.toMap() - this.mpRoktEventCallback = mpRoktEventCallback val finalAttributes = prepareFinalAttributes(filterUser, attributes) val roktConfig = mpRoktConfig?.toRoktSdkConfig() - Rokt.execute( - viewName, - finalAttributes, - this, + + Rokt.selectPlacements( + identifier = viewName, + attributes = finalAttributes, + eventCollector = null, // Pass placeholders and fontTypefaces only if they are not empty or null - placeholders.takeIf { it?.isNotEmpty() == true }, - fontTypefaces.takeIf { it?.isNotEmpty() == true }, - roktConfig, - placementOptions?.toRoktSdkPlacementOptions(), + placeholders = placeholders.takeIf { it?.isNotEmpty() == true }, + fontTypefaces = fontTypefaces.takeIf { it?.isNotEmpty() == true }, + config = roktConfig, + placementOptions = placementOptions?.toRoktSdkPlacementOptions(), ) } @@ -280,28 +265,28 @@ class RoktKit : is RoktEvent.HideLoadingIndicator -> com.mparticle.RoktEvent.HideLoadingIndicator is RoktEvent.ShowLoadingIndicator -> com.mparticle.RoktEvent.ShowLoadingIndicator is RoktEvent.FirstPositiveEngagement -> com.mparticle.RoktEvent.FirstPositiveEngagement( - event.id, + event.identifier, ) is RoktEvent.PositiveEngagement -> com.mparticle.RoktEvent.PositiveEngagement( - event.id, + event.identifier, ) - is RoktEvent.OfferEngagement -> com.mparticle.RoktEvent.OfferEngagement(event.id) - is RoktEvent.OpenUrl -> com.mparticle.RoktEvent.OpenUrl(event.id, event.url) - is RoktEvent.PlacementClosed -> com.mparticle.RoktEvent.PlacementClosed(event.id) + is RoktEvent.OfferEngagement -> com.mparticle.RoktEvent.OfferEngagement(event.identifier) + is RoktEvent.OpenUrl -> com.mparticle.RoktEvent.OpenUrl(event.identifier, event.url) + is RoktEvent.PlacementClosed -> com.mparticle.RoktEvent.PlacementClosed(event.identifier) is RoktEvent.PlacementCompleted -> com.mparticle.RoktEvent.PlacementCompleted( - event.id, + event.identifier, ) - is RoktEvent.PlacementFailure -> com.mparticle.RoktEvent.PlacementFailure(event.id) + is RoktEvent.PlacementFailure -> com.mparticle.RoktEvent.PlacementFailure(event.identifier) is RoktEvent.PlacementInteractive -> com.mparticle.RoktEvent.PlacementInteractive( - event.id, + event.identifier, ) - is RoktEvent.PlacementReady -> com.mparticle.RoktEvent.PlacementReady(event.id) + is RoktEvent.PlacementReady -> com.mparticle.RoktEvent.PlacementReady(event.identifier) is RoktEvent.CartItemInstantPurchase -> com.mparticle.RoktEvent.CartItemInstantPurchase( - placementId = event.placementId, + placementId = event.identifier, cartItemId = event.cartItemId, catalogItemId = event.catalogItemId, currency = event.currency, @@ -357,18 +342,13 @@ class RoktKit : deferredAttributes?.complete(finalAttributes) } - suspend fun runComposableWithCallback( - attributes: Map, - mpRoktEventCallback: MpRoktEventCallback?, - onResult: (Map, RoktCallback) -> Unit, - ) { + suspend fun prepareComposableAttributes(attributes: Map, onResult: (Map) -> Unit) { val instance = MParticle.getInstance() deferredAttributes = CompletableDeferred() instance?.Internal()?.kitManager?.roktKitApi?.prepareAttributesAsync(attributes) - this.mpRoktEventCallback = mpRoktEventCallback CoroutineScope(Dispatchers.Default).launch { val resultAttributes = deferredAttributes!!.await() - onResult(resultAttributes, this@RoktKit) + onResult(resultAttributes) } } @@ -467,33 +447,6 @@ class RoktKit : const val NO_ROKT_ACCOUNT_ID = "No Rokt account ID provided, can't initialize kit." const val NO_APP_VERSION_FOUND = "No App version found, can't initialize kit." } - - override fun onLoad() { - mpRoktEventCallback?.onLoad() - } - - override fun onShouldHideLoadingIndicator() { - mpRoktEventCallback?.onShouldHideLoadingIndicator() - } - - override fun onShouldShowLoadingIndicator() { - mpRoktEventCallback?.onShouldShowLoadingIndicator() - } - - override fun onUnload(reason: Rokt.UnloadReasons) { - mpRoktEventCallback?.onUnload( - when (reason) { - Rokt.UnloadReasons.NO_OFFERS -> UnloadReasons.NO_OFFERS - Rokt.UnloadReasons.FINISHED -> UnloadReasons.FINISHED - Rokt.UnloadReasons.TIMEOUT -> UnloadReasons.TIMEOUT - Rokt.UnloadReasons.NETWORK_ERROR -> UnloadReasons.NETWORK_ERROR - Rokt.UnloadReasons.NO_WIDGET -> UnloadReasons.NO_WIDGET - Rokt.UnloadReasons.INIT_FAILED -> UnloadReasons.INIT_FAILED - Rokt.UnloadReasons.UNKNOWN_PLACEHOLDER -> UnloadReasons.UNKNOWN_PLACEHOLDER - Rokt.UnloadReasons.UNKNOWN -> UnloadReasons.UNKNOWN - }, - ) - } } fun PackageManager.getPackageInfoForApp(packageName: String, flags: Int = 0): PackageInfo = diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktLayout.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktLayout.kt index 0987ea40d..1dc9a7c43 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktLayout.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktLayout.kt @@ -5,10 +5,8 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import com.mparticle.MpRoktEventCallback import com.mparticle.rokt.PlacementOptions import com.mparticle.rokt.RoktConfig -import com.rokt.roktsdk.Rokt @Composable @Suppress("FunctionName") @@ -18,12 +16,11 @@ fun RoktLayout( attributes: Map, location: String, modifier: Modifier = Modifier, - mpRoktEventCallback: MpRoktEventCallback? = null, config: RoktConfig? = null, ) { var placementOptions: PlacementOptions? = null val instance = RoktKit.instance - val resultMapState = remember { mutableStateOf(null) } + val resolvedAttributes = remember { mutableStateOf?>(null) } if (sdkTriggered) { // Capture the timestamp when the SDK is triggered placementOptions = PlacementOptions( @@ -31,27 +28,21 @@ fun RoktLayout( dynamicPerformanceMarkers = mapOf(), ) LaunchedEffect(Unit) { - instance?.runComposableWithCallback( - HashMap(attributes), - mpRoktEventCallback, - { resultMap, callback -> - resultMapState.value = RoktResult(resultMap, callback) - }, - ) + instance?.prepareComposableAttributes(HashMap(attributes)) { result -> + resolvedAttributes.value = result + } } } - resultMapState.value?.let { resultMap -> + resolvedAttributes.value?.let { finalAttributes -> com.rokt.roktsdk.RoktLayout( - sdkTriggered, identifier, modifier, resultMap.attributes, location, - onLoad = { resultMap.callback.onLoad() }, - onShouldShowLoadingIndicator = { resultMap.callback.onShouldShowLoadingIndicator() }, - onShouldHideLoadingIndicator = { resultMap.callback.onShouldHideLoadingIndicator() }, - onUnload = { reason -> resultMap.callback.onUnload(reason) }, + sdkTriggered = sdkTriggered, + identifier = identifier, + modifier = modifier, + attributes = finalAttributes, + location = location, config = config?.toRoktSdkConfig(), placementOptions = placementOptions?.toRoktSdkPlacementOptions(), ) } } - -data class RoktResult(val attributes: Map, val callback: Rokt.RoktCallback) diff --git a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt index 9717978a6..ad4d56608 100644 --- a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt +++ b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt @@ -131,13 +131,14 @@ class RoktKitTests { mockkObject(Rokt) val capturedAttributesSlot = slot>() every { - Rokt.execute( + Rokt.selectPlacements( any(), capture(capturedAttributesSlot), - any(), - null, - null, - null, + any(), + any(), + any(), + any(), + any(), ) } just runs @@ -160,7 +161,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test_view", attributes = inputAttributes, - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -191,13 +191,14 @@ class RoktKitTests { mockkObject(Rokt) val capturedAttributesSlot = slot>() every { - Rokt.execute( + Rokt.selectPlacements( any(), capture(capturedAttributesSlot), - any(), - null, - null, - null, + any(), + any(), + any(), + any(), + any(), ) } just runs @@ -217,7 +218,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test_view", attributes = emptyMap(), - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -240,13 +240,14 @@ class RoktKitTests { mockkObject(Rokt) val capturedAttributesSlot = slot>() every { - Rokt.execute( + Rokt.selectPlacements( any(), capture(capturedAttributesSlot), - any(), - null, - null, - null, + any(), + any(), + any(), + any(), + any(), ) } just runs @@ -266,7 +267,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test_view", attributes = emptyMap(), - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -289,13 +289,14 @@ class RoktKitTests { mockkObject(Rokt) val capturedAttributesSlot = slot>() every { - Rokt.execute( + Rokt.selectPlacements( any(), capture(capturedAttributesSlot), - any(), - null, - null, - null, + any(), + any(), + any(), + any(), + any(), ) } just runs @@ -315,7 +316,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test_view", attributes = emptyMap(), - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -338,13 +338,14 @@ class RoktKitTests { mockkObject(Rokt) val capturedAttributesSlot = slot>() every { - Rokt.execute( + Rokt.selectPlacements( any(), capture(capturedAttributesSlot), - any(), - null, - null, - null, + any(), + any(), + any(), + any(), + any(), ) } just runs @@ -382,7 +383,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test", attributes = inputAttributes, - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -413,13 +413,14 @@ class RoktKitTests { mockkObject(Rokt) val capturedAttributesSlot = slot>() every { - Rokt.execute( + Rokt.selectPlacements( any(), capture(capturedAttributesSlot), - any(), - null, - null, - null, + any(), + any(), + any(), + any(), + any(), ) } just runs @@ -457,7 +458,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test", attributes = inputAttributes, - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -925,7 +925,7 @@ class RoktKitTests { fun testRoktEventMapping_CartItemInstantPurchase() = runTest { mockkObject(Rokt) val roktEvent = RoktEvent.CartItemInstantPurchase( - placementId = "test-placement-purchase", + identifier = "test-placement-purchase", cartItemId = "cart-item-123", catalogItemId = "catalog-item-456", currency = "USD", @@ -1333,10 +1333,11 @@ class RoktKitTests { // Arrange mockkObject(Rokt) every { - Rokt.execute( + Rokt.selectPlacements( any(), any>(), - any(), + any(), + any(), any(), any(), any(), @@ -1358,7 +1359,6 @@ class RoktKitTests { roktKit.selectPlacements( viewName = "test_view", attributes = testAttributes, - mpRoktEventCallback = null, placeHolders = null, fontTypefaces = null, filterUser = mockFilterUser, @@ -1367,10 +1367,11 @@ class RoktKitTests { ) verify(exactly = 1) { - Rokt.execute( + Rokt.selectPlacements( any(), any>(), - any(), + any(), + any(), any(), any(), any(), From b3706d6cc2bddc84be0b53e8a5b846104bf8795e Mon Sep 17 00:00:00 2001 From: James Newman Date: Mon, 18 May 2026 18:26:34 -0400 Subject: [PATCH 2/3] refactor: align mParticle Rokt API naming with Rokt SDK 5.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renames public API symbols to match Rokt 5.x's vocabulary: - com.mparticle.RoktEvent.*.placementId → identifier on all event classes (OfferEngagement, PositiveEngagement, FirstPositiveEngagement, PlacementInteractive, PlacementReady, PlacementClosed, PlacementCompleted, PlacementFailure, OpenUrl, CartItemInstantPurchase) - Rokt.purchaseFinalized(placementId, ..., status) → (identifier, ..., success); propagated through RoktKitApi, RoktKitApiImpl, KitIntegration.RoktListener, and RoktKit Rename-only — no behavior change. BREAKING CHANGE: RoktEvent.placementId is renamed to identifier and Rokt.purchaseFinalized parameters renamed from (placementId, status) to (identifier, success). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/main/kotlin/com/mparticle/Rokt.kt | 8 ++-- .../main/kotlin/com/mparticle/RoktEvent.kt | 40 +++++++++---------- .../com/mparticle/internal/RoktKitApi.kt | 6 +-- .../com/mparticle/kits/KitIntegration.java | 2 +- .../com/mparticle/kits/RoktKitApiImpl.kt | 4 +- .../com/mparticle/kits/KitManagerImplTest.kt | 6 +-- .../main/kotlin/com/mparticle/kits/RoktKit.kt | 6 +-- .../kotlin/com/mparticle/kits/RoktKitTests.kt | 2 +- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/android-core/src/main/kotlin/com/mparticle/Rokt.kt b/android-core/src/main/kotlin/com/mparticle/Rokt.kt index 9e39928af..0df3cc382 100644 --- a/android-core/src/main/kotlin/com/mparticle/Rokt.kt +++ b/android-core/src/main/kotlin/com/mparticle/Rokt.kt @@ -57,13 +57,13 @@ class Rokt internal constructor(private val mConfigManager: ConfigManager, priva /** * Notify Rokt that a purchase has been finalized. * - * @param placementId The placement identifier + * @param identifier The placement identifier * @param catalogItemId The catalog item identifier - * @param status Whether the purchase was successful + * @param success Whether the purchase was successful */ - fun purchaseFinalized(placementId: String, catalogItemId: String, status: Boolean) { + fun purchaseFinalized(identifier: String, catalogItemId: String, success: Boolean) { if (mConfigManager.isEnabled) { - mKitManager.roktKitApi?.purchaseFinalized(placementId, catalogItemId, status) + mKitManager.roktKitApi?.purchaseFinalized(identifier, catalogItemId, success) } } diff --git a/android-core/src/main/kotlin/com/mparticle/RoktEvent.kt b/android-core/src/main/kotlin/com/mparticle/RoktEvent.kt index fa9d6aa85..b271ed8b0 100644 --- a/android-core/src/main/kotlin/com/mparticle/RoktEvent.kt +++ b/android-core/src/main/kotlin/com/mparticle/RoktEvent.kt @@ -15,52 +15,52 @@ sealed interface RoktEvent { /** * OfferEngagement event will be triggered if User engaged with the offer - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class OfferEngagement(val placementId: String) : RoktEvent + data class OfferEngagement(val identifier: String) : RoktEvent /** * PositiveEngagement event will be triggered if User positively engaged with the offer - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class PositiveEngagement(val placementId: String) : RoktEvent + data class PositiveEngagement(val identifier: String) : RoktEvent /** * FirstPositiveEngagement event will be triggered when the user positively engaged with the offer first time - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class FirstPositiveEngagement(val placementId: String) : RoktEvent + data class FirstPositiveEngagement(val identifier: String) : RoktEvent /** * PlacementInteractive event will be triggered when placement has been rendered and is interactable - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class PlacementInteractive(val placementId: String) : RoktEvent + data class PlacementInteractive(val identifier: String) : RoktEvent /** * PlacementReady event will be triggered when placement is ready to display but has not rendered content yet - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class PlacementReady(val placementId: String) : RoktEvent + data class PlacementReady(val identifier: String) : RoktEvent /** * PlacementClosed event will be triggered when placement closes by user - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class PlacementClosed(val placementId: String) : RoktEvent + data class PlacementClosed(val identifier: String) : RoktEvent /** * PlacementCompleted event will be triggered when the offer progression moves to the end and no more * offer to display - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event */ - data class PlacementCompleted(val placementId: String) : RoktEvent + data class PlacementCompleted(val identifier: String) : RoktEvent /** * PlacementFailure event will be triggered when placement could not be displayed due to some failure - * @param placementId - optional identifier for the placement emitting the event + * @param identifier - optional identifier for the placement emitting the event */ - data class PlacementFailure(val placementId: String? = null) : RoktEvent + data class PlacementFailure(val identifier: String? = null) : RoktEvent /** * InitComplete event will be triggered when SDK has finished initialization @@ -70,15 +70,15 @@ sealed interface RoktEvent { /** * OpenUrl event will be triggered when user clicks on a link and the link target is set to Passthrough - * @param placementId - identifier for the placement emitting the event + * @param identifier - identifier for the placement emitting the event * @param url - url to open */ - data class OpenUrl(val placementId: String, val url: String) : RoktEvent + data class OpenUrl(val identifier: String, val url: String) : RoktEvent /** * CartItemInstantPurchase event will be triggered when the catalog item purchase is initiated * by the user - * @property placementId The layout identifier. + * @property identifier The layout identifier. * @property cartItemId The cart item identifier. * @property catalogItemId The catalog item identifier. * @property currency The currency used for the purchase. @@ -89,7 +89,7 @@ sealed interface RoktEvent { * @property unitPrice The unit price of the cart item. */ data class CartItemInstantPurchase( - val placementId: String, + val identifier: String, val cartItemId: String, val catalogItemId: String, val currency: String, diff --git a/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt b/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt index af5d05e13..1c66d4d38 100644 --- a/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt +++ b/android-core/src/main/kotlin/com/mparticle/internal/RoktKitApi.kt @@ -45,11 +45,11 @@ interface RoktKitApi { /** * Notify Rokt that a purchase has been finalized. * - * @param placementId The placement identifier + * @param identifier The placement identifier * @param catalogItemId The catalog item identifier - * @param status Whether the purchase was successful + * @param success Whether the purchase was successful */ - fun purchaseFinalized(placementId: String, catalogItemId: String, status: Boolean) + fun purchaseFinalized(identifier: String, catalogItemId: String, success: Boolean) /** * Close any active Rokt placements. 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 aa5be243f..4663bfaca 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 @@ -618,7 +618,7 @@ void enrichAttributes( */ void setWrapperSdkVersion(@NonNull WrapperSdkVersion wrapperSdkVersion); - void purchaseFinalized(@NonNull String placementId, @NonNull String catalogItemId, boolean status); + void purchaseFinalized(@NonNull String identifier, @NonNull String catalogItemId, boolean success); void close(); diff --git a/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt b/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt index ecf5e78ce..54c886d11 100644 --- a/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt +++ b/android-kit-base/src/main/kotlin/com/mparticle/kits/RoktKitApiImpl.kt @@ -72,9 +72,9 @@ internal class RoktKitApiImpl(private val roktListener: KitIntegration.RoktListe flowOf() } - override fun purchaseFinalized(placementId: String, catalogItemId: String, status: Boolean) { + override fun purchaseFinalized(identifier: String, catalogItemId: String, success: Boolean) { try { - roktListener.purchaseFinalized(placementId, catalogItemId, status) + roktListener.purchaseFinalized(identifier, catalogItemId, success) } catch (e: Exception) { Logger.warning("Failed to call purchaseFinalized for Rokt Kit: ${e.message}") } 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 f74066d64..0b31670cc 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 @@ -1835,11 +1835,11 @@ class KitManagerImplTest { } override fun purchaseFinalized( - placementId: String, + identifier: String, catalogItemId: String, - status: Boolean, + success: Boolean, ) { - Logger.info("purchaseFinalized with placementId: $placementId catalogItemId : $catalogItemId status : $status ") + Logger.info("purchaseFinalized with identifier: $identifier catalogItemId : $catalogItemId success : $success ") } override fun close() { diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt index 18d392741..52b60d23d 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt @@ -286,7 +286,7 @@ class RoktKit : is RoktEvent.PlacementReady -> com.mparticle.RoktEvent.PlacementReady(event.identifier) is RoktEvent.CartItemInstantPurchase -> com.mparticle.RoktEvent.CartItemInstantPurchase( - placementId = event.identifier, + identifier = event.identifier, cartItemId = event.cartItemId, catalogItemId = event.catalogItemId, currency = event.currency, @@ -311,8 +311,8 @@ class RoktKit : Rokt.setFrameworkType(sdkFrameworkType) } - override fun purchaseFinalized(placementId: String, catalogItemId: String, status: Boolean) { - Rokt.purchaseFinalized(placementId, catalogItemId, status) + override fun purchaseFinalized(identifier: String, catalogItemId: String, success: Boolean) { + Rokt.purchaseFinalized(identifier, catalogItemId, success) } override fun close() { diff --git a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt index ad4d56608..0e8745062 100644 --- a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt +++ b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt @@ -942,7 +942,7 @@ class RoktKitTests { assertEquals( result, com.mparticle.RoktEvent.CartItemInstantPurchase( - placementId = "test-placement-purchase", + identifier = "test-placement-purchase", cartItemId = "cart-item-123", catalogItemId = "catalog-item-456", currency = "USD", From a81dddc6d533e57ad2e54bf4d5701fa46eb25de4 Mon Sep 17 00:00:00 2001 From: James Newman Date: Mon, 18 May 2026 18:32:17 -0400 Subject: [PATCH 3/3] refactor: drop dead onMarginChanged from RoktLayoutDimensionCallBack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rokt SDK 5.x removed onMarginChanged from RoktWidgetDimensionCallBack; the kit already dropped its override, but mParticle's mirror interface still forced customers to implement an onMarginChanged that never fires. onHeightChanged remains the only method on RoktLayoutDimensionCallBack and is still the way to observe Widget height changes — 5.x exposes no event-based equivalent. BREAKING CHANGE: RoktLayoutDimensionCallBack.onMarginChanged is removed. Customers implementing this interface should drop the override. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../kotlin/com/mparticle/rokt/RoktLayoutDimensionCallBack.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/android-core/src/main/kotlin/com/mparticle/rokt/RoktLayoutDimensionCallBack.kt b/android-core/src/main/kotlin/com/mparticle/rokt/RoktLayoutDimensionCallBack.kt index e22535c90..36ca19c23 100644 --- a/android-core/src/main/kotlin/com/mparticle/rokt/RoktLayoutDimensionCallBack.kt +++ b/android-core/src/main/kotlin/com/mparticle/rokt/RoktLayoutDimensionCallBack.kt @@ -2,6 +2,4 @@ package com.mparticle.rokt interface RoktLayoutDimensionCallBack { fun onHeightChanged(height: Int) - - fun onMarginChanged(start: Int, top: Int, end: Int, bottom: Int) }