Custom Storage
By default, Android SDK uses an internal SharedPreferences-based storage implementation.
If your app requires encrypted storage, DataStore, or another persistence layer, pass a custom DetourStorage via DetourConfig.storage.
Storage interface
interface DetourStorage {
suspend fun getItem(key: String): String?
suspend fun setItem(key: String, value: String)
suspend fun removeItem(key: String) { }
}
What SDK persists
SDK stores internal keys for:
- first-launch detection (
Detour_firstEntranceFlag) - analytics device identifier (
Detour_deviceId)
Custom storage should preserve values across app restarts to keep deferred-flow and analytics behavior consistent.
Example: EncryptedSharedPreferences
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.swmansion.detour.storage.DetourStorage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class EncryptedStorageProvider(context: Context) : DetourStorage {
private val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
private val prefs = EncryptedSharedPreferences.create(
context,
"DetourSecureStorage",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
override suspend fun getItem(key: String): String? = withContext(Dispatchers.IO) {
prefs.getString(key, null)
}
override suspend fun setItem(key: String, value: String) = withContext(Dispatchers.IO) {
prefs.edit().putString(key, value).apply()
}
}
val config = DetourConfig(
apiKey = BuildConfig.DETOUR_API_KEY,
appId = BuildConfig.DETOUR_APP_ID,
storage = EncryptedStorageProvider(this)
)