Skip to content

Commit 80de8ea

Browse files
author
markvdouw
authored
feat: sideloading kits (#401)
* feat: sideloading kits (#378) * Adding local kit as a wrapper for config and kit integration. Creating empty config based on a random unused Int generated by the factory. Adding kit merging and initializing. * Changes on tests for compatibility * Changes due to comments Adding unit test to check getting config from KitIntegration wrapper set in MParticleOptions, KitManagerFactory creating instances, applying config, etc. * Redoing sideloaded kits * Changes into dependencies * Combining sideloaded kits into prefs for merge. * Adding capabilities for integration and merging sideloaded kits with remote config. * Fixing unit tests * # Conflicts: # android-core/src/main/java/com/mparticle/internal/ConfigManager.java * ktlintFormat * Test fixes * Fixing incorrect HTML tag * Changes due to comments * Change due to comments * Modification of long proguard * ktlintFormat * Changes due to team discussion. Using kit instance and combine it with created instances. Support for multiple instances. Adding condition to filter sideloaded kits with id < 1000000 * Implementing default functions from KitIntegration * Test fix --------- Signed-off-by: markvdouw <[email protected]>
1 parent 2281194 commit 80de8ea

28 files changed

+897
-177
lines changed

android-core/proguard.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@
123123
-keep class com.mparticle.consent.CCPAConsent$Builder {*;}
124124

125125

126+
-keep class com.mparticle.internal.SideloadedKit { *; }
127+
126128
-keep class com.mparticle.internal.KitManager { *; }
127129
-keep class com.mparticle.internal.KitManager$* { *; }
128130
-keep class com.mparticle.internal.CoreCallbacks { *; }

android-core/src/androidTest/kotlin/com.mparticle/internal/ConfigMigrationTest.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package com.mparticle.internal
33
import com.mparticle.MParticle
44
import com.mparticle.MParticleOptions
55
import com.mparticle.testutils.BaseCleanInstallEachTest
6+
import org.json.JSONArray
67
import org.json.JSONObject
78
import org.junit.Test
89
import kotlin.test.assertEquals
910
import kotlin.test.assertNull
11+
import kotlin.test.assertTrue
1012

1113
class ConfigMigrationTest : BaseCleanInstallEachTest() {
1214
private val oldConfigSharedprefsKey = "json"
@@ -81,7 +83,7 @@ class ConfigMigrationTest : BaseCleanInstallEachTest() {
8183

8284
// make sure config is deleted
8385
MParticle.getInstance()!!.Internal().configManager.let {
84-
assertNull(it.config)
86+
assertTrue(it.config?.isEmpty()!!)
8587
assertNull(it.configTimestamp)
8688
assertNull(it.etag)
8789
assertNull(it.ifModified)
@@ -127,13 +129,12 @@ class ConfigMigrationTest : BaseCleanInstallEachTest() {
127129
}
128130

129131
private fun assertOldConfigState(config: JSONObject) {
130-
assertNull(ConfigManager.getInstance(mContext).getKitConfigPreferences().getString(ConfigManager.KIT_CONFIG_KEY, null))
131-
assertEquals(config.toString(), ConfigManager.getPreferences(mContext).getString(oldConfigSharedprefsKey, null))
132+
assertEquals(config.toString(), ConfigManager.getPreferences(mContext).getString(oldConfigSharedprefsKey, JSONArray().toString()))
132133
}
133134

134135
private fun assertNewConfigState(config: JSONObject) {
135-
val configString = ConfigManager.getPreferences(mContext).getString(ConfigManager.CONFIG_JSON, null)
136+
val configString = ConfigManager.getPreferences(mContext).getString(ConfigManager.CONFIG_JSON, JSONArray().toString())
136137
assertNull(JSONObject(configString).optJSONArray(ConfigManager.KEY_EMBEDDED_KITS))
137-
assertEquals(config.optString(ConfigManager.KEY_EMBEDDED_KITS, null), ConfigManager.getInstance(mContext).kitConfigPreferences.getString(ConfigManager.KIT_CONFIG_KEY, null))
138+
assertEquals(config.optString(ConfigManager.KEY_EMBEDDED_KITS, JSONArray().toString()), ConfigManager.getInstance(mContext).kitConfigPreferences.getString(ConfigManager.KIT_CONFIG_KEY, JSONArray().toString()))
138139
}
139140
}

android-core/src/androidTest/kotlin/com.mparticle/internal/ConfigStalenessCheckTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.junit.Test
99
import kotlin.test.assertEquals
1010
import kotlin.test.assertNotNull
1111
import kotlin.test.assertNull
12+
import kotlin.test.assertTrue
1213

1314
class ConfigStalenessCheckTest : BaseCleanInstallEachTest() {
1415
val configManager: ConfigManager
@@ -82,7 +83,7 @@ class ConfigStalenessCheckTest : BaseCleanInstallEachTest() {
8283
latch = MPLatch(1)
8384

8485
// after configMaxAge time has elapsed, config should be cleared after restart
85-
assertNull(configManager.config)
86+
assertTrue(configManager.config?.isEmpty()!!)
8687
assertNull(configManager.etag)
8788
assertNull(configManager.ifModified)
8889
assertNull(configManager.configTimestamp)
@@ -161,7 +162,7 @@ class ConfigStalenessCheckTest : BaseCleanInstallEachTest() {
161162
latch = MPLatch(1)
162163

163164
// directly after restart, config should be cleared
164-
assertNull(configManager.config)
165+
assertTrue(configManager.config?.isEmpty()!!)
165166
assertNull(configManager.etag)
166167
assertNull(configManager.ifModified)
167168
assertNull(configManager.configTimestamp)

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private MParticle(MParticleOptions options) {
147147
*/
148148
public void setUpdateInterval(int interval) {
149149
long intervalMillis = interval * 1000L;
150-
if ( (intervalMillis >= 1 && mConfigManager.getUploadInterval() != intervalMillis)) {
150+
if ((intervalMillis >= 1 && mConfigManager.getUploadInterval() != intervalMillis)) {
151151
upload();
152152
mConfigManager.setUploadInterval(interval);
153153
}
@@ -293,6 +293,7 @@ public static boolean isAndroidIdEnabled() {
293293

294294
/**
295295
* Returns the wrapper sdk version
296+
*
296297
* @return
297298
*/
298299
public WrapperSdkVersion getWrapperSdkVersion() {
@@ -302,6 +303,7 @@ public WrapperSdkVersion getWrapperSdkVersion() {
302303
/**
303304
* Set wrapper sdk, by default NONE.
304305
* This can only be set once.
306+
*
305307
* @param wrapperSdk diffent from {@link WrapperSdk.NONE}
306308
* @param version
307309
*/
@@ -1508,7 +1510,7 @@ public void onUserIdentified(MParticleUser user, MParticleUser previousUser) {
15081510
if (user != null) {
15091511
Identity().removeIdentityStateListener(this);
15101512
Logger.verbose("Sending previously deferred logPushRegistration Modify request.");
1511-
sendPushTokenModifyRequest(user, newInstanceId, oldInstanceId);
1513+
sendPushTokenModifyRequest(user, newInstanceId, oldInstanceId);
15121514
}
15131515
}
15141516
};

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
import com.mparticle.internal.Logger;
1313
import com.mparticle.internal.MPUtility;
1414
import com.mparticle.internal.PushRegistrationHelper;
15+
import com.mparticle.internal.SideloadedKit;
1516
import com.mparticle.networking.NetworkOptions;
1617
import com.mparticle.networking.NetworkOptionsManager;
1718

18-
import org.jetbrains.annotations.NotNull;
1919
import org.json.JSONException;
2020
import org.json.JSONObject;
2121

@@ -54,6 +54,7 @@ public class MParticleOptions {
5454
private MParticle.OperatingSystem mOperatingSystem = MParticle.OperatingSystem.ANDROID;
5555
private DataplanOptions mDataplanOptions;
5656
private Map<Class, List<Configuration>> mConfigurations = new HashMap();
57+
private List<SideloadedKit> sideloadedKits = new ArrayList<>();
5758

5859
private MParticleOptions() {
5960
}
@@ -145,6 +146,7 @@ public MParticleOptions(@NonNull Builder builder) {
145146
this.mDataplanVersion = builder.dataplanVersion;
146147
this.mDataplanOptions = builder.dataplanOptions;
147148
this.mConfigurations = builder.configurations;
149+
this.sideloadedKits = builder.sideloadedKits;
148150
}
149151

150152
/**
@@ -179,6 +181,16 @@ public MParticle.Environment getEnvironment() {
179181
return mEnvironment;
180182
}
181183

184+
/**
185+
* Get list of sideloadedKits kits
186+
*
187+
* @return
188+
*/
189+
@NonNull
190+
public List<SideloadedKit> getSideloadedKits() {
191+
return sideloadedKits;
192+
}
193+
182194
/**
183195
* Query the API Key.
184196
*
@@ -387,6 +399,7 @@ public static class Builder {
387399
private DataplanOptions dataplanOptions;
388400
private Map<Class, List<Configuration>> configurations = new HashMap();
389401
private boolean isAppDebuggable;
402+
private List<SideloadedKit> sideloadedKits = new ArrayList<>();
390403

391404
private Builder(Context context) {
392405
this.context = context;
@@ -421,6 +434,26 @@ public Builder installType(@NonNull MParticle.InstallType installType) {
421434
return this;
422435
}
423436

437+
/**
438+
* Add sideloaded kits
439+
*
440+
* @param kits
441+
* @return
442+
*/
443+
@NonNull
444+
public Builder sideloadedKits(@NonNull List<SideloadedKit> kits) {
445+
List<SideloadedKit> _kits = new ArrayList<>();
446+
for (SideloadedKit kit : kits) {
447+
if (kit.kitId() < 1000000) {
448+
Logger.error("Sideloaded kit " + kit.getName() + " must have a kitId greater or equal than 1000000, current one is " + kit.kitId() + " and will not be included.");
449+
} else {
450+
_kits.add(kit);
451+
}
452+
}
453+
this.sideloadedKits = _kits;
454+
return this;
455+
}
456+
424457
/**
425458
* Indicate a known {@link com.mparticle.MParticle.Environment} the Application will be running in. If this method is not used.
426459
* a default Environment of MParticle.Environment.AutoDetect will be used.

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

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public class ConfigManager {
7070
static final String DATAPLAN_BLOCK_EVENT_ATTRIBUTES = "ea";
7171
static final String DATAPLAN_BLOCK_USER_ATTRIBUTES = "ua";
7272
static final String DATAPLAN_BLOCK_USER_IDENTITIES = "id";
73-
static final String KIT_CONFIG_KEY = "kit_config";
73+
public static final String KIT_CONFIG_KEY = "kit_config";
7474
static final String MIGRATED_TO_KIT_SHARED_PREFS = "is_mig_kit_sp";
7575

7676
private static final int DEVMODE_UPLOAD_INTERVAL_MILLISECONDS = 10 * 1000;
@@ -106,6 +106,7 @@ public class ConfigManager {
106106
public static final int DEFAULT_SESSION_TIMEOUT_SECONDS = 60;
107107
public static final int DEFAULT_UPLOAD_INTERVAL = 600;
108108
private List<ConfigLoadedListener> configUpdatedListeners = new ArrayList<>();
109+
private List<SideloadedKit> sideloadedKits = new ArrayList<>();
109110

110111
private ConfigManager() {
111112
super();
@@ -129,10 +130,10 @@ public ConfigManager(Context context) {
129130
}
130131

131132
public ConfigManager(@NonNull MParticleOptions options) {
132-
this(options.getContext(), options.getEnvironment(), options.getApiKey(), options.getApiSecret(), options.getDataplanOptions(), options.getDataplanId(), options.getDataplanVersion(), options.getConfigMaxAge(), options.getConfigurationsForTarget(ConfigManager.class));
133+
this(options.getContext(), options.getEnvironment(), options.getApiKey(), options.getApiSecret(), options.getDataplanOptions(), options.getDataplanId(), options.getDataplanVersion(), options.getConfigMaxAge(), options.getConfigurationsForTarget(ConfigManager.class), options.getSideloadedKits());
133134
}
134135

135-
public ConfigManager(@NonNull Context context, @Nullable MParticle.Environment environment, @Nullable String apiKey, @Nullable String apiSecret, @Nullable MParticleOptions.DataplanOptions dataplanOptions, @Nullable String dataplanId, @Nullable Integer dataplanVersion, @Nullable Integer configMaxAge, @Nullable List<Configuration<ConfigManager>> configurations) {
136+
public ConfigManager(@NonNull Context context, @Nullable MParticle.Environment environment, @Nullable String apiKey, @Nullable String apiSecret, @Nullable MParticleOptions.DataplanOptions dataplanOptions, @Nullable String dataplanId, @Nullable Integer dataplanVersion, @Nullable Integer configMaxAge, @Nullable List<Configuration<ConfigManager>> configurations, @Nullable List<SideloadedKit> sideloadedKits) {
136137
mContext = context.getApplicationContext();
137138
sPreferences = getPreferences(mContext);
138139
if (apiKey != null || apiSecret != null) {
@@ -148,6 +149,11 @@ public ConfigManager(@NonNull Context context, @Nullable MParticle.Environment e
148149
mDataplanVersion = dataplanVersion;
149150
mDataplanId = dataplanId;
150151
mMaxConfigAge = configMaxAge;
152+
if (sideloadedKits != null) {
153+
this.sideloadedKits = sideloadedKits;
154+
} else {
155+
this.sideloadedKits = new ArrayList<>();
156+
}
151157
if (configurations != null) {
152158
for (Configuration configuration : configurations) {
153159
configuration.apply(this);
@@ -277,7 +283,7 @@ void checkConfigStaleness() {
277283

278284
@Nullable
279285
String getConfig() {
280-
return sPreferences.getString(CONFIG_JSON, null);
286+
return sPreferences.getString(CONFIG_JSON, "");
281287
}
282288

283289
void setConfigTimestamp(Long timestamp) {
@@ -321,7 +327,7 @@ void saveConfigJson(JSONObject coreConfig, JSONArray kitConfig, String etag, Str
321327
.apply();
322328
getKitConfigPreferences()
323329
.edit()
324-
.putString(KIT_CONFIG_KEY, kitConfigString)
330+
.putString(KIT_CONFIG_KEY, SideloadedKitsUtils.INSTANCE.combineConfig(kitConfig, sideloadedKits).toString())
325331
.apply();
326332
} else {
327333
Logger.debug("clearing current configurations");
@@ -346,7 +352,26 @@ public synchronized void updateConfig(JSONObject responseJSON) throws JSONExcept
346352
updateConfig(responseJSON, null, null);
347353
}
348354

349-
public synchronized void updateConfig(JSONObject responseJSON, String etag, String lastModified) throws JSONException {
355+
public synchronized void configUpToDate() throws JSONException {
356+
try {
357+
String config = getKitConfigPreferences().getString(KIT_CONFIG_KEY, "");
358+
if (!config.isEmpty()) {
359+
JSONArray kitConfig = new JSONArray(config);
360+
JSONArray combined = SideloadedKitsUtils.INSTANCE.combineConfig(kitConfig, sideloadedKits);
361+
getKitConfigPreferences()
362+
.edit()
363+
.putString(KIT_CONFIG_KEY, combined.toString())
364+
.apply();
365+
onConfigLoaded(ConfigType.KIT, kitConfig != combined);
366+
}
367+
} catch (JSONException e) {
368+
e.printStackTrace();
369+
throw new RuntimeException(e);
370+
}
371+
}
372+
373+
public synchronized void updateConfig(JSONObject responseJSON, String etag, String
374+
lastModified) throws JSONException {
350375
if (responseJSON == null) {
351376
responseJSON = new JSONObject();
352377
}
@@ -369,7 +394,8 @@ private synchronized void updateKitConfig(@Nullable JSONArray kitConfigs) {
369394
}
370395
}
371396

372-
private synchronized void updateCoreConfig(JSONObject responseJSON, boolean newConfig) throws JSONException {
397+
private synchronized void updateCoreConfig(JSONObject responseJSON, boolean newConfig) throws
398+
JSONException {
373399
SharedPreferences.Editor editor = sPreferences.edit();
374400
if (responseJSON.has(KEY_UNHANDLED_EXCEPTIONS)) {
375401
mLogUnhandledExceptions = responseJSON.getString(KEY_UNHANDLED_EXCEPTIONS);
@@ -673,7 +699,8 @@ public void setPushRegistration(PushRegistrationHelper.PushRegistration pushRegi
673699
}
674700
}
675701

676-
public void setPushRegistrationInBackground(PushRegistrationHelper.PushRegistration pushRegistration) {
702+
public void setPushRegistrationInBackground(PushRegistrationHelper.PushRegistration
703+
pushRegistration) {
677704
String oldInstanceId = getPushInstanceId();
678705
if (oldInstanceId == null) {
679706
oldInstanceId = "";

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public interface MessageKey {
221221
String LAUNCH_COUNT = "lc";
222222
String LAUNCH_COUNT_SINCE_UPGRADE = "lcu";
223223
String LAST_USE_DATE = "lud";
224+
String SIDELOADED_KITS_COUNT = "sideloaded_kits_count";
224225
// device customAttributes
225226
String BUILD_ID = "bid";
226227
String BRAND = "b";

0 commit comments

Comments
 (0)