On this page
Modern Android devices use file-based encryption: data at rest is encrypted, and apps' private directories are protected by the sandbox. So why encrypt again? Because device encryption protects a powered-off, locked device, not your app's data from backups, debugging tools on compromised devices, or another layer of defence your compliance team requires.
What to encrypt at the app level
| Data | Encrypt? | Notes |
|---|---|---|
| Auth tokens, session secrets | Yes | See Secure Token Storage |
| Health, financial, identity documents | Yes | Often required by policy or regulation |
| Private user content (journals, private notes) | Often | Consider user expectations |
| Cached public content, preferences like theme | No | Encryption adds cost without benefit |
About EncryptedSharedPreferences and EncryptedFile
Jetpack Security (androidx.security:security-crypto), which provided EncryptedSharedPreferences and EncryptedFile, has been deprecated. Existing apps keep working, but new code should use alternatives such as Tink directly (which security-crypto used internally), together with DataStore or files. Plan a migration that reads old values once and re-writes them with the new mechanism.
Encrypting files with Tink
object EncryptedFiles {
private fun streamingAead(context: Context): StreamingAead {
StreamingAeadConfig.register()
return AndroidKeysetManager.Builder()
.withSharedPref(context, "file_keyset", "file_keyset_prefs")
.withKeyTemplate(KeyTemplates.get("AES256_GCM_HKDF_4KB"))
.withMasterKeyUri("android-keystore://file_master_key")
.build()
.keysetHandle
.getPrimitive(RegistryConfiguration.get(), StreamingAead::class.java)
}
fun write(context: Context, file: File, bytes: ByteArray) {
val aad = file.name.toByteArray() // bind ciphertext to the file name
FileOutputStream(file).use { out ->
streamingAead(context).newEncryptingStream(out, aad).use { it.write(bytes) }
}
}
fun read(context: Context, file: File): ByteArray {
val aad = file.name.toByteArray()
return FileInputStream(file).use { input ->
streamingAead(context).newDecryptingStream(input, aad).use { it.readBytes() }
}
}
}In production, create the primitive once and reuse it. For small values, use Tink's Aead with a DataStore serializer, as shown in Secure Token Storage.
Encrypting a Room database
Room doesn't encrypt by itself. A common approach is SQLCipher, which plugs into Room through an openHelperFactory. Protect the database passphrase by generating random bytes and storing them encrypted with a Keystore-backed key:
val passphrase: ByteArray = DbKeyProvider.getOrCreate(context) // random 32 bytes, stored Tink/Keystore-encrypted
val factory = SupportOpenHelperFactory(passphrase) // from the SQLCipher Android library
val db = Room.databaseBuilder(context, AppDatabase::class.java, "secure.db")
.openHelperFactory(factory)
.build()Check the SQLCipher library's current artifact and class names, and measure the performance impact on your queries.
Practices
- Use authenticated encryption (AES-GCM / AEAD), never ECB or unauthenticated modes.
- Never hard-code keys, and never derive keys from constants in the APK.
- Exclude encrypted data and keysets from backups, since Keystore keys don't restore.
- Handle key loss: treat undecryptable data as missing, and re-sync or sign out.
- Encrypt only what needs it, because encryption costs CPU and complexity.
Examples
Health diary
Room with SQLCipher, biometric lock on open, and no cloud backup of the database.
Document wallet
PDFs encrypted with Tink streaming AEAD, plus FLAG_SECURE on the viewer.
Banking session
Tokens via Tink AEAD in DataStore, cleared on logout.
Frequently asked questions
Is device encryption enough?
For low-sensitivity data, usually yes. For secrets and regulated data, app-level encryption adds protection for backups and some compromised-device scenarios.
Does encryption slow my app?
Some, especially for large files or databases. Measure, and encrypt selectively.
Can I use the deprecated library a bit longer?
Existing code continues to function, but it won't get updates. Plan migration rather than adding new usage.
Conclusion
Encrypt sensitive data at the app level with Keystore-protected keys: Tink AEAD for small values, streaming AEAD for files, and SQLCipher for databases. Migrate off the deprecated EncryptedSharedPreferences, exclude secrets from backup, and handle key loss gracefully.
Next step: limit what you collect in the first place with Android Permissions and Privacy Best Practices.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Security is easiest to get right when it is part of how you build from the first screen. Strengthen the Android fundamentals that secure, privacy-respecting apps are built on.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.