diff --git a/datapipelines/api/datapipelines.api b/datapipelines/api/datapipelines.api index 6f725ed55..e3c73db21 100644 --- a/datapipelines/api/datapipelines.api +++ b/datapipelines/api/datapipelines.api @@ -1,6 +1,6 @@ public final class io/customer/datapipelines/config/DataPipelinesModuleConfig : io/customer/sdk/core/module/CustomerIOModuleConfig { - public fun (Ljava/lang/String;Lio/customer/sdk/data/model/Region;Ljava/lang/String;Ljava/lang/String;IILjava/util/List;ZZZZLjava/lang/String;)V - public synthetic fun (Ljava/lang/String;Lio/customer/sdk/data/model/Region;Ljava/lang/String;Ljava/lang/String;IILjava/util/List;ZZZZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lio/customer/sdk/data/model/Region;Ljava/lang/String;Ljava/lang/String;IILjava/util/List;ZZZZLjava/lang/String;Lio/customer/datapipelines/config/ScreenView;)V + public synthetic fun (Ljava/lang/String;Lio/customer/sdk/data/model/Region;Ljava/lang/String;Ljava/lang/String;IILjava/util/List;ZZZZLjava/lang/String;Lio/customer/datapipelines/config/ScreenView;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getApiHost ()Ljava/lang/String; public final fun getAutoAddCustomerIODestination ()Z public final fun getAutoTrackActivityScreens ()Z @@ -11,9 +11,30 @@ public final class io/customer/datapipelines/config/DataPipelinesModuleConfig : public final fun getFlushInterval ()I public final fun getFlushPolicies ()Ljava/util/List; public final fun getMigrationSiteId ()Ljava/lang/String; + public final fun getScreenViewUse ()Lio/customer/datapipelines/config/ScreenView; public final fun getTrackApplicationLifecycleEvents ()Z } +public abstract class io/customer/datapipelines/config/ScreenView { + public static final field Companion Lio/customer/datapipelines/config/ScreenView$Companion; + public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getName ()Ljava/lang/String; +} + +public final class io/customer/datapipelines/config/ScreenView$All : io/customer/datapipelines/config/ScreenView { + public static final field INSTANCE Lio/customer/datapipelines/config/ScreenView$All; +} + +public final class io/customer/datapipelines/config/ScreenView$Companion { + public final fun getScreenView (Ljava/lang/String;)Lio/customer/datapipelines/config/ScreenView; + public final fun getScreenView (Ljava/lang/String;Lio/customer/datapipelines/config/ScreenView;)Lio/customer/datapipelines/config/ScreenView; + public static synthetic fun getScreenView$default (Lio/customer/datapipelines/config/ScreenView$Companion;Ljava/lang/String;Lio/customer/datapipelines/config/ScreenView;ILjava/lang/Object;)Lio/customer/datapipelines/config/ScreenView; +} + +public final class io/customer/datapipelines/config/ScreenView$InApp : io/customer/datapipelines/config/ScreenView { + public static final field INSTANCE Lio/customer/datapipelines/config/ScreenView$InApp; +} + public final class io/customer/datapipelines/extensions/JsonExtensionsKt { public static final fun toJsonArray (Lorg/json/JSONArray;)Lkotlinx/serialization/json/JsonArray; public static final fun toJsonObject (Lorg/json/JSONObject;)Lkotlinx/serialization/json/JsonObject; @@ -183,6 +204,7 @@ public final class io/customer/sdk/CustomerIOBuilder { public final fun logLevel (Lio/customer/sdk/core/util/CioLogLevel;)Lio/customer/sdk/CustomerIOBuilder; public final fun migrationSiteId (Ljava/lang/String;)Lio/customer/sdk/CustomerIOBuilder; public final fun region (Lio/customer/sdk/data/model/Region;)Lio/customer/sdk/CustomerIOBuilder; + public final fun screenViewUse (Lio/customer/datapipelines/config/ScreenView;)Lio/customer/sdk/CustomerIOBuilder; public final fun trackApplicationLifecycleEvents (Z)Lio/customer/sdk/CustomerIOBuilder; } diff --git a/datapipelines/src/main/kotlin/io/customer/datapipelines/config/DataPipelinesModuleConfig.kt b/datapipelines/src/main/kotlin/io/customer/datapipelines/config/DataPipelinesModuleConfig.kt index f9656626b..b9d8f229c 100644 --- a/datapipelines/src/main/kotlin/io/customer/datapipelines/config/DataPipelinesModuleConfig.kt +++ b/datapipelines/src/main/kotlin/io/customer/datapipelines/config/DataPipelinesModuleConfig.kt @@ -27,7 +27,9 @@ class DataPipelinesModuleConfig( // Track screen views for Activities val autoTrackActivityScreens: Boolean, // Configuration options required for migration from earlier versions - val migrationSiteId: String? = null + val migrationSiteId: String? = null, + // Determines how SDK should handle screen view events + val screenViewUse: ScreenView ) : CustomerIOModuleConfig { val apiHost: String = apiHostOverride ?: region.apiHost() val cdnHost: String = cdnHostOverride ?: region.cdnHost() diff --git a/datapipelines/src/main/kotlin/io/customer/datapipelines/config/ScreenView.kt b/datapipelines/src/main/kotlin/io/customer/datapipelines/config/ScreenView.kt new file mode 100644 index 000000000..60bc4cb03 --- /dev/null +++ b/datapipelines/src/main/kotlin/io/customer/datapipelines/config/ScreenView.kt @@ -0,0 +1,38 @@ +package io.customer.datapipelines.config + +/** + * Enum class to define how CustomerIO SDK should handle screen view events. + */ +sealed class ScreenView(val name: String) { + /** + * Screen view events are sent to destinations for analytics purposes. + * They are also used to display in-app messages based on page rules. + */ + object All : ScreenView(name = "all") + + /** + * Screen view events are kept on device only. They are used to display in-app messages based on + * page rules. Events are not sent to our back end servers. + */ + + object InApp : ScreenView(name = "inapp") + + companion object { + /** + * Returns the [ScreenView] enum constant for the given name. + * Returns fallback if the specified enum type has no constant with the given name. + * Defaults to [All]. + */ + @JvmOverloads + fun getScreenView(screenView: String?, fallback: ScreenView = All): ScreenView { + if (screenView.isNullOrBlank()) { + return fallback + } + + return listOf( + All, + InApp + ).find { value -> value.name.equals(screenView, ignoreCase = true) } ?: fallback + } + } +} diff --git a/datapipelines/src/main/kotlin/io/customer/datapipelines/plugins/ScreenFilterPlugin.kt b/datapipelines/src/main/kotlin/io/customer/datapipelines/plugins/ScreenFilterPlugin.kt new file mode 100644 index 000000000..23712830c --- /dev/null +++ b/datapipelines/src/main/kotlin/io/customer/datapipelines/plugins/ScreenFilterPlugin.kt @@ -0,0 +1,27 @@ +package io.customer.datapipelines.plugins + +import com.segment.analytics.kotlin.core.Analytics +import com.segment.analytics.kotlin.core.BaseEvent +import com.segment.analytics.kotlin.core.ScreenEvent +import com.segment.analytics.kotlin.core.platform.EventPlugin +import com.segment.analytics.kotlin.core.platform.Plugin +import io.customer.datapipelines.config.ScreenView + +/** + * Plugin to filter screen events based on the configuration provided by customer app. + * This plugin is used to filter out screen events that should not be processed further. + */ +internal class ScreenFilterPlugin(private val screenViewUse: ScreenView) : EventPlugin { + override lateinit var analytics: Analytics + override val type: Plugin.Type = Plugin.Type.Enrichment + + override fun screen(payload: ScreenEvent): BaseEvent? { + // Filter out screen events based on the configuration provided by customer app + // Using when expression so it enforce right check for all possible values of ScreenView in future + return when (screenViewUse) { + ScreenView.All -> payload + // Do not send screen events to server if ScreenView is not Analytics + ScreenView.InApp -> null + } + } +} diff --git a/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIO.kt b/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIO.kt index 44f0e2b08..b891ca240 100644 --- a/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIO.kt +++ b/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIO.kt @@ -21,6 +21,7 @@ import io.customer.datapipelines.plugins.AutomaticActivityScreenTrackingPlugin import io.customer.datapipelines.plugins.ContextPlugin import io.customer.datapipelines.plugins.CustomerIODestination import io.customer.datapipelines.plugins.DataPipelinePublishedEvents +import io.customer.datapipelines.plugins.ScreenFilterPlugin import io.customer.datapipelines.util.EventNames import io.customer.sdk.communication.Event import io.customer.sdk.communication.subscribe @@ -121,6 +122,9 @@ class CustomerIO private constructor( // Add plugin to publish events to EventBus for other modules to consume analytics.add(DataPipelinePublishedEvents()) + // Add plugin to filter events based on SDK configuration + analytics.add(ScreenFilterPlugin(moduleConfig.screenViewUse)) + // subscribe to journey events emitted from push/in-app module to send them via data pipelines subscribeToJourneyEvents() // if profile is already identified, republish identifier for late-added modules. diff --git a/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIOBuilder.kt b/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIOBuilder.kt index e8a3ee86e..256b04a84 100644 --- a/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIOBuilder.kt +++ b/datapipelines/src/main/kotlin/io/customer/sdk/CustomerIOBuilder.kt @@ -3,6 +3,7 @@ package io.customer.sdk import android.app.Application import com.segment.analytics.kotlin.core.platform.policies.FlushPolicy import io.customer.datapipelines.config.DataPipelinesModuleConfig +import io.customer.datapipelines.config.ScreenView import io.customer.sdk.core.di.SDKComponent import io.customer.sdk.core.di.setupAndroidComponent import io.customer.sdk.core.module.CustomerIOModule @@ -69,6 +70,9 @@ class CustomerIOBuilder( // Configuration options required for migration from earlier versions private var migrationSiteId: String? = null + // Determines how SDK should handle screen view events + private var screenViewUse: ScreenView = ScreenView.All + /** * Specifies the log level for the SDK. * Default value is [CioLogLevel.ERROR]. @@ -167,6 +171,16 @@ class CustomerIOBuilder( return this } + /** + * Set the screen view configuration for the SDK. + * + * @see ScreenView for more details. + */ + fun screenViewUse(screenView: ScreenView): CustomerIOBuilder { + this.screenViewUse = screenView + return this + } + fun addCustomerIOModule(module: CustomerIOModule): CustomerIOBuilder { registeredModules.add(module) return this @@ -191,7 +205,8 @@ class CustomerIOBuilder( trackApplicationLifecycleEvents = trackApplicationLifecycleEvents, autoTrackDeviceAttributes = autoTrackDeviceAttributes, autoTrackActivityScreens = autoTrackActivityScreens, - migrationSiteId = migrationSiteId + migrationSiteId = migrationSiteId, + screenViewUse = screenViewUse ) // Initialize CustomerIO instance before initializing the modules diff --git a/datapipelines/src/test/java/io/customer/datapipelines/config/ScreenViewTest.kt b/datapipelines/src/test/java/io/customer/datapipelines/config/ScreenViewTest.kt new file mode 100644 index 000000000..be0face32 --- /dev/null +++ b/datapipelines/src/test/java/io/customer/datapipelines/config/ScreenViewTest.kt @@ -0,0 +1,46 @@ +package io.customer.datapipelines.config + +import io.customer.commontest.core.JUnit5Test +import org.amshove.kluent.shouldBeEqualTo +import org.junit.jupiter.api.Test + +class ScreenViewTest : JUnit5Test() { + @Test + fun getScreenView_givenNamesWithMatchingCase_expectCorrectScreenView() { + val screenViewAnalytics = ScreenView.getScreenView("All") + val screenViewInApp = ScreenView.getScreenView("InApp") + + screenViewAnalytics shouldBeEqualTo ScreenView.All + screenViewInApp shouldBeEqualTo ScreenView.InApp + } + + @Test + fun getScreenView_givenNamesWithDifferentCase_expectCorrectScreenView() { + val screenViewAnalytics = ScreenView.getScreenView("all") + val screenViewInApp = ScreenView.getScreenView("inapp") + + screenViewAnalytics shouldBeEqualTo ScreenView.All + screenViewInApp shouldBeEqualTo ScreenView.InApp + } + + @Test + fun getScreenView_givenInvalidValue_expectFallbackScreenView() { + val parsedValue = ScreenView.getScreenView("none") + + parsedValue shouldBeEqualTo ScreenView.All + } + + @Test + fun getScreenView_givenEmptyValue_expectFallbackScreenView() { + val parsedValue = ScreenView.getScreenView(screenView = "", fallback = ScreenView.InApp) + + parsedValue shouldBeEqualTo ScreenView.InApp + } + + @Test + fun getScreenView_givenNull_expectFallbackScreenView() { + val parsedValue = ScreenView.getScreenView(null) + + parsedValue shouldBeEqualTo ScreenView.All + } +} diff --git a/datapipelines/src/test/java/io/customer/datapipelines/plugins/ScreenFilterPluginTest.kt b/datapipelines/src/test/java/io/customer/datapipelines/plugins/ScreenFilterPluginTest.kt new file mode 100644 index 000000000..b89c85a50 --- /dev/null +++ b/datapipelines/src/test/java/io/customer/datapipelines/plugins/ScreenFilterPluginTest.kt @@ -0,0 +1,72 @@ +package io.customer.datapipelines.plugins + +import io.customer.commontest.config.TestConfig +import io.customer.commontest.extensions.random +import io.customer.datapipelines.config.ScreenView +import io.customer.datapipelines.testutils.core.DataPipelinesTestConfig +import io.customer.datapipelines.testutils.core.JUnitTest +import io.customer.datapipelines.testutils.core.testConfiguration +import io.customer.datapipelines.testutils.extensions.shouldMatchTo +import io.customer.datapipelines.testutils.utils.OutputReaderPlugin +import io.customer.datapipelines.testutils.utils.screenEvents +import io.customer.sdk.data.model.CustomAttributes +import org.amshove.kluent.shouldBeEmpty +import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldHaveSingleItem +import org.junit.jupiter.api.Test + +class ScreenFilterPluginTest : JUnitTest() { + private lateinit var outputReaderPlugin: OutputReaderPlugin + + override fun setup(testConfig: TestConfig) { + // Keep setup empty to avoid calling super.setup() as it will initialize the SDK + // and we want to test the SDK with different configurations in each test + } + + private fun setupWithConfig(screenViewUse: ScreenView, testConfig: DataPipelinesTestConfig = testConfiguration {}) { + super.setup( + testConfiguration { + analytics { add(ScreenFilterPlugin(screenViewUse = screenViewUse)) } + } + testConfig + ) + + outputReaderPlugin = OutputReaderPlugin() + analytics.add(outputReaderPlugin) + } + + @Test + fun process_givenScreenViewUseAnalytics_expectScreenEventWithoutPropertiesProcessed() { + setupWithConfig(screenViewUse = ScreenView.All) + + val givenScreenTitle = String.random + sdkInstance.screen(givenScreenTitle) + + val result = outputReaderPlugin.screenEvents.shouldHaveSingleItem() + result.name shouldBeEqualTo givenScreenTitle + result.properties.shouldBeEmpty() + } + + @Test + fun process_givenScreenViewUseAnalytics_expectScreenEventWithPropertiesProcessed() { + setupWithConfig(screenViewUse = ScreenView.All) + + val givenScreenTitle = String.random + val givenProperties: CustomAttributes = mapOf("source" to "push", "discount" to 10) + sdkInstance.screen(givenScreenTitle, givenProperties) + + val screenEvent = outputReaderPlugin.screenEvents.shouldHaveSingleItem() + screenEvent.name shouldBeEqualTo givenScreenTitle + screenEvent.properties shouldMatchTo givenProperties + } + + @Test + fun process_givenScreenViewUseInApp_expectAllScreenEventsIgnored() { + setupWithConfig(screenViewUse = ScreenView.InApp) + + for (i in 1..5) { + sdkInstance.screen(String.random) + } + + outputReaderPlugin.allEvents.shouldBeEmpty() + } +} diff --git a/datapipelines/src/test/java/io/customer/datapipelines/sdk/CustomerIOBuilderTest.kt b/datapipelines/src/test/java/io/customer/datapipelines/sdk/CustomerIOBuilderTest.kt index eb2424160..53bb62ed9 100644 --- a/datapipelines/src/test/java/io/customer/datapipelines/sdk/CustomerIOBuilderTest.kt +++ b/datapipelines/src/test/java/io/customer/datapipelines/sdk/CustomerIOBuilderTest.kt @@ -5,9 +5,11 @@ import io.customer.commontest.extensions.assertCalledNever import io.customer.commontest.extensions.assertCalledOnce import io.customer.commontest.extensions.random import io.customer.commontest.module.CustomerIOGenericModule +import io.customer.datapipelines.config.ScreenView import io.customer.datapipelines.plugins.AutomaticActivityScreenTrackingPlugin import io.customer.datapipelines.plugins.CustomerIODestination import io.customer.datapipelines.plugins.DataPipelinePublishedEvents +import io.customer.datapipelines.plugins.ScreenFilterPlugin import io.customer.sdk.CustomerIO import io.customer.sdk.CustomerIOBuilder import io.customer.sdk.core.di.SDKComponent @@ -105,6 +107,7 @@ class CustomerIOBuilderTest : RobolectricTest() { dataPipelinesModuleConfig.apiHost shouldBe "cdp.customer.io/v1" dataPipelinesModuleConfig.cdnHost shouldBe "cdp.customer.io/v1" dataPipelinesModuleConfig.autoAddCustomerIODestination shouldBe true + dataPipelinesModuleConfig.screenViewUse shouldBe ScreenView.All } @Test @@ -112,6 +115,7 @@ class CustomerIOBuilderTest : RobolectricTest() { val givenCdpApiKey = String.random val givenMigrationSiteId = String.random val givenRegion = Region.EU + val givenScreenViewUse = ScreenView.InApp createCustomerIOBuilder(givenCdpApiKey) .logLevel(CioLogLevel.DEBUG) @@ -123,6 +127,7 @@ class CustomerIOBuilderTest : RobolectricTest() { .flushAt(100) .flushInterval(2) .flushPolicies(emptyList()) + .screenViewUse(givenScreenViewUse) .build() // verify the customerIOBuilder config with DataPipelinesModuleConfig @@ -137,6 +142,7 @@ class CustomerIOBuilderTest : RobolectricTest() { dataPipelinesModuleConfig.flushInterval shouldBe 2 dataPipelinesModuleConfig.apiHost shouldBe "cdp-eu.customer.io/v1" dataPipelinesModuleConfig.cdnHost shouldBe "cdp-eu.customer.io/v1" + dataPipelinesModuleConfig.screenViewUse shouldBe givenScreenViewUse // verify the shared logger has updated log level SDKComponent.logger.logLevel shouldBe CioLogLevel.DEBUG @@ -165,6 +171,13 @@ class CustomerIOBuilderTest : RobolectricTest() { CustomerIO.instance().analytics.find(AutomaticActivityScreenTrackingPlugin::class) shouldBe null } + @Test + fun build_givenModuleInitialized_expectScreenFilterPluginPluginAdded() { + createCustomerIOBuilder().build() + + CustomerIO.instance().analytics.find(ScreenFilterPlugin::class) shouldNotBe null + } + @Test fun build_givenHostConfiguration_expectCorrectHostDataPipelinesModuleConfig() { val givenRegion = Region.EU diff --git a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/data/model/CustomerIOSDKConfig.java b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/data/model/CustomerIOSDKConfig.java index f53da4f00..3b3636758 100644 --- a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/data/model/CustomerIOSDKConfig.java +++ b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/data/model/CustomerIOSDKConfig.java @@ -11,6 +11,7 @@ import io.customer.android.sample.java_layout.BuildConfig; import io.customer.android.sample.java_layout.support.Optional; import io.customer.android.sample.java_layout.utils.StringUtils; +import io.customer.datapipelines.config.ScreenView; import io.customer.datapipelines.extensions.RegionExtKt; import io.customer.sdk.core.util.CioLogLevel; import io.customer.sdk.data.model.Region; @@ -28,6 +29,7 @@ private static class Keys { static final String TRACK_DEVICE_ATTRIBUTES = "cio_sdk_track_device_attributes"; static final String LOG_LEVEL = "cio_sdk_log_level"; static final String REGION = "cio_sdk_region"; + static final String SCREEN_VIEW_USE = "cio_sdk_screen_view_use"; static final String TRACK_APPLICATION_LIFECYCLE = "cio_sdk_track_application_lifecycle"; static final String TEST_MODE_ENABLED = "cio_sdk_test_mode"; static final String IN_APP_MESSAGING_ENABLED = "cio_sdk_in_app_messaging_enabled"; @@ -42,6 +44,7 @@ public static CustomerIOSDKConfig getDefaultConfigurations() { true, CioLogLevel.DEBUG, Region.US.INSTANCE, + ScreenView.All.INSTANCE, true, false, true); @@ -62,6 +65,7 @@ public static Optional fromMap(@NonNull Map boolean deviceAttributesTrackingEnabled = StringUtils.parseBoolean(bundle.get(Keys.TRACK_DEVICE_ATTRIBUTES), defaultConfig.deviceAttributesTrackingEnabled); CioLogLevel logLevel = CioLogLevel.Companion.getLogLevel(bundle.get(Keys.LOG_LEVEL), CioLogLevel.DEBUG); Region region = Region.Companion.getRegion(bundle.get(Keys.REGION), Region.US.INSTANCE); + ScreenView screenViewUse = ScreenView.Companion.getScreenView(bundle.get(Keys.SCREEN_VIEW_USE)); boolean applicationLifecycleTrackingEnabled = StringUtils.parseBoolean(bundle.get(Keys.TRACK_APPLICATION_LIFECYCLE), defaultConfig.applicationLifecycleTrackingEnabled); boolean testModeEnabled = StringUtils.parseBoolean(bundle.get(Keys.TEST_MODE_ENABLED), defaultConfig.testModeEnabled); boolean inAppMessagingEnabled = StringUtils.parseBoolean(bundle.get(Keys.IN_APP_MESSAGING_ENABLED), defaultConfig.inAppMessagingEnabled); @@ -74,6 +78,7 @@ public static Optional fromMap(@NonNull Map deviceAttributesTrackingEnabled, logLevel, region, + screenViewUse, applicationLifecycleTrackingEnabled, testModeEnabled, inAppMessagingEnabled); @@ -91,6 +96,7 @@ public static Map toMap(@NonNull CustomerIOSDKConfig config) { bundle.put(Keys.TRACK_DEVICE_ATTRIBUTES, StringUtils.fromBoolean(config.deviceAttributesTrackingEnabled)); bundle.put(Keys.LOG_LEVEL, config.logLevel.name()); bundle.put(Keys.REGION, config.getRegion().getCode()); + bundle.put(Keys.SCREEN_VIEW_USE, config.getScreenViewUse().getName()); bundle.put(Keys.TRACK_APPLICATION_LIFECYCLE, StringUtils.fromBoolean(config.applicationLifecycleTrackingEnabled)); bundle.put(Keys.TEST_MODE_ENABLED, StringUtils.fromBoolean(config.testModeEnabled)); bundle.put(Keys.IN_APP_MESSAGING_ENABLED, StringUtils.fromBoolean(config.inAppMessagingEnabled)); @@ -111,6 +117,7 @@ public static Map toMap(@NonNull CustomerIOSDKConfig config) { private final CioLogLevel logLevel; @NonNull private final Region region; + private final ScreenView screenViewUse; private final boolean applicationLifecycleTrackingEnabled; private final boolean testModeEnabled; private final boolean inAppMessagingEnabled; @@ -123,6 +130,7 @@ public CustomerIOSDKConfig(@NonNull String cdpApiKey, boolean deviceAttributesTrackingEnabled, @NonNull CioLogLevel logLevel, @NonNull Region region, + @NonNull ScreenView screenViewUse, boolean applicationLifecycleTrackingEnabled, boolean testModeEnabled, boolean inAppMessagingEnabled) { @@ -134,6 +142,7 @@ public CustomerIOSDKConfig(@NonNull String cdpApiKey, this.deviceAttributesTrackingEnabled = deviceAttributesTrackingEnabled; this.logLevel = logLevel; this.region = region; + this.screenViewUse = screenViewUse; this.applicationLifecycleTrackingEnabled = applicationLifecycleTrackingEnabled; this.testModeEnabled = testModeEnabled; this.inAppMessagingEnabled = inAppMessagingEnabled; @@ -188,4 +197,9 @@ public boolean isApplicationLifecycleTrackingEnabled() { public Region getRegion() { return region; } + + @NonNull + public ScreenView getScreenViewUse() { + return screenViewUse; + } } diff --git a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/sdk/CustomerIORepository.java b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/sdk/CustomerIORepository.java index 05aa8a9be..47d41e7e9 100644 --- a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/sdk/CustomerIORepository.java +++ b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/sdk/CustomerIORepository.java @@ -77,6 +77,7 @@ private void configureSdk(CustomerIOBuilder builder, final CustomerIOSDKConfig s builder.trackApplicationLifecycleEvents(sdkConfig.isApplicationLifecycleTrackingEnabled()); builder.region(sdkConfig.getRegion()); builder.logLevel(sdkConfig.getLogLevel()); + builder.screenViewUse(sdkConfig.getScreenViewUse()); } public void identify(@NonNull String email, @NonNull Map attributes) { diff --git a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/InternalSettingsActivity.java b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/InternalSettingsActivity.java index f53260ff4..7cd5c5195 100644 --- a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/InternalSettingsActivity.java +++ b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/InternalSettingsActivity.java @@ -137,6 +137,7 @@ private static CustomerIOSDKConfig createNewSettings(CustomerIOSDKConfig current currentSettings.isDeviceAttributesTrackingEnabled(), currentSettings.getLogLevel(), currentSettings.getRegion(), + currentSettings.getScreenViewUse(), currentSettings.isApplicationLifecycleTrackingEnabled(), currentSettings.isTestModeEnabled(), currentSettings.isInAppMessagingEnabled() diff --git a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/SettingsActivity.java b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/SettingsActivity.java index aa237c585..d0dd8a015 100644 --- a/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/SettingsActivity.java +++ b/samples/java_layout/src/main/java/io/customer/android/sample/java_layout/ui/settings/SettingsActivity.java @@ -17,6 +17,7 @@ import io.customer.android.sample.java_layout.ui.dashboard.DashboardActivity; import io.customer.android.sample.java_layout.utils.OSUtils; import io.customer.android.sample.java_layout.utils.ViewUtils; +import io.customer.datapipelines.config.ScreenView; import io.customer.sdk.core.util.CioLogLevel; import io.customer.sdk.data.model.Region; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; @@ -53,6 +54,7 @@ protected void onDestroy() { @Override protected void setupContent() { + prepareViews(); prepareViewsForAutomatedTests(); setupViews(); setupObservers(); @@ -84,6 +86,11 @@ private void parseLinkParams() { isLinkParamsPopulated = true; } + private void prepareViews() { + binding.settingsScreenViewUseAllButton.setText(ScreenView.All.INSTANCE.getName()); + binding.settingsScreenViewUseInAppButton.setText(ScreenView.InApp.INSTANCE.getName()); + } + private void prepareViewsForAutomatedTests() { ViewUtils.prepareForAutomatedTests(binding.topAppBar); ViewUtils.prepareForAutomatedTests(binding.settingsCdpApiKeyLabel, R.string.acd_cdp_api_key_input); @@ -128,6 +135,7 @@ private void updateIOWithConfig(@NonNull CustomerIOSDKConfig config) { binding.settingsTrackDeviceAttrsValuesGroup.check(getCheckedAutoTrackDeviceAttributesButtonId(config.isDeviceAttributesTrackingEnabled())); binding.settingsTrackScreenViewsValuesGroup.check(getCheckedTrackScreenViewsButtonId(config.isScreenTrackingEnabled())); binding.settingsTrackAppLifecycleValuesGroup.check(getCheckedTrackAppLifecycleButtonId(config.isApplicationLifecycleTrackingEnabled())); + binding.screenViewUseSettingsValuesGroup.check(getCheckedScreenViewUseButtonId(config.getScreenViewUse())); binding.settingsLogLevelValuesGroup.check(getCheckedLogLevelButtonId(config.getLogLevel())); binding.settingsTestModeValuesGroup.check(getCheckedTestModeButtonId(config.isTestModeEnabled())); binding.settingsInAppMessagingValuesGroup.check(getCheckedInAppMessagingButtonId(config.isInAppMessagingEnabled())); @@ -173,6 +181,7 @@ private CustomerIOSDKConfig createNewSettings(String cdpApiKey, String siteId, C boolean featInAppMessagingEnabled = binding.settingsInAppMessagingValuesGroup.getCheckedButtonId() == R.id.settings_in_app_messaging_yes_button; CioLogLevel logLevel = getSelectedLogLevel(); Region region = getSelectedRegion(); + ScreenView screenViewUse = getSelectedScreenViewUse(); return new CustomerIOSDKConfig(cdpApiKey, siteId, @@ -182,6 +191,7 @@ private CustomerIOSDKConfig createNewSettings(String cdpApiKey, String siteId, C featTrackDeviceAttributes, logLevel, region, + screenViewUse, featTrackApplicationLifecycle, featTestModeEnabled, featInAppMessagingEnabled); @@ -213,6 +223,18 @@ private Region getSelectedRegion() { throw new IllegalStateException(); } + + @NonNull + private ScreenView getSelectedScreenViewUse() { + int checkedButton = binding.screenViewUseSettingsValuesGroup.getCheckedButtonId(); + if (checkedButton == R.id.settings_screen_view_use_all_button) { + return ScreenView.All.INSTANCE; + } else if (checkedButton == R.id.settings_screen_view_use_in_app_button) { + return ScreenView.InApp.INSTANCE; + } + throw new IllegalStateException(); + } + private int getCheckedInAppMessagingButtonId(boolean enabled) { return enabled ? R.id.settings_in_app_messaging_yes_button : R.id.settings_in_app_messaging_no_button; } @@ -256,6 +278,13 @@ private int getCheckedRegionButtonId(@NonNull Region region) { : R.id.settings_region_eu_button; } + private int getCheckedScreenViewUseButtonId(@NonNull ScreenView screenViewUse) { + if (screenViewUse instanceof ScreenView.InApp) { + return R.id.settings_screen_view_use_in_app_button; + } + return R.id.settings_screen_view_use_all_button; + } + private boolean updateErrorState(TextInputLayout textInputLayout, boolean isErrorEnabled, @StringRes int errorResId) { diff --git a/samples/java_layout/src/main/res/layout/activity_settings.xml b/samples/java_layout/src/main/res/layout/activity_settings.xml index f448e50da..a69a66691 100644 --- a/samples/java_layout/src/main/res/layout/activity_settings.xml +++ b/samples/java_layout/src/main/res/layout/activity_settings.xml @@ -234,6 +234,47 @@ android:text="@string/settings_no" /> + + + + +