Skip to content

Commit 71cd132

Browse files
feat: Add support for the fontFilePathMap (#589)
1 parent 2487f70 commit 71cd132

7 files changed

Lines changed: 241 additions & 13 deletions

File tree

android-core/proguard.pro

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -206,23 +206,13 @@
206206
-keep class com.mparticle.rokt.CacheConfig { *; }
207207
-keep class com.mparticle.rokt.RoktEmbeddedView { *; }
208208
-keep class com.mparticle.rokt.RoktLayoutDimensionCallBack { *; }
209-
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-
}
209+
-keep class com.mparticle.rokt.RoktOptions { *; }
217210

218211
# Preserve all method signatures in the Rokt class to prevent overload resolution issues
219212
-keepclassmembers class com.mparticle.Rokt {
220-
*;
213+
public void selectPlacements(...);
214+
public void purchaseFinalized(...);
221215
}
222-
-keepclassmembers class com.mparticle.KitIntegration$RoktListener* {
223-
*;
224-
}
225-
226216
-keep public class com.mparticle.audience.* {
227217
*;
228218
}

android-core/src/main/java/com/mparticle/MParticleOptions.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.mparticle.internal.SideloadedKit;
1616
import com.mparticle.networking.NetworkOptions;
1717
import com.mparticle.networking.NetworkOptionsManager;
18+
import com.mparticle.rokt.RoktOptions;
1819

1920
import org.json.JSONException;
2021
import org.json.JSONObject;
@@ -51,6 +52,7 @@ public class MParticleOptions {
5152
private NetworkOptions mNetworkOptions;
5253
private String mDataplanId;
5354
private Integer mDataplanVersion;
55+
private RoktOptions mRoktOptions;
5456
private MParticle.OperatingSystem mOperatingSystem = MParticle.OperatingSystem.ANDROID;
5557
private DataplanOptions mDataplanOptions;
5658
private Map<Class, List<Configuration>> mConfigurations = new HashMap();
@@ -143,6 +145,7 @@ public MParticleOptions(@NonNull Builder builder) {
143145
this.mOperatingSystem = builder.operatingSystem;
144146
}
145147
this.mNetworkOptions = NetworkOptionsManager.validateAndResolve(builder.networkOptions);
148+
this.mRoktOptions = builder.roktOptions;
146149
this.mDataplanId = builder.dataplanId;
147150
this.mDataplanVersion = builder.dataplanVersion;
148151
this.mDataplanOptions = builder.dataplanOptions;
@@ -335,6 +338,11 @@ public NetworkOptions getNetworkOptions() {
335338
return mNetworkOptions;
336339
}
337340

341+
@NonNull
342+
public RoktOptions getRoktOptions() {
343+
return mRoktOptions;
344+
}
345+
338346
@Nullable
339347
public String getDataplanId() {
340348
return mDataplanId;
@@ -409,6 +417,7 @@ public static class Builder {
409417
private Integer dataplanVersion;
410418
private MParticle.OperatingSystem operatingSystem;
411419
private DataplanOptions dataplanOptions;
420+
private RoktOptions roktOptions;
412421
private Map<Class, List<Configuration>> configurations = new HashMap();
413422
private boolean isAppDebuggable;
414423
private List<SideloadedKit> sideloadedKits = new ArrayList<>();
@@ -751,6 +760,12 @@ public Builder dataplanOptions(DataplanOptions dataplanOptions) {
751760
return this;
752761
}
753762

763+
@NonNull
764+
public Builder roktOptions(@NonNull RoktOptions roktOptions) {
765+
this.roktOptions = roktOptions;
766+
return this;
767+
}
768+
754769
/**
755770
* Register a {@link com.mparticle.Configuration}n. Various implementations of Configuration can modify the behavior of
756771
* the SDK at runtime.

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.mparticle.internal.listeners.InternalListenerManager;
2929
import com.mparticle.rokt.RoktConfig;
3030
import com.mparticle.rokt.RoktEmbeddedView;
31+
import com.mparticle.rokt.RoktOptions;
3132

3233
import org.json.JSONArray;
3334

@@ -514,8 +515,17 @@ public void updateDataplan(@Nullable MParticleOptions.DataplanOptions dataplanOp
514515
}
515516
}
516517

518+
@Override
517519
@NonNull
520+
public RoktOptions getRoktOptions() {
521+
if (mKitManager != null) {
522+
return mKitManager.getRoktOptions();
523+
}
524+
return mOptions != null ? mOptions.getRoktOptions() : new RoktOptions();
525+
}
526+
518527
@Override
528+
@NonNull
519529
public Map<Integer, KitStatus> getKitStatus() {
520530
if (mKitManager != null) {
521531
return mKitManager.getKitStatus();

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.mparticle.identity.MParticleUser;
2525
import com.mparticle.rokt.RoktConfig;
2626
import com.mparticle.rokt.RoktEmbeddedView;
27+
import com.mparticle.rokt.RoktOptions;
2728

2829
import org.json.JSONArray;
2930

@@ -90,6 +91,9 @@ public interface KitManager {
9091

9192
void updateDataplan(@NonNull MParticleOptions.DataplanOptions dataplanOptions);
9293

94+
@NonNull
95+
RoktOptions getRoktOptions();
96+
9397
@NonNull
9498
Map<Integer, KitStatus> getKitStatus();
9599

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.mparticle.rokt
2+
3+
class RoktOptions @JvmOverloads constructor(
4+
fontFilePathMap: Map<String, String> = emptyMap(),
5+
fontPostScriptNames: Set<String> = emptySet()
6+
) {
7+
val fontFilePathMap: Map<String, String> = fontFilePathMap.toMap()
8+
val fontPostScriptNames: Set<String> = fontPostScriptNames.toSet()
9+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
package com.mparticle.rokt
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Assert.assertFalse
5+
import org.junit.Assert.assertNotEquals
6+
import org.junit.Assert.assertNull
7+
import org.junit.Assert.assertTrue
8+
import org.junit.Test
9+
10+
class RoktOptionsTest {
11+
12+
@Test
13+
fun testDefaultConstructor_shouldCreateEmptyOptions() {
14+
val roktOptions = RoktOptions()
15+
16+
assertTrue("fontFilePathMap should be empty", roktOptions.fontFilePathMap.isEmpty())
17+
assertTrue("fontPostScriptNames should be empty", roktOptions.fontPostScriptNames.isEmpty())
18+
}
19+
20+
@Test
21+
fun testConstructorWithFontFilePathMap_shouldSetCorrectValues() {
22+
val fontMap = mapOf(
23+
"font1" to "/path/to/font1.ttf",
24+
"font2" to "/path/to/font2.otf"
25+
)
26+
27+
val roktOptions = RoktOptions(fontFilePathMap = fontMap)
28+
29+
assertEquals("fontFilePathMap should match", fontMap, roktOptions.fontFilePathMap)
30+
assertTrue("fontPostScriptNames should be empty", roktOptions.fontPostScriptNames.isEmpty())
31+
assertEquals("Should have 2 font files", 2, roktOptions.fontFilePathMap.size)
32+
assertEquals("Should contain font1 path", "/path/to/font1.ttf", roktOptions.fontFilePathMap["font1"])
33+
assertEquals("Should contain font2 path", "/path/to/font2.otf", roktOptions.fontFilePathMap["font2"])
34+
}
35+
36+
@Test
37+
fun testConstructorWithFontPostScriptNames_shouldSetCorrectValues() {
38+
val fontNames = setOf(
39+
"Arial-Bold",
40+
"Helvetica-Light",
41+
"CustomFont-Regular"
42+
)
43+
44+
val roktOptions = RoktOptions(fontPostScriptNames = fontNames)
45+
46+
assertTrue("fontFilePathMap should be empty", roktOptions.fontFilePathMap.isEmpty())
47+
assertEquals("fontPostScriptNames should match", fontNames, roktOptions.fontPostScriptNames)
48+
assertEquals("Should have 3 font names", 3, roktOptions.fontPostScriptNames.size)
49+
assertTrue("Should contain Arial-Bold", roktOptions.fontPostScriptNames.contains("Arial-Bold"))
50+
assertTrue("Should contain Helvetica-Light", roktOptions.fontPostScriptNames.contains("Helvetica-Light"))
51+
assertTrue("Should contain CustomFont-Regular", roktOptions.fontPostScriptNames.contains("CustomFont-Regular"))
52+
}
53+
54+
@Test
55+
fun testConstructorWithBothParameters_shouldSetBothValues() {
56+
val fontMap = mapOf("font1" to "/path/to/font1.ttf")
57+
val fontNames = setOf("Arial-Bold")
58+
59+
val roktOptions = RoktOptions(
60+
fontFilePathMap = fontMap,
61+
fontPostScriptNames = fontNames
62+
)
63+
64+
assertEquals("fontFilePathMap should match", fontMap, roktOptions.fontFilePathMap)
65+
assertEquals("fontPostScriptNames should match", fontNames, roktOptions.fontPostScriptNames)
66+
assertEquals("Should have 1 font file", 1, roktOptions.fontFilePathMap.size)
67+
assertEquals("Should have 1 font name", 1, roktOptions.fontPostScriptNames.size)
68+
}
69+
70+
@Test
71+
fun testConstructorWithEmptyCollections_shouldCreateEmptyOptions() {
72+
val roktOptions = RoktOptions(
73+
fontFilePathMap = emptyMap(),
74+
fontPostScriptNames = emptySet()
75+
)
76+
77+
assertTrue("fontFilePathMap should be empty", roktOptions.fontFilePathMap.isEmpty())
78+
assertTrue("fontPostScriptNames should be empty", roktOptions.fontPostScriptNames.isEmpty())
79+
}
80+
81+
@Test
82+
fun testFontFilePathMapImmutability_shouldNotAllowModification() {
83+
val mutableMap = mutableMapOf("font1" to "/path/to/font1.ttf")
84+
val roktOptions = RoktOptions(fontFilePathMap = mutableMap)
85+
86+
// Modify the original map
87+
mutableMap["font2"] = "/path/to/font2.ttf"
88+
89+
// The RoktOptions should not be affected if the implementation is correct
90+
assertEquals("RoktOptions should have 1 font file", 1, roktOptions.fontFilePathMap.size)
91+
assertFalse("RoktOptions should not contain font2", roktOptions.fontFilePathMap.containsKey("font2"))
92+
}
93+
94+
@Test
95+
fun testFontPostScriptNamesImmutability_shouldNotAllowModification() {
96+
val mutableSet = mutableSetOf("Arial-Bold")
97+
val roktOptions = RoktOptions(fontPostScriptNames = mutableSet)
98+
99+
// Modify the original set
100+
mutableSet.add("Helvetica-Light")
101+
102+
// The RoktOptions should not be affected if the implementation is correct
103+
assertEquals("RoktOptions should have 1 font name", 1, roktOptions.fontPostScriptNames.size)
104+
assertFalse("RoktOptions should not contain Helvetica-Light", roktOptions.fontPostScriptNames.contains("Helvetica-Light"))
105+
}
106+
107+
@Test
108+
fun testMultipleInstances_shouldBeIndependent() {
109+
val fontMap1 = mapOf("font1" to "/path1")
110+
val fontMap2 = mapOf("font2" to "/path2")
111+
112+
val roktOptions1 = RoktOptions(fontFilePathMap = fontMap1)
113+
val roktOptions2 = RoktOptions(fontFilePathMap = fontMap2)
114+
115+
assertNotEquals("Instances should be different", roktOptions1.fontFilePathMap, roktOptions2.fontFilePathMap)
116+
assertEquals("First instance should have font1", "/path1", roktOptions1.fontFilePathMap["font1"])
117+
assertEquals("Second instance should have font2", "/path2", roktOptions2.fontFilePathMap["font2"])
118+
assertNull("First instance should not have font2", roktOptions1.fontFilePathMap["font2"])
119+
assertNull("Second instance should not have font1", roktOptions2.fontFilePathMap["font1"])
120+
}
121+
122+
@Test
123+
fun testLargeCollections_shouldHandleCorrectly() {
124+
val largeFontMap = (1..100).associate { "font$it" to "/path/to/font$it.ttf" }
125+
val largeFontNames = (1..100).map { "Font-$it" }.toSet()
126+
127+
val roktOptions = RoktOptions(
128+
fontFilePathMap = largeFontMap,
129+
fontPostScriptNames = largeFontNames
130+
)
131+
132+
assertEquals("Should have 100 font files", 100, roktOptions.fontFilePathMap.size)
133+
assertEquals("Should have 100 font names", 100, roktOptions.fontPostScriptNames.size)
134+
assertEquals("Should contain first font file", "/path/to/font1.ttf", roktOptions.fontFilePathMap["font1"])
135+
assertEquals("Should contain last font file", "/path/to/font100.ttf", roktOptions.fontFilePathMap["font100"])
136+
assertTrue("Should contain first font name", roktOptions.fontPostScriptNames.contains("Font-1"))
137+
assertTrue("Should contain last font name", roktOptions.fontPostScriptNames.contains("Font-100"))
138+
}
139+
140+
@Test
141+
fun testEquality_sameParameters_shouldBeEqual() {
142+
val fontMap = mapOf("font1" to "/path1")
143+
val fontNames = setOf("Arial-Bold")
144+
145+
val roktOptions1 = RoktOptions(fontFilePathMap = fontMap, fontPostScriptNames = fontNames)
146+
val roktOptions2 = RoktOptions(fontFilePathMap = fontMap, fontPostScriptNames = fontNames)
147+
148+
// Note: Kotlin data classes would provide equals() automatically, but since RoktOptions
149+
// is not a data class, we test the property values individually
150+
assertEquals("fontFilePathMap should be equal", roktOptions1.fontFilePathMap, roktOptions2.fontFilePathMap)
151+
assertEquals("fontPostScriptNames should be equal", roktOptions1.fontPostScriptNames, roktOptions2.fontPostScriptNames)
152+
}
153+
154+
@Test
155+
fun testSpecialCharactersInPaths_shouldHandleCorrectly() {
156+
val fontMap = mapOf(
157+
"font with spaces" to "/path with spaces/font file.ttf",
158+
"font-with-dashes" to "/path-with-dashes/font-file.ttf",
159+
"font_with_underscores" to "/path_with_underscores/font_file.ttf",
160+
"fontWithUnicode" to "/path/with/unicode/字体.ttf"
161+
)
162+
163+
val roktOptions = RoktOptions(fontFilePathMap = fontMap)
164+
165+
assertEquals("Should handle spaces", "/path with spaces/font file.ttf", roktOptions.fontFilePathMap["font with spaces"])
166+
assertEquals("Should handle dashes", "/path-with-dashes/font-file.ttf", roktOptions.fontFilePathMap["font-with-dashes"])
167+
assertEquals("Should handle underscores", "/path_with_underscores/font_file.ttf", roktOptions.fontFilePathMap["font_with_underscores"])
168+
assertEquals("Should handle unicode", "/path/with/unicode/字体.ttf", roktOptions.fontFilePathMap["fontWithUnicode"])
169+
}
170+
171+
@Test
172+
fun testSpecialCharactersInFontNames_shouldHandleCorrectly() {
173+
val fontNames = setOf(
174+
"Arial-Bold",
175+
"Helvetica_Light",
176+
"Font With Spaces",
177+
"Font.With.Dots",
178+
"字体名称" // Unicode font name
179+
)
180+
181+
val roktOptions = RoktOptions(fontPostScriptNames = fontNames)
182+
183+
assertTrue("Should contain Arial-Bold", roktOptions.fontPostScriptNames.contains("Arial-Bold"))
184+
assertTrue("Should contain Helvetica_Light", roktOptions.fontPostScriptNames.contains("Helvetica_Light"))
185+
assertTrue("Should contain Font With Spaces", roktOptions.fontPostScriptNames.contains("Font With Spaces"))
186+
assertTrue("Should contain Font.With.Dots", roktOptions.fontPostScriptNames.contains("Font.With.Dots"))
187+
assertTrue("Should contain unicode font name", roktOptions.fontPostScriptNames.contains("字体名称"))
188+
}
189+
}

android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.mparticle.kits.mappings.CustomMapping;
5151
import com.mparticle.rokt.RoktConfig;
5252
import com.mparticle.rokt.RoktEmbeddedView;
53+
import com.mparticle.rokt.RoktOptions;
5354

5455
import org.json.JSONArray;
5556
import org.json.JSONException;
@@ -86,6 +87,7 @@ public class KitManagerImpl implements KitManager, AttributionListener, UserAttr
8687
KitIntegrationFactory mKitIntegrationFactory;
8788
private DataplanFilter mDataplanFilter = DataplanFilterImpl.EMPTY;
8889
private KitOptions mKitOptions;
90+
private RoktOptions mRoktOptions;
8991
private volatile List<KitConfiguration> kitConfigurations = new ArrayList<>();
9092

9193
private static final String RESERVED_KEY_LTV = "$Amount";
@@ -104,6 +106,9 @@ public KitManagerImpl(Context context, ReportingManager reportingManager, CoreCa
104106
mReportingManager = reportingManager;
105107
mCoreCallbacks = coreCallbacks;
106108
mKitIntegrationFactory = new KitIntegrationFactory(options);
109+
if (options != null) {
110+
mRoktOptions = options.getRoktOptions();
111+
}
107112
MParticle instance = MParticle.getInstance();
108113
if (instance != null) {
109114
instance.Identity().addIdentityStateListener(this);
@@ -204,6 +209,12 @@ public void updateDataplan(@Nullable MParticleOptions.DataplanOptions dataplanOp
204209
}
205210
}
206211

212+
@Override
213+
@NonNull
214+
public RoktOptions getRoktOptions() {
215+
return mRoktOptions != null ? mRoktOptions : new RoktOptions();
216+
}
217+
207218
/**
208219
* Update the current list of active kits based on server (or cached) configuration.
209220
* <p>

0 commit comments

Comments
 (0)