diff --git a/android/src/main/java/com/segment/analytics/kotlin/android/AndroidAnalytics.kt b/android/src/main/java/com/segment/analytics/kotlin/android/AndroidAnalytics.kt index 0daf9640..5d94fb65 100644 --- a/android/src/main/java/com/segment/analytics/kotlin/android/AndroidAnalytics.kt +++ b/android/src/main/java/com/segment/analytics/kotlin/android/AndroidAnalytics.kt @@ -3,12 +3,18 @@ package com.segment.analytics.kotlin.android import android.content.Context import android.content.Intent import android.util.Log +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ProcessLifecycleOwner import com.segment.analytics.kotlin.android.plugins.AndroidContextPlugin import com.segment.analytics.kotlin.android.plugins.AndroidLifecyclePlugin import com.segment.analytics.kotlin.android.utilities.DeepLinkUtils import com.segment.analytics.kotlin.core.Analytics import com.segment.analytics.kotlin.core.Configuration +import com.segment.analytics.kotlin.core.checkSettings import com.segment.analytics.kotlin.core.platform.plugins.logger.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch // A set of functions tailored to the Android implementation of analytics @@ -67,6 +73,25 @@ public fun Analytics( private fun Analytics.startup() { add(AndroidContextPlugin()) add(AndroidLifecyclePlugin()) + registerLifecycle() +} + +private fun Analytics.registerLifecycle() { + analyticsScope.launch(Dispatchers.Main) { + ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver { + var lastCheckSettings = java.lang.System.currentTimeMillis() + val CHECK_SETTINGS_INTERVAL = 10 * 1000L + + override fun onStart(owner: LifecycleOwner) { + analyticsScope.launch(analyticsDispatcher) { + if (java.lang.System.currentTimeMillis() - lastCheckSettings > CHECK_SETTINGS_INTERVAL) { + checkSettings() + lastCheckSettings = java.lang.System.currentTimeMillis() + } + } + } + }) + } } /** diff --git a/core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt b/core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt index 073b7cbf..62fef554 100644 --- a/core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt +++ b/core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt @@ -96,7 +96,13 @@ suspend fun Analytics.checkSettings() { settingsObj?.let { log("Dispatching update settings on ${Thread.currentThread().name}") store.dispatch(System.UpdateSettingsAction(settingsObj), System::class) - update(settingsObj) + } + + store.currentState(System::class)?.let { system -> + system.settings?.let { settings -> + log("Propagating settings on ${Thread.currentThread().name}") + update(settings) + } } // we're good to go back to a running state. diff --git a/core/src/test/kotlin/com/segment/analytics/kotlin/core/SettingsTests.kt b/core/src/test/kotlin/com/segment/analytics/kotlin/core/SettingsTests.kt index d67d6963..657daf7a 100644 --- a/core/src/test/kotlin/com/segment/analytics/kotlin/core/SettingsTests.kt +++ b/core/src/test/kotlin/com/segment/analytics/kotlin/core/SettingsTests.kt @@ -5,6 +5,7 @@ import com.segment.analytics.kotlin.core.platform.Plugin import com.segment.analytics.kotlin.core.utils.StubPlugin import com.segment.analytics.kotlin.core.utils.mockHTTPClient import com.segment.analytics.kotlin.core.utils.testAnalytics +import io.mockk.every import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.test.TestScope @@ -75,6 +76,34 @@ class SettingsTests { } @Test + fun `cached settings propagates to plugins when network error`() = runTest { + every { anyConstructed().settings("cdn-settings.segment.com/v1") } throws Exception() + val mockPlugin = spyk(StubPlugin()) + + val settings = Settings( + integrations = buildJsonObject { + put( + "cachedSettings", + buildJsonObject { + put( + "apiKey", + "1vNgUqwJeCHmqgI9S1sOm9UHCyfYqbaQ" + ) + }) + }, + plan = emptyJsonObject, + edgeFunction = emptyJsonObject, + middlewareSettings = emptyJsonObject + ) + analytics.store.dispatch(System.UpdateSettingsAction(settings), System::class) + analytics.add(mockPlugin) + verify { + mockPlugin.update(settings, Plugin.UpdateType.Initial) + } + } + + // Disabled because now we always propagate settings regardless network status + @Test @Disabled fun `plugin added before settings is available updates plugin correctly`() = runTest { // forces settings to fail mockHTTPClient("") diff --git a/gradle/codecov.gradle b/gradle/codecov.gradle index 29fc393b..f61aec21 100644 --- a/gradle/codecov.gradle +++ b/gradle/codecov.gradle @@ -29,9 +29,9 @@ task codeCoverageReport(type: JacocoReport) { executionData.setFrom(execData) reports { - xml.enabled true - xml.destination file("${buildDir}/reports/jacoco/report.xml") - html.enabled true - csv.enabled false + xml.required = true + xml.outputLocation = file("${buildDir}/reports/jacoco/report.xml") + html.required = true + csv.required = false } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 56f4c60d..85decc7f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jan 22 15:05:55 PST 2021 +#Tue Jun 24 14:05:08 CDT 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip