com.launchdarkly.sdk.android.Migration Maven / Gradle / Ivy
package com.launchdarkly.sdk.android;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
class Migration {
static void migrateWhenNeeded(Application application, LDConfig config) {
SharedPreferences migrations = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "migrations", Context.MODE_PRIVATE);
if (migrations.contains("v2.7.0")) {
return;
}
if (!migrations.contains("v2.6.0")) {
try {
migrate_2_7_fresh(application, config);
} catch (Exception ex) {
LDConfig.LOG.w(ex, "Exception while performing fresh v2.7.0 store migration");
}
}
if (migrations.contains("v2.6.0") && !migrations.contains("v2.7.0")) {
try {
migrate_2_7_from_2_6(application);
} catch (Exception ex) {
LDConfig.LOG.w(ex, "Exception while performing v2.6.0 to v2.7.0 store migration");
}
}
}
private static String reconstructFlag(String key, String metadata, Object value) {
JsonObject flagJson = GsonCache.getGson().fromJson(metadata, JsonObject.class);
flagJson.addProperty("key", key);
if (value instanceof Float) {
flagJson.addProperty("value", (Float) value);
} else if (value instanceof Boolean) {
flagJson.addProperty("value", (Boolean) value);
} else if (value instanceof String) {
try {
JsonElement jsonVal = GsonCache.getGson().fromJson((String) value, JsonElement.class);
flagJson.add("value", jsonVal);
} catch (JsonSyntaxException unused) {
flagJson.addProperty("value", (String) value);
}
}
return GsonCache.getGson().toJson(flagJson);
}
private static void migrate_2_7_fresh(Application application, LDConfig config) {
LDConfig.LOG.d("Migrating to v2.7.0 shared preferences store");
ArrayList userKeys = getUserKeysPre_2_6(application, config);
SharedPreferences versionSharedPrefs = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "version", Context.MODE_PRIVATE);
Map flagData = versionSharedPrefs.getAll();
Set flagKeys = flagData.keySet();
boolean allSuccess = true;
for (Map.Entry mobileKeys : config.getMobileKeys().entrySet()) {
String mobileKey = mobileKeys.getValue();
boolean users = copySharedPreferences(application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "users", Context.MODE_PRIVATE),
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + "-users", Context.MODE_PRIVATE));
boolean stores = true;
for (String key : userKeys) {
Map flagValues = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + key, Context.MODE_PRIVATE).getAll();
String prefsKey = LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + key + "-flags";
SharedPreferences.Editor userFlagStoreEditor = application.getSharedPreferences(prefsKey, Context.MODE_PRIVATE).edit();
for (String flagKey : flagKeys) {
Object flagVersionData = flagData.get(flagKey);
if (flagVersionData instanceof String) {
String flagString = reconstructFlag(flagKey, (String) flagVersionData, flagValues.get(flagKey));
userFlagStoreEditor.putString(flagKey, flagString);
}
}
stores = stores && userFlagStoreEditor.commit();
}
allSuccess = allSuccess && users && stores;
}
if (allSuccess) {
LDConfig.LOG.d("Migration to v2.7.0 shared preferences store successful");
SharedPreferences migrations = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "migrations", Context.MODE_PRIVATE);
boolean logged = migrations.edit().putString("v2.7.0", "v2.7.0").commit();
if (logged) {
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "users", Context.MODE_PRIVATE).edit().clear().apply();
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "version", Context.MODE_PRIVATE).edit().clear().apply();
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "active", Context.MODE_PRIVATE).edit().clear().apply();
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "summaryevents", Context.MODE_PRIVATE).edit().clear().apply();
for (String key : userKeys) {
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + key, Context.MODE_PRIVATE).edit().clear().apply();
}
}
}
}
private static void migrate_2_7_from_2_6(Application application) {
LDConfig.LOG.d("Migrating to v2.7.0 shared preferences store from v2.6.0");
Map> keyUsers = getUserKeys_2_6(application);
boolean allSuccess = true;
for (String mobileKey : keyUsers.keySet()) {
SharedPreferences versionSharedPrefs = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + "-version", Context.MODE_PRIVATE);
Map flagData = versionSharedPrefs.getAll();
Set flagKeys = flagData.keySet();
for (String key : keyUsers.get(mobileKey)) {
Map flagValues = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + key + "-user", Context.MODE_PRIVATE).getAll();
SharedPreferences.Editor userFlagStoreEditor = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + key + "-flags", Context.MODE_PRIVATE).edit();
for (String flagKey : flagKeys) {
Object flagVersionData = flagData.get(flagKey);
if (flagVersionData instanceof String) {
String flagString = reconstructFlag(flagKey, (String) flagVersionData, flagValues.get(flagKey));
userFlagStoreEditor.putString(flagKey, flagString);
}
}
allSuccess = allSuccess && userFlagStoreEditor.commit();
}
}
if (allSuccess) {
LDConfig.LOG.d("Migration to v2.7.0 shared preferences store successful");
SharedPreferences migrations = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "migrations", Context.MODE_PRIVATE);
boolean logged = migrations.edit().putString("v2.7.0", "v2.7.0").commit();
if (logged) {
for (String mobileKey : keyUsers.keySet()) {
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + "-version", Context.MODE_PRIVATE).edit().clear().apply();
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + "-active", Context.MODE_PRIVATE).edit().clear().apply();
for (String key : keyUsers.get(mobileKey)) {
application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + mobileKey + key + "-user", Context.MODE_PRIVATE).edit().clear().apply();
}
}
}
}
}
static ArrayList getUserKeysPre_2_6(Application application, LDConfig config) {
File directory = new File(application.getFilesDir().getParent() + "/shared_prefs/");
File[] files = directory.listFiles();
if (files == null) {
return new ArrayList<>();
}
ArrayList filenames = new ArrayList<>();
for (File file : files) {
if (file.isFile())
filenames.add(file.getName());
}
filenames.remove(LDConfig.SHARED_PREFS_BASE_KEY + "id.xml");
filenames.remove(LDConfig.SHARED_PREFS_BASE_KEY + "users.xml");
filenames.remove(LDConfig.SHARED_PREFS_BASE_KEY + "version.xml");
filenames.remove(LDConfig.SHARED_PREFS_BASE_KEY + "active.xml");
filenames.remove(LDConfig.SHARED_PREFS_BASE_KEY + "summaryevents.xml");
filenames.remove(LDConfig.SHARED_PREFS_BASE_KEY + "migrations.xml");
Iterator nameIter = filenames.iterator();
while (nameIter.hasNext()) {
String name = nameIter.next();
if (!name.startsWith(LDConfig.SHARED_PREFS_BASE_KEY) || !name.endsWith(".xml")) {
nameIter.remove();
continue;
}
for (String mobileKey : config.getMobileKeys().values()) {
if (mobileKey != null && name.contains(mobileKey)) {
nameIter.remove();
break;
}
}
}
ArrayList userKeys = new ArrayList<>();
for (String filename : filenames) {
userKeys.add(filename.substring(LDConfig.SHARED_PREFS_BASE_KEY.length(), filename.length() - 4));
}
return userKeys;
}
static Map> getUserKeys_2_6(Application application) {
File directory = new File(application.getFilesDir().getParent() + "/shared_prefs/");
File[] files = directory.listFiles();
ArrayList filenames = new ArrayList<>();
for (File file : files) {
String name = file.getName();
if (file.isFile() && name.startsWith(LDConfig.SHARED_PREFS_BASE_KEY) && name.endsWith("-user.xml")) {
filenames.add(file.getName());
}
}
Map> keyUserMap = new HashMap<>();
for (String filename : filenames) {
String strip = filename.substring(LDConfig.SHARED_PREFS_BASE_KEY.length(), filename.length() - 9);
int splitAt = strip.length() - 44;
if (splitAt > 0) {
String mobileKey = strip.substring(0, splitAt);
String userKey = strip.substring(splitAt);
Set userKeys = keyUserMap.get(mobileKey);
if (userKeys == null) {
userKeys = new HashSet<>();
}
userKeys.add(userKey);
keyUserMap.put(mobileKey, userKeys);
}
}
return keyUserMap;
}
private static boolean copySharedPreferences(SharedPreferences oldPreferences, SharedPreferences newPreferences) {
SharedPreferences.Editor editor = newPreferences.edit();
for (Map.Entry entry : oldPreferences.getAll().entrySet()) {
Object value = entry.getValue();
String key = entry.getKey();
if (value instanceof Boolean)
editor.putBoolean(key, (Boolean) value);
else if (value instanceof Float)
editor.putFloat(key, (Float) value);
else if (value instanceof Integer)
editor.putInt(key, (Integer) value);
else if (value instanceof Long)
editor.putLong(key, (Long) value);
else if (value instanceof String)
editor.putString(key, ((String) value));
}
return editor.commit();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy