Answer:
My migration looks like this:
fun migrate() {
val oldPreferences = PreferenceManager.getDefaultSharedPreferences(context)
val newPreferences = EncryptedSharedPreferences.create(...)
with(newPreferences.edit()) {
oldPreferences.all.forEach { (key, value) ->
when (value) {
is Boolean -> putBoolean(key, value)
is Float -> putFloat(key, value)
is String -> putString(key, value)
is Int -> putInt(key, value)
is Long -> putLong(key, value)
is Set<*> -> putStringSet(key, value.map { it.toString() }.toSet())
else -> throw IllegalStateException("unsupported type for shared preferences migration")
}
}
apply()
}
oldPreferences.edit().clear().apply()
}
It is possible to do this without creating new shared preferences file, but why would you...
Explanation:
Any shared preferences are stored in an .xml
file. You can find the file and read it, so it's not that hard to see what is happening with it.
I've tried to use EncryptedSharedPreferences
with existing file and old values remained unencrypted. And EncryptedSharedPreferences
are not able to access old values now.
EncryptedSharedPreferences
are not encrypting the file. They encrypt keys and values separately, so your preferences.xml file might look like this:
<map>
<string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a9018b0938...</string>
<string name="AWNywuPwU...">ARu2fgn5N7wV...</string>
<string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">1288018cc6...</string>
</map>
This means you cannot run some oneliner to encrypt existing file. So I believe the only way is to make your own migration as shown in answer.
Hope it helps