From 06cb6f82ef8d29ea99e5aa7a5bab5fd30a892953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 13:15:14 +0200 Subject: [PATCH 1/7] remove legacy gradle commands --- samples/metaapp/build.gradle.kts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/samples/metaapp/build.gradle.kts b/samples/metaapp/build.gradle.kts index 580345d9a..9565e82b6 100644 --- a/samples/metaapp/build.gradle.kts +++ b/samples/metaapp/build.gradle.kts @@ -72,11 +72,6 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } - tasks { - withType { - kotlinOptions.jvmTarget = "11" - } - } testOptions { // JSONObject return null during unit tests @@ -89,10 +84,6 @@ android { // https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24/44752239 abortOnError = false } - - kotlinOptions { - jvmTarget = "11" - } } sqldelight { From e19f67985884480534e97e70fad7d10175c9603b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 13:15:54 +0200 Subject: [PATCH 2/7] update kotlin to 2.1.21 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 50f518b3e..06be3f5c2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.9.25' + ext.kotlin_version = "2.1.21" repositories { google() @@ -23,7 +23,7 @@ plugins { id 'io.github.dryrum.replace-in-file' version '0.7.0' id 'io.github.dryrum.git-utils' version '0.7.0' id 'io.github.dryrum.bump-version-code' version '0.7.0' - id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.21' + id 'org.jetbrains.kotlin.plugin.serialization' version "2.1.21" } allprojects { From e29ca1537e60455070d3104ff94384bab086159e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 13:17:59 +0200 Subject: [PATCH 3/7] recovery authId from legacy state --- .../cmplibrary/legacy/TransferFromNativeSDK.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt b/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt index c661ba731..e0de73d1b 100644 --- a/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt +++ b/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt @@ -38,6 +38,7 @@ fun migrateLegacyToNewState( fun removeLegacyData(preferences: SharedPreferences) { preferences.edit().apply { + remove(LegacyState.AUTH_ID_PREFS_KEY) remove(GDPRLegacyConsent.PREFS_KEY) remove(CCPALegacyConsent.PREFS_KEY) remove(USNatLegacyConsent.PREFS_KEY) @@ -57,6 +58,7 @@ fun removeLegacyData(preferences: SharedPreferences) { @Serializable data class LegacyState( + val authId: String? = null, val gdpr: GDPRLegacyConsent? = null, val usnat: USNatLegacyConsent? = null, val ccpa: CCPALegacyConsent? = null, @@ -70,11 +72,22 @@ data class LegacyState( val localState: JsonObject? = null, val nonKeyedLocalState: JsonObject? = null ) { + companion object { + const val AUTH_ID_PREFS_KEY = "sp.gdpr.authId" + + private inline fun decodeWithLogging(jsonString: String, name: String): T? = runCatching { + json.decodeFromString(jsonString) + }.onFailure { e -> + println("Failed to decode $name: ${e.message}") + }.getOrNull() + } + constructor(sharedPrefs: SharedPreferences) : this( gdpr = sharedPrefs.getString(GDPRLegacyConsent.PREFS_KEY, null)?.let { json.decodeFromString(it) }, ccpa = sharedPrefs.getString(CCPALegacyConsent.PREFS_KEY, null)?.let { json.decodeFromString(it) }, usnat = sharedPrefs.getString(USNatLegacyConsent.PREFS_KEY, null)?.let { json.decodeFromString(it) }, metaData = sharedPrefs.getString(LegacyMetaData.PREFS_KEY, null)?.let { json.decodeFromString(it) }, + authId = sharedPrefs.getString(AUTH_ID_PREFS_KEY, null), gdprSampled = sharedPrefs.getBoolean(LegacyGDPRSampled.PREFS_KEY, false), usnatSampled = sharedPrefs.getBoolean(LegacyUSNATSampled.PREFS_KEY, false), ccpaSampled = sharedPrefs.getBoolean(LegacyCCPASampled.PREFS_KEY, false), @@ -88,6 +101,7 @@ data class LegacyState( fun toState(accountId: Int, propertyId: Int) = State( accountId = accountId, propertyId = propertyId, + authId = authId, gdpr = State.GDPRState( consents = gdpr?.toCore() ?: GDPRConsent(), childPmId = gdprChildPmId, From 245a26c658f193d77f8d5d5387b31171497036e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 13:18:33 +0200 Subject: [PATCH 4/7] log if transferring legacy state decoding fails --- .../sourcepoint/cmplibrary/SpConsentLib.kt | 1 + .../legacy/TransferFromNativeSDK.kt | 26 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/SpConsentLib.kt b/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/SpConsentLib.kt index e1291ec6b..ea9abd66a 100644 --- a/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/SpConsentLib.kt +++ b/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/SpConsentLib.kt @@ -28,6 +28,7 @@ interface SpConsentLib { */ fun loadMessage(cmpViewId: Int) + // TODO: remove authId from loadMessages and move it to SpConfig in the next major release /** * Load the First Layer Message (FLM) * @param authId is used to get an already saved consent diff --git a/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt b/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt index e0de73d1b..a6fb7dc60 100644 --- a/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt +++ b/cmplibrary/src/main/java/com/sourcepoint/cmplibrary/legacy/TransferFromNativeSDK.kt @@ -24,16 +24,12 @@ fun migrateLegacyToNewState( propertyId: Int ): State? { if (preferences.contains(LegacyLocalState.PREFS_KEY)) { - try { - val newState = LegacyState(preferences).toState(accountId, propertyId) - removeLegacyData(preferences) - return newState - } catch (_: Exception) { - return null - } - } else { - return null + val legacyState = LegacyState(preferences) + val newState = legacyState.toState(accountId, propertyId) + removeLegacyData(preferences) + return newState } + return null } fun removeLegacyData(preferences: SharedPreferences) { @@ -83,19 +79,19 @@ data class LegacyState( } constructor(sharedPrefs: SharedPreferences) : this( - gdpr = sharedPrefs.getString(GDPRLegacyConsent.PREFS_KEY, null)?.let { json.decodeFromString(it) }, - ccpa = sharedPrefs.getString(CCPALegacyConsent.PREFS_KEY, null)?.let { json.decodeFromString(it) }, - usnat = sharedPrefs.getString(USNatLegacyConsent.PREFS_KEY, null)?.let { json.decodeFromString(it) }, - metaData = sharedPrefs.getString(LegacyMetaData.PREFS_KEY, null)?.let { json.decodeFromString(it) }, authId = sharedPrefs.getString(AUTH_ID_PREFS_KEY, null), + gdpr = sharedPrefs.getString(GDPRLegacyConsent.PREFS_KEY, null)?.let { decodeWithLogging(it, "GDPRLegacyConsent") }, + ccpa = sharedPrefs.getString(CCPALegacyConsent.PREFS_KEY, null)?.let { decodeWithLogging(it, "CCPALegacyConsent") }, + usnat = sharedPrefs.getString(USNatLegacyConsent.PREFS_KEY, null)?.let { decodeWithLogging(it, "USNatLegacyConsent") }, + metaData = sharedPrefs.getString(LegacyMetaData.PREFS_KEY, null)?.let { decodeWithLogging(it, "LegacyMetaData") }, gdprSampled = sharedPrefs.getBoolean(LegacyGDPRSampled.PREFS_KEY, false), usnatSampled = sharedPrefs.getBoolean(LegacyUSNATSampled.PREFS_KEY, false), ccpaSampled = sharedPrefs.getBoolean(LegacyCCPASampled.PREFS_KEY, false), gdprChildPmId = sharedPrefs.getString(LegacyGDPRChildPmId.PREFS_KEY, null), ccpaChildPmId = sharedPrefs.getString(LegacyCCPAChildPmId.PREFS_KEY, null), usnatChildPmId = sharedPrefs.getString(LegacyUSNATChildPmId.PREFS_KEY, null), - localState = sharedPrefs.getString(LegacyLocalState.PREFS_KEY, null)?.let { json.decodeFromString(it) }, - nonKeyedLocalState = sharedPrefs.getString(LegacyNonKeyedLocalState.PREFS_KEY, null)?.let { json.decodeFromString(it) } + localState = sharedPrefs.getString(LegacyLocalState.PREFS_KEY, null)?.let { decodeWithLogging(it, "LegacyLocalState") }, + nonKeyedLocalState = sharedPrefs.getString(LegacyNonKeyedLocalState.PREFS_KEY, null)?.let { decodeWithLogging(it, "LegacyNonKeyedLocalState") } ) fun toState(accountId: Int, propertyId: Int) = State( From 832d1888129c21da60c749369bd1b9a333990860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 13:19:09 +0200 Subject: [PATCH 5/7] update core-module * kotlin version 2.1.21 * initialise authId from State if none is passed to its constructor --- cmplibrary/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmplibrary/build.gradle.kts b/cmplibrary/build.gradle.kts index 7931101ff..bbd4ce5e4 100644 --- a/cmplibrary/build.gradle.kts +++ b/cmplibrary/build.gradle.kts @@ -54,7 +54,7 @@ android { } dependencies { - implementation("com.sourcepoint:core:0.1.11") + implementation("com.sourcepoint:core:0.1.12-beta-3") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1") implementation("com.squareup.okhttp3:okhttp:4.12.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") From aec077faad5d9c54b80010ec94845e0ccfe5bf8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 14:27:09 +0200 Subject: [PATCH 6/7] fix failing test regarding legacy data transfer --- .../java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt b/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt index 5de7e4cce..8c5b1dc96 100644 --- a/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt +++ b/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt @@ -106,6 +106,8 @@ class LegacyStateTest { @Test fun testMigratingLegacyStateDoesntThrowEvenWhenInvalid() { loadLegacySharedPrefs(preferences, faultyLegacySharedPrefsXML) + migrateLegacyToNewState(preferences, accountId, propertyId).assertNotNull() + preferences.getString(LegacyLocalState.PREFS_KEY, null).assertNull() migrateLegacyToNewState(preferences, accountId, propertyId).assertNull() preferences.getString(LegacyLocalState.PREFS_KEY, null).assertNotNull() } From e5d3529e3f036fa2308693a172f157d6651f61de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 17 Sep 2025 14:27:27 +0200 Subject: [PATCH 7/7] add test for empty legacy transfer data --- .../com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt | 8 +++++++- .../sourcepoint/cmplibrary/legacy/SharedPrefsImporter.kt | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt b/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt index 8c5b1dc96..6faedf3f4 100644 --- a/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt +++ b/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/LegacyStateTest.kt @@ -108,7 +108,13 @@ class LegacyStateTest { loadLegacySharedPrefs(preferences, faultyLegacySharedPrefsXML) migrateLegacyToNewState(preferences, accountId, propertyId).assertNotNull() preferences.getString(LegacyLocalState.PREFS_KEY, null).assertNull() + } + + @Test + fun testMigratingLegacyStateReturnsNullIfLegacyStateIsNotPresent() { + loadLegacySharedPrefs(preferences, sharedPrefsWithoutLegacyState) migrateLegacyToNewState(preferences, accountId, propertyId).assertNull() - preferences.getString(LegacyLocalState.PREFS_KEY, null).assertNotNull() + preferences.getString(LegacyLocalState.PREFS_KEY, null).assertNull() + preferences.getString("foo", null).assertEquals("bar") } } diff --git a/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/SharedPrefsImporter.kt b/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/SharedPrefsImporter.kt index fbdefc58b..be238f032 100644 --- a/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/SharedPrefsImporter.kt +++ b/integration_tests/src/androidTest/java/com/sourcepoint/cmplibrary/legacy/SharedPrefsImporter.kt @@ -60,3 +60,9 @@ const val faultyLegacySharedPrefsXML = """{} """ + +const val sharedPrefsWithoutLegacyState = """ + + bar + +"""