Skip to content

Commit 2487f70

Browse files
authored
feat: SQDSDKS-7422 - Add all Rokt events (#587)
1 parent 88c73b8 commit 2487f70

17 files changed

Lines changed: 515 additions & 9 deletions

File tree

.github/workflows/cross-platform-tests.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ jobs:
5656
force-avd-creation: false
5757
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
5858
disable-animations: true
59-
script: ./gradlew runAndroid
59+
script: |
60+
adb uninstall com.mparticle.kittests || true
61+
adb uninstall com.mparticle.kits.test || true
62+
adb uninstall com.mparticle.legacyTest || true
63+
adb uninstall com.mparticle.test || true
64+
adb uninstall com.mparticle.cpt.testing.test || true
65+
./gradlew runAndroid
6066
- name: "Archive Test Results"
6167
if: ${{ always() }}
6268
uses: actions/upload-artifact@v4

.github/workflows/pull-request.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,17 @@ jobs:
4747
force-avd-creation: false
4848
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
4949
disable-animations: true
50-
#script: ./gradlew :android-core:cAT :android-kit-base:cAT --stacktrace
5150
script: |
5251
# Disable benchmark tests as they do not work on emulators
52+
adb uninstall com.mparticle.kittests || true
5353
adb uninstall com.mparticle.kits.test || true
54-
adb uninstall com.mparticle.testutils.test || true
54+
adb uninstall com.mparticle.legacyTest || true
55+
adb uninstall com.mparticle.test || true
56+
5557
./gradlew connectedCheck --stacktrace
5658
57-
adb uninstall com.mparticle.kits.test || true
58-
adb uninstall com.mparticle.testutils.test || true
59-
./gradlew :android-core:cAT :android-kit-base:cAT -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=none
59+
./gradlew :android-core:cAT -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=none
60+
./gradlew :android-kit-base:cAT -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=none
6061
- name: "Archive Instrumented Tests Results"
6162
uses: actions/upload-artifact@v4
6263
if: always()
@@ -102,7 +103,12 @@ jobs:
102103
disable-animations: true
103104
script: |
104105
# Disable benchmark tests as they do not work on emulators
105-
adb uninstall com.mparticle.test; ./gradlew connectedCheck --stacktrace
106+
adb uninstall com.mparticle.kittests || true
107+
adb uninstall com.mparticle.kits.test || true
108+
adb uninstall com.mparticle.legacyTest || true
109+
adb uninstall com.mparticle.test || true
110+
111+
./gradlew connectedCheck --stacktrace
106112
./gradlew -Porchestrator=true :android-core:cAT -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=none
107113
- name: "Archive Instrumented Orchestrator Tests Results"
108114
uses: actions/upload-artifact@v4

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ local.properties
2323

2424
# Keystore
2525
*keystore
26+
!debug.keystore
2627

2728
# OS X files
2829
.DS_Store

android-core/proguard.pro

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,22 @@
207207
-keep class com.mparticle.rokt.RoktEmbeddedView { *; }
208208
-keep class com.mparticle.rokt.RoktLayoutDimensionCallBack { *; }
209209

210+
# Preserve annotation classes
211+
-keep class androidx.annotation.NonNull { *; }
212+
-keep class androidx.annotation.Nullable { *; }
213+
-keepclassmembers class com.mparticle.** {
214+
@androidx.annotation.NonNull *;
215+
@androidx.annotation.Nullable *;
216+
}
217+
210218
# Preserve all method signatures in the Rokt class to prevent overload resolution issues
211219
-keepclassmembers class com.mparticle.Rokt {
212-
public void selectPlacements(...);
213-
public void purchaseFinalized(...);
220+
*;
214221
}
222+
-keepclassmembers class com.mparticle.KitIntegration$RoktListener* {
223+
*;
224+
}
225+
215226
-keep public class com.mparticle.audience.* {
216227
*;
217228
}
@@ -249,3 +260,6 @@
249260
-keep interface com.mparticle.MpRoktEventCallback { *; }
250261
-keep interface com.mparticle.UnloadReasons { *; }
251262
-keep class com.mparticle.UnloadReasons { *; }
263+
-keep class com.mparticle.RoktEvent { *; }
264+
-keepclassmembers class com.mparticle.RoktEvent { *; }
265+
-keepclasseswithmembers class com.mparticle.RoktEvent$* { *; }

android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.mparticle.internal;
22

3+
import static kotlinx.coroutines.flow.FlowKt.flowOf;
4+
35
import android.app.Activity;
46
import android.content.Context;
57
import android.content.Intent;
@@ -18,6 +20,7 @@
1820
import com.mparticle.MParticle;
1921
import com.mparticle.MParticleOptions;
2022
import com.mparticle.MpRoktEventCallback;
23+
import com.mparticle.RoktEvent;
2124
import com.mparticle.WrapperSdkVersion;
2225
import com.mparticle.consent.ConsentState;
2326
import com.mparticle.identity.IdentityApiRequest;
@@ -39,6 +42,8 @@
3942
import java.util.TreeMap;
4043
import java.util.concurrent.ConcurrentLinkedQueue;
4144

45+
import kotlinx.coroutines.flow.Flow;
46+
4247
public class KitFrameworkWrapper implements KitManager {
4348
private final Context mContext;
4449
final CoreCallbacks mCoreCallbacks;
@@ -509,6 +514,7 @@ public void updateDataplan(@Nullable MParticleOptions.DataplanOptions dataplanOp
509514
}
510515
}
511516

517+
@NonNull
512518
@Override
513519
public Map<Integer, KitStatus> getKitStatus() {
514520
if (mKitManager != null) {
@@ -669,6 +675,15 @@ public void execute(@NonNull String viewName,
669675
}
670676
}
671677

678+
@Override
679+
public Flow<RoktEvent> events(@NonNull String identifier) {
680+
if (mKitManager != null) {
681+
return mKitManager.events(identifier);
682+
} else {
683+
return flowOf();
684+
}
685+
}
686+
672687
@Override
673688
public void setWrapperSdkVersion(@NonNull WrapperSdkVersion wrapperSdkVersion) {
674689
if (mKitManager != null) {

android-core/src/main/java/com/mparticle/internal/KitManager.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.mparticle.MParticle;
1818
import com.mparticle.MParticleOptions;
1919
import com.mparticle.MpRoktEventCallback;
20+
import com.mparticle.RoktEvent;
2021
import com.mparticle.WrapperSdkVersion;
2122
import com.mparticle.consent.ConsentState;
2223
import com.mparticle.identity.IdentityApiRequest;
@@ -31,6 +32,8 @@
3132
import java.util.Map;
3233
import java.util.Set;
3334

35+
import kotlinx.coroutines.flow.Flow;
36+
3437
public interface KitManager {
3538

3639
WeakReference<Activity> getCurrentActivity();
@@ -133,6 +136,8 @@ void execute(@NonNull String identifier,
133136
@Nullable Map<String, WeakReference<Typeface>> fontTypefaces,
134137
@Nullable RoktConfig config);
135138

139+
Flow<RoktEvent> events(@NonNull String identifier);
140+
136141
void setWrapperSdkVersion(@NonNull WrapperSdkVersion wrapperSdkVersion);
137142

138143
void purchaseFinalized(@NonNull String placementId, @NonNull String catalogItemId, boolean status);

android-core/src/main/kotlin/com/mparticle/Rokt.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import com.mparticle.internal.KitManager
66
import com.mparticle.internal.listeners.ApiClass
77
import com.mparticle.rokt.RoktConfig
88
import com.mparticle.rokt.RoktEmbeddedView
9+
import kotlinx.coroutines.flow.Flow
10+
import kotlinx.coroutines.flow.flowOf
911
import java.lang.ref.WeakReference
1012

1113
@ApiClass
@@ -28,6 +30,14 @@ class Rokt internal constructor(
2830
}
2931
}
3032

33+
fun events(identifier: String) : Flow<RoktEvent> {
34+
return if (mConfigManager.isEnabled) {
35+
mKitManager.events(identifier)
36+
} else {
37+
flowOf()
38+
}
39+
}
40+
3141
fun purchaseFinalized(placementId: String, catalogItemId: String, status: Boolean) {
3242
if (mConfigManager.isEnabled) {
3343
mKitManager.purchaseFinalized(placementId, catalogItemId, status)
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.mparticle
2+
3+
// RoktEvent interface for handling events from the Rokt SDK.
4+
sealed interface RoktEvent {
5+
/**
6+
* ShowLoadingIndicator event will be triggered before SDK calls Rokt backend
7+
*/
8+
data object ShowLoadingIndicator : RoktEvent
9+
10+
/**
11+
* HideLoadingIndicator event will be triggered when SDK obtains a success or failure from
12+
* Rokt backend
13+
*/
14+
data object HideLoadingIndicator : RoktEvent
15+
16+
/**
17+
* OfferEngagement event will be triggered if User engaged with the offer
18+
* @param placementId - identifier for the placement emitting the event
19+
*/
20+
data class OfferEngagement(val placementId: String) : RoktEvent
21+
22+
/**
23+
* PositiveEngagement event will be triggered if User positively engaged with the offer
24+
* @param placementId - identifier for the placement emitting the event
25+
*/
26+
data class PositiveEngagement(val placementId: String) : RoktEvent
27+
28+
/**
29+
* FirstPositiveEngagement event will be triggered when the user positively engaged with the offer first time
30+
* @param placementId - identifier for the placement emitting the event
31+
*/
32+
data class FirstPositiveEngagement(val placementId: String) : RoktEvent
33+
34+
/**
35+
* PlacementInteractive event will be triggered when placement has been rendered and is interactable
36+
* @param placementId - identifier for the placement emitting the event
37+
*/
38+
data class PlacementInteractive(val placementId: String) : RoktEvent
39+
40+
/**
41+
* PlacementReady event will be triggered when placement is ready to display but has not rendered content yet
42+
* @param placementId - identifier for the placement emitting the event
43+
*/
44+
data class PlacementReady(val placementId: String) : RoktEvent
45+
46+
/**
47+
* PlacementClosed event will be triggered when placement closes by user
48+
* @param placementId - identifier for the placement emitting the event
49+
*/
50+
data class PlacementClosed(val placementId: String) : RoktEvent
51+
52+
/**
53+
* PlacementCompleted event will be triggered when the offer progression moves to the end and no more
54+
* offer to display
55+
* @param placementId - identifier for the placement emitting the event
56+
*/
57+
data class PlacementCompleted(val placementId: String) : RoktEvent
58+
59+
/**
60+
* PlacementFailure event will be triggered when placement could not be displayed due to some failure
61+
* @param placementId - optional identifier for the placement emitting the event
62+
*/
63+
data class PlacementFailure(val placementId: String? = null) : RoktEvent
64+
65+
/**
66+
* InitComplete event will be triggered when SDK has finished initialization
67+
* @param success - true if init was successful
68+
*/
69+
data class InitComplete(val success: Boolean) : RoktEvent
70+
71+
/**
72+
* OpenUrl event will be triggered when user clicks on a link and the link target is set to Passthrough
73+
* @param placementId - identifier for the placement emitting the event
74+
* @param url - url to open
75+
*/
76+
data class OpenUrl(val placementId: String, val url: String) : RoktEvent
77+
78+
/**
79+
* CartItemInstantPurchase event will be triggered when the catalog item purchase is initiated
80+
* by the user
81+
* @property placementId The layout identifier.
82+
* @property cartItemId The cart item identifier.
83+
* @property catalogItemId The catalog item identifier.
84+
* @property currency The currency used for the purchase.
85+
* @property description The description of the cart item.
86+
* @property linkedProductId The linked product identifier.
87+
* @property totalPrice The total price of the cart item.
88+
* @property quantity The quantity of the cart item.
89+
* @property unitPrice The unit price of the cart item.
90+
*/
91+
data class CartItemInstantPurchase(
92+
val placementId: String,
93+
val cartItemId: String,
94+
val catalogItemId: String,
95+
val currency: String,
96+
val description: String,
97+
val linkedProductId: String,
98+
val totalPrice: Double,
99+
val quantity: Int,
100+
val unitPrice: Double
101+
) : RoktEvent
102+
}

android-core/src/test/kotlin/com/mparticle/RoktTest.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import com.mparticle.internal.ConfigManager
77
import com.mparticle.internal.KitManager
88
import com.mparticle.rokt.RoktConfig
99
import com.mparticle.rokt.RoktEmbeddedView
10+
import kotlinx.coroutines.flow.Flow
11+
import kotlinx.coroutines.flow.flowOf
12+
import kotlinx.coroutines.flow.toList
13+
import kotlinx.coroutines.test.runTest
1014
import org.junit.Before
1115
import org.junit.Test
1216
import org.junit.runner.RunWith
@@ -19,6 +23,8 @@ import org.mockito.MockitoAnnotations
1923
import org.powermock.core.classloader.annotations.PrepareForTest
2024
import org.powermock.modules.junit4.PowerMockRunner
2125
import java.lang.ref.WeakReference
26+
import kotlin.test.assertEquals
27+
import kotlin.test.assertTrue
2228

2329
@RunWith(PowerMockRunner::class)
2430
@PrepareForTest(Looper::class, SystemClock::class)
@@ -133,4 +139,33 @@ class RoktTest {
133139

134140
verify(kitManager, never()).purchaseFinalized("132", "1111", true)
135141
}
142+
143+
@Test
144+
fun testEvents_whenEnabled_delegatesToKitManager() {
145+
`when`(configManager.isEnabled).thenReturn(true)
146+
147+
val testIdentifier = "test-identifier"
148+
val expectedFlow: Flow<RoktEvent> = flowOf()
149+
`when`(kitManager.events(testIdentifier)).thenReturn(expectedFlow)
150+
151+
val result = rokt.events(testIdentifier)
152+
153+
verify(kitManager).events(testIdentifier)
154+
assertEquals(expectedFlow, result)
155+
}
156+
157+
@Test
158+
fun testEvents_whenDisabled_returnsEmptyFlow() {
159+
`when`(configManager.isEnabled).thenReturn(false)
160+
161+
val testIdentifier = "test-identifier"
162+
163+
val result = rokt.events(testIdentifier)
164+
165+
verify(kitManager, never()).events(any())
166+
runTest {
167+
val elements = result.toList()
168+
assertTrue(elements.isEmpty())
169+
}
170+
}
136171
}

0 commit comments

Comments
 (0)