diff --git a/buildSrc/src/main/kotlin/io.customer/android/Dependencies.kt b/buildSrc/src/main/kotlin/io.customer/android/Dependencies.kt
index 44d58abea..0c71b12c1 100644
--- a/buildSrc/src/main/kotlin/io.customer/android/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/io.customer/android/Dependencies.kt
@@ -3,6 +3,8 @@ package io.customer.android
object Dependencies {
const val androidGradlePlugin =
"com.android.tools.build:gradle:${Versions.ANDROID_GRADLE_PLUGIN}"
+ const val androidxSecurityCrypto =
+ "androidx.security:security-crypto:${Versions.ANDROIDX_SECURITY_CRYPTO}"
const val androidxTestJunit = "androidx.test.ext:junit:${Versions.ANDROIDX_TEST_JUNIT}"
const val androidxTestRunner = "androidx.test:runner:${Versions.ANDROIDX_TEST_RUNNER}"
const val androidxTestRules = "androidx.test:rules:${Versions.ANDROIDX_TEST_RULES}"
diff --git a/buildSrc/src/main/kotlin/io.customer/android/Versions.kt b/buildSrc/src/main/kotlin/io.customer/android/Versions.kt
index 26cad265f..d4ff357a7 100644
--- a/buildSrc/src/main/kotlin/io.customer/android/Versions.kt
+++ b/buildSrc/src/main/kotlin/io.customer/android/Versions.kt
@@ -2,6 +2,9 @@ package io.customer.android
object Versions {
internal const val ANDROID_GRADLE_PLUGIN = "7.2.0"
+
+ // Using alpha version as current stable version (1.0.0) has minSdkVersion 23
+ internal const val ANDROIDX_SECURITY_CRYPTO = "1.1.0-alpha06"
internal const val ANDROIDX_TEST_JUNIT = "1.1.4"
internal const val ANDROIDX_TEST_RUNNER = "1.4.0"
internal const val ANDROIDX_TEST_RULES = "1.4.0"
diff --git a/messagingpush/src/main/AndroidManifest.xml b/messagingpush/src/main/AndroidManifest.xml
index 2f4af990f..e3132f963 100644
--- a/messagingpush/src/main/AndroidManifest.xml
+++ b/messagingpush/src/main/AndroidManifest.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/messagingpush/src/main/res/xml/backup_rules.xml b/messagingpush/src/main/res/xml/backup_rules.xml
new file mode 100644
index 000000000..3a1c4ebcf
--- /dev/null
+++ b/messagingpush/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/sdk/build.gradle b/sdk/build.gradle
index f7c7fde78..22668c82f 100644
--- a/sdk/build.gradle
+++ b/sdk/build.gradle
@@ -57,6 +57,7 @@ dependencies {
implementation Dependencies.coroutinesCore
implementation Dependencies.coroutinesAndroid
+ implementation Dependencies.androidxSecurityCrypto
implementation Dependencies.retrofit
implementation Dependencies.moshi
implementation Dependencies.retrofitMoshiConverter
diff --git a/sdk/src/main/java/io/customer/sdk/repository/preference/BasePreferenceRepository.kt b/sdk/src/main/java/io/customer/sdk/repository/preference/BasePreferenceRepository.kt
index 514e37108..6961342b1 100644
--- a/sdk/src/main/java/io/customer/sdk/repository/preference/BasePreferenceRepository.kt
+++ b/sdk/src/main/java/io/customer/sdk/repository/preference/BasePreferenceRepository.kt
@@ -10,11 +10,8 @@ internal abstract class BasePreferenceRepository(val context: Context) {
abstract val prefsName: String
- internal val prefs: SharedPreferences
- get() = context.applicationContext.getSharedPreferences(
- prefsName,
- Context.MODE_PRIVATE
- )
+ // Making this abstract so base class has option to use encrypted shared prefs
+ internal abstract val prefs: SharedPreferences
// this would clear the prefs asynchronously
open fun clearAll() {
diff --git a/sdk/src/main/java/io/customer/sdk/repository/preference/SharedPreferenceRepository.kt b/sdk/src/main/java/io/customer/sdk/repository/preference/SharedPreferenceRepository.kt
index 9defef649..31ddc4a12 100644
--- a/sdk/src/main/java/io/customer/sdk/repository/preference/SharedPreferenceRepository.kt
+++ b/sdk/src/main/java/io/customer/sdk/repository/preference/SharedPreferenceRepository.kt
@@ -1,6 +1,9 @@
package io.customer.sdk.repository.preference
import android.content.Context
+import android.content.SharedPreferences
+import androidx.security.crypto.EncryptedSharedPreferences
+import androidx.security.crypto.MasterKey
import io.customer.sdk.Version
import io.customer.sdk.data.model.Region
import io.customer.sdk.data.store.Client
@@ -16,8 +19,29 @@ internal interface SharedPreferenceRepository {
internal class SharedPreferenceRepositoryImp(context: Context) : SharedPreferenceRepository,
BasePreferenceRepository(context) {
+ // The file name used for storing shared preferences.
+ // This preference file should not be included in Auto Backup.
+ // Upon restoration, the encryption key originally used may no longer be present.
+ // To prevent this, ensure the file name matches the one excluded in backup_rules.xml.
+ // Read more: https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences
override val prefsName: String by lazy {
- "io.customer.sdk.${context.packageName}.PREFERENCE_FILE_KEY"
+ "io.customer.sdk.EncryptedConfigCache"
+ }
+
+ override val prefs: SharedPreferences
+
+ init {
+ val masterKey = MasterKey.Builder(context)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build()
+
+ prefs = EncryptedSharedPreferences.create(
+ context,
+ prefsName,
+ masterKey,
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
+ )
}
override fun saveSettings(
diff --git a/sdk/src/main/java/io/customer/sdk/repository/preference/SitePreferenceRepository.kt b/sdk/src/main/java/io/customer/sdk/repository/preference/SitePreferenceRepository.kt
index 92f30c7a6..123d5fc0b 100644
--- a/sdk/src/main/java/io/customer/sdk/repository/preference/SitePreferenceRepository.kt
+++ b/sdk/src/main/java/io/customer/sdk/repository/preference/SitePreferenceRepository.kt
@@ -1,6 +1,7 @@
package io.customer.sdk.repository.preference
import android.content.Context
+import android.content.SharedPreferences
import io.customer.sdk.CustomerIOConfig
import io.customer.sdk.extensions.getDate
import io.customer.sdk.extensions.putDate
@@ -28,6 +29,12 @@ internal class SitePreferenceRepositoryImpl(
"io.customer.sdk.${context.packageName}.${config.siteId}"
}
+ override val prefs: SharedPreferences
+ get() = context.applicationContext.getSharedPreferences(
+ prefsName,
+ Context.MODE_PRIVATE
+ )
+
companion object {
private const val KEY_IDENTIFIER = "identifier"
private const val KEY_DEVICE_TOKEN = "device_token"