package com.example.myapp.data.local
import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class SecurePreferencesManager @Inject constructor(
context: Context
) {
private val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
private val sharedPreferences: SharedPreferences =
EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
companion object {
private const val KEY_AUTH_TOKEN = "auth_token"
private const val KEY_REFRESH_TOKEN = "refresh_token"
private const val KEY_USER_ID = "user_id"
private const val KEY_IS_LOGGED_IN = "is_logged_in"
}
var authToken: String?
get() = sharedPreferences.getString(KEY_AUTH_TOKEN, null)
set(value) {
sharedPreferences.edit().putString(KEY_AUTH_TOKEN, value).apply()
}
var refreshToken: String?
get() = sharedPreferences.getString(KEY_REFRESH_TOKEN, null)
set(value) {
sharedPreferences.edit().putString(KEY_REFRESH_TOKEN, value).apply()
}
var userId: Int
get() = sharedPreferences.getInt(KEY_USER_ID, -1)
set(value) {
sharedPreferences.edit().putInt(KEY_USER_ID, value).apply()
}
var isLoggedIn: Boolean
get() = sharedPreferences.getBoolean(KEY_IS_LOGGED_IN, false)
set(value) {
sharedPreferences.edit().putBoolean(KEY_IS_LOGGED_IN, value).apply()
}
fun saveTokens(authToken: String, refreshToken: String) {
sharedPreferences.edit()
.putString(KEY_AUTH_TOKEN, authToken)
.putString(KEY_REFRESH_TOKEN, refreshToken)
.putBoolean(KEY_IS_LOGGED_IN, true)
.apply()
}
fun clearAll() {
sharedPreferences.edit().clear().apply()
}
fun logout() {
sharedPreferences.edit()
.remove(KEY_AUTH_TOKEN)
.remove(KEY_REFRESH_TOKEN)
.putBoolean(KEY_IS_LOGGED_IN, false)
.apply()
}
}
EncryptedSharedPreferences secures simple key-value data using Android Keystore. I create instances with EncryptedSharedPreferences.create() specifying encryption schemes. The master key uses MasterKeys or MasterKey.Builder for automatic key generation and storage. Data is encrypted at rest using AES256-GCM for values and AES256-SIV for keys. The API matches standard SharedPreferences—putString(), getString(), etc. Security supports API 23+. For older devices, fallback to unencrypted or custom encryption. Use for auth tokens, API keys, user preferences—not large files. EncryptedSharedPreferences handles encryption transparently, providing security without complexity.