Skip to content
Dashboard

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.

interface DetourStorage {
suspend fun getItem(key: String): String?
suspend fun setItem(key: String, value: String)
suspend fun removeItem(key: String) { }
}

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.

The adapter below wraps EncryptedSharedPreferences. Any class that implements DetourStorage works, so use it as a starting point for DataStore or another persistence layer.

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)
)