Setting up Encrypted SharedPreferences in Android Application
When an app doesn't need biometry or complex key schema, but plaintext tokens in SharedPreferences are an obvious risk, EncryptedSharedPreferences from Jetpack Security covers 80% of use cases in half a day.
What Exactly Gets Encrypted
EncryptedSharedPreferences uses Google's Tink library with two-level encryption: keys encrypted with AES256-SIV (deterministic encryption, allows key-based search), values with AES256-GCM. Master key stored in Android Keystore. Result: preferences XML file contains unreadable blob instead of <string name="auth_token">eyJhb...</string>.
Initialization
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.setUserAuthenticationRequired(false) // true for biometry
.build()
val prefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
After this, API identical to regular SharedPreferences — putString, getString, edit().apply(). No extra code.
Important Limitations
EncryptedSharedPreferences doesn't support getAll() — method throws UnsupportedOperationException. If code anywhere iterates all keys, refactoring is needed before migration.
Preferences file can't be copied between devices — master key tied to specific device's Keystore. Important restriction to warn about when migrating from regular SharedPreferences: restore from backup (Auto Backup) won't bring encrypted data.
Jetpack Security version 1.1.0-alpha (and above) stabilized API after long alpha. Use no lower than 1.1.0-alpha06 — earlier versions have known bug with file corruption under certain write conditions.
When EncryptedSharedPreferences Insufficient
If data needed in background worker without user on screen, and device could be rebooted, you need explicit control over access schemes, that is, direct Keystore work with proper setUserAuthenticationRequired(false). EncryptedSharedPreferences uses BIOMETRIC_STRONG or DEVICE_CREDENTIAL if biometry enabled, which can block background access.
For large data (files, databases), use EncryptedFile from same Jetpack Security, not SharedPreferences.
Timeline
Simple SharedPreferences to EncryptedSharedPreferences swap: 4–8 hours including testing on several API levels. If Auto Backup present and need to properly configure backup_rules.xml to exclude encrypted file from backup — add several more hours.







