From a47dd13a79339e16d700e535c745a7ee12d79c55 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 12 Jan 2024 15:16:39 +0400 Subject: [PATCH 1/8] Remove `READ_PHONE_STATE` and update dependencies --- CHANGELOG.md | 6 ++++ gradle.properties | 1 - gradle/libs.versions.toml | 14 ++++---- gradle/wrapper/gradle-wrapper.properties | 2 +- piano-analytics/build.gradle.kts | 5 ++- piano-analytics/gradle.properties | 2 +- .../android/analytics/DeviceInfoProvider.kt | 35 +------------------ .../io/piano/android/analytics/model/Enums.kt | 7 ---- .../InternalPropertiesEventProcessorTest.kt | 2 +- settings.gradle.kts | 2 +- 10 files changed, 22 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 051464d..24da932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Piano Analytics SDK for Android +## v3.3.6-SNAPSHOT +* Removed requirement for `READ_PHONE_STATE` permission for Android 6-9 +* Updated dependencies: + - androidx.lifecycle:lifecycle-process [2.6.2 -> 2.7.0] + https://developer.android.com/jetpack/androidx/releases/lifecycle#2.7.0 + ## v3.3.5 * Decreased default offline storage lifetime for events * Fixed bug with cyclic read/save current privacy mode after its expiration diff --git a/gradle.properties b/gradle.properties index bbc5fc2..4a6d0b6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,6 @@ android.useAndroidX=true android.enableJetifier=false android.nonTransitiveRClass=true android.nonFinalResIds=false -android.defaults.buildfeatures.buildconfig=true org.gradle.configuration-cache=true kotlin.incremental.useClasspathSnapshot=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 08b9e80..52b3180 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,17 +1,17 @@ [versions] # Plugins kotlin = "1.8.22" -android = "8.1.3" -versionUpdater = "0.49.0" -ktlint = "11.6.1" +android = "8.2.1" +versionUpdater = "0.50.0" +ktlint = "12.1.0" dokka = "1.8.20" -mavenRelease = "0.25.3" +mavenRelease = "0.27.0" moshiIR = "0.22.1" # AndroidX libraries compatLibrary = "1.6.1" -lifecycle = "2.6.2" -materialLibrary = "1.10.0" +lifecycle = "2.7.0" +materialLibrary = "1.11.0" # Third party Libraries googleAdsId = "18.0.1" @@ -26,7 +26,7 @@ viewBindingProperty = "1.5.9" junit = "4.13.2" androidxTestCore = "1.5.0" mockitoKotlin = "2.2.0" -mockitoCore = "5.7.0" +mockitoCore = "5.8.0" [plugins] android-library = { id = "com.android.library", version.ref = "android" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ed5c605..4b48f1a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip diff --git a/piano-analytics/build.gradle.kts b/piano-analytics/build.gradle.kts index 4303d46..22c4739 100644 --- a/piano-analytics/build.gradle.kts +++ b/piano-analytics/build.gradle.kts @@ -36,6 +36,9 @@ android { proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } + buildFeatures { + buildConfig = true + } namespace = "io.piano.android.analytics" } @@ -48,7 +51,7 @@ kotlin { ktlint { android = true - version = "1.0.1" + version = "1.1.1" } dependencies { diff --git a/piano-analytics/gradle.properties b/piano-analytics/gradle.properties index 769d580..8d9ecff 100644 --- a/piano-analytics/gradle.properties +++ b/piano-analytics/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=3.3.5 +VERSION_NAME=3.3.6-SNAPSHOT GROUP=io.piano.android POM_NAME=Analytics POM_ARTIFACT_ID=analytics diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/DeviceInfoProvider.kt b/piano-analytics/src/main/java/io/piano/android/analytics/DeviceInfoProvider.kt index bb50ed2..099b676 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/DeviceInfoProvider.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/DeviceInfoProvider.kt @@ -8,7 +8,6 @@ import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.net.NetworkInfo import android.os.Build -import android.telephony.TelephonyManager import android.util.DisplayMetrics import androidx.core.content.ContextCompat import io.piano.android.analytics.model.ConnectionType @@ -65,38 +64,6 @@ internal class DeviceInfoProvider( private fun NetworkInfo?.toConnectionType(): ConnectionType = when { this == null || !isConnected -> ConnectionType.OFFLINE type == ConnectivityManager.TYPE_WIFI -> ConnectionType.WIFI - else -> ContextCompat.getSystemService(context, TelephonyManager::class.java)?.run { - val type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) dataNetworkType else networkType - type.toConnectionType() - } ?: ConnectionType.UNKNOWN - } - - private fun Int.toConnectionType(): ConnectionType = when (this) { - TelephonyManager.NETWORK_TYPE_GPRS -> ConnectionType.GPRS - TelephonyManager.NETWORK_TYPE_EDGE -> ConnectionType.EDGE - - TelephonyManager.NETWORK_TYPE_CDMA, - TelephonyManager.NETWORK_TYPE_IDEN, - TelephonyManager.NETWORK_TYPE_1xRTT, - -> ConnectionType.TWOG - - TelephonyManager.NETWORK_TYPE_UMTS, - TelephonyManager.NETWORK_TYPE_EVDO_0, - TelephonyManager.NETWORK_TYPE_EVDO_A, - TelephonyManager.NETWORK_TYPE_EVDO_B, - -> ConnectionType.THREEG - - TelephonyManager.NETWORK_TYPE_HSPA, - TelephonyManager.NETWORK_TYPE_HSDPA, - TelephonyManager.NETWORK_TYPE_HSUPA, - -> ConnectionType.THREEGPLUS - - TelephonyManager.NETWORK_TYPE_HSPAP, - TelephonyManager.NETWORK_TYPE_LTE, - -> ConnectionType.FOURG - - TelephonyManager.NETWORK_TYPE_NR -> ConnectionType.FIVEG - - else -> ConnectionType.UNKNOWN + else -> ConnectionType.MOBILE } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt index 052accf..d6a7cc7 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt @@ -1,13 +1,6 @@ package io.piano.android.analytics.model internal enum class ConnectionType(val key: String) { - GPRS("GPRS"), - EDGE("EDGE"), - TWOG("2G"), - THREEG("3G"), - THREEGPLUS("3G+"), - FOURG("4G"), - FIVEG("5G"), MOBILE("MOBILE"), WIFI("WIFI"), OFFLINE("OFFLINE"), diff --git a/piano-analytics/src/test/java/io/piano/android/analytics/eventprocessors/InternalPropertiesEventProcessorTest.kt b/piano-analytics/src/test/java/io/piano/android/analytics/eventprocessors/InternalPropertiesEventProcessorTest.kt index df8071c..b946b6a 100644 --- a/piano-analytics/src/test/java/io/piano/android/analytics/eventprocessors/InternalPropertiesEventProcessorTest.kt +++ b/piano-analytics/src/test/java/io/piano/android/analytics/eventprocessors/InternalPropertiesEventProcessorTest.kt @@ -33,7 +33,7 @@ class InternalPropertiesEventProcessorTest { packageName = DUMMY versionName = DUMMY } - on { connectionType } doReturn ConnectionType.FIVEG + on { connectionType } doReturn ConnectionType.MOBILE } val processor = InternalPropertiesEventProcessor(configuration, deviceInfoProvider) val events = processor.process(listOf(event)) diff --git a/settings.gradle.kts b/settings.gradle.kts index c76183b..68ce496 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,7 +16,7 @@ dependencyResolutionManagement { } plugins { - id("com.gradle.enterprise") version "3.13.3" + id("com.gradle.enterprise") version "3.16.1" } include( ":app", From 0bd22dc00969ebc367bbd91cf73b1f71923741f3 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Tue, 9 Apr 2024 16:11:53 +0400 Subject: [PATCH 2/8] Update Gradle plugins --- .github/workflows/publish.yml | 6 ++---- gradle/libs.versions.toml | 10 ++++------ gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 19e21e3..1c96e0d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,7 +23,5 @@ jobs: run: chmod +x gradlew - name: Generate Javadoc run: ./gradlew javaDocReleaseGeneration --no-parallel - - name: Upload artifacts - run: ./gradlew publish --no-configuration-cache - - name: Close repository - run: ./gradlew closeAndReleaseRepository --no-configuration-cache + - name: Release artifacts + run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 52b3180..3f466e3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,11 +1,10 @@ [versions] # Plugins kotlin = "1.8.22" -android = "8.2.1" -versionUpdater = "0.50.0" +android = "8.3.1" +versionUpdater = "0.51.0" ktlint = "12.1.0" -dokka = "1.8.20" -mavenRelease = "0.27.0" +mavenRelease = "0.28.0" moshiIR = "0.22.1" # AndroidX libraries @@ -26,14 +25,13 @@ viewBindingProperty = "1.5.9" junit = "4.13.2" androidxTestCore = "1.5.0" mockitoKotlin = "2.2.0" -mockitoCore = "5.8.0" +mockitoCore = "5.11.0" [plugins] android-library = { id = "com.android.library", version.ref = "android" } android-app = { id = "com.android.application", version.ref = "android" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } -dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } mavenRelease = { id = "com.vanniktech.maven.publish", version.ref = "mavenRelease" } moshiIR = { id = "dev.zacsweers.moshix", version.ref = "moshiIR"} versionUpdater = { id = "com.github.ben-manes.versions", version.ref = "versionUpdater" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4b48f1a..f57a641 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip diff --git a/settings.gradle.kts b/settings.gradle.kts index 68ce496..1be30fd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,7 +16,7 @@ dependencyResolutionManagement { } plugins { - id("com.gradle.enterprise") version "3.16.1" + id("com.gradle.develocity") version "3.17" } include( ":app", From 7fd192fb1b23547fc6e583a543622d4e107ea342 Mon Sep 17 00:00:00 2001 From: DeKaN Date: Thu, 11 Apr 2024 16:06:13 +0400 Subject: [PATCH 3/8] Migrate to Kotlin 1.9 --- build.gradle.kts | 1 + gradle/libs.versions.toml | 11 +- piano-analytics/build.gradle.kts | 3 +- .../piano/android/analytics/Configuration.kt | 116 ++++----- .../analytics/ContextPropertiesStorage.kt | 8 +- .../io/piano/android/analytics/DataEncoder.kt | 6 +- .../io/piano/android/analytics/MediaHelper.kt | 93 ++++--- .../piano/android/analytics/PianoAnalytics.kt | 36 +-- .../android/analytics/PlainDataEncoder.kt | 2 +- .../android/analytics/PrivacyModesStorage.kt | 8 +- .../io/piano/android/analytics/RawJson.kt | 2 +- .../piano/android/analytics/RawJsonAdapter.kt | 2 +- .../android/analytics/ReportUrlProvider.kt | 10 +- .../io/piano/android/analytics/UserStorage.kt | 6 +- .../eventprocessors/EventProcessor.kt | 4 +- .../analytics/idproviders/IdProvider.kt | 2 +- .../analytics/model/ContextProperty.kt | 2 +- .../io/piano/android/analytics/model/Enums.kt | 8 +- .../io/piano/android/analytics/model/Event.kt | 46 ++-- .../android/analytics/model/PrivacyMode.kt | 30 +-- .../piano/android/analytics/model/Property.kt | 28 +-- .../android/analytics/model/PropertyName.kt | 228 +++++++++--------- .../io/piano/android/analytics/model/User.kt | 8 +- 23 files changed, 346 insertions(+), 314 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 87737e8..7d66eac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.android.library) apply false alias(libs.plugins.android.app) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.ksp) apply false alias(libs.plugins.ktlint) apply false alias(libs.plugins.mavenRelease) apply false alias(libs.plugins.moshiIR) apply false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3f466e3..bc8b104 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,11 +1,12 @@ [versions] # Plugins -kotlin = "1.8.22" -android = "8.3.1" +kotlin = "1.9.23" +android = "8.3.2" versionUpdater = "0.51.0" ktlint = "12.1.0" mavenRelease = "0.28.0" -moshiIR = "0.22.1" +moshiIR = "0.25.1" +ksp = "1.9.23-1.0.20" # AndroidX libraries compatLibrary = "1.6.1" @@ -15,9 +16,8 @@ materialLibrary = "1.11.0" # Third party Libraries googleAdsId = "18.0.1" huaweiAdsId = "3.4.26.303" -retrofit = "2.6.4" okhttp = "4.12.0" -moshi = "1.15.0" +moshi = "1.15.1" timber = "5.0.1" viewBindingProperty = "1.5.9" @@ -31,6 +31,7 @@ mockitoCore = "5.11.0" android-library = { id = "com.android.library", version.ref = "android" } android-app = { id = "com.android.application", version.ref = "android" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } mavenRelease = { id = "com.vanniktech.maven.publish", version.ref = "mavenRelease" } moshiIR = { id = "dev.zacsweers.moshix", version.ref = "moshiIR"} diff --git a/piano-analytics/build.gradle.kts b/piano-analytics/build.gradle.kts index 22c4739..9e4dfd5 100644 --- a/piano-analytics/build.gradle.kts +++ b/piano-analytics/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) + alias(libs.plugins.ksp) alias(libs.plugins.moshiIR) alias(libs.plugins.ktlint) alias(libs.plugins.mavenRelease) @@ -51,7 +52,7 @@ kotlin { ktlint { android = true - version = "1.1.1" + version = "1.2.1" } dependencies { diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt b/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt index adbe6e9..f080036 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt @@ -8,38 +8,38 @@ import io.piano.android.analytics.model.VisitorStorageMode /** * Class for storing all configuration */ -class Configuration private constructor( - val reportUrlProvider: ReportUrlProvider, - val defaultPrivacyMode: PrivacyMode, - val visitorIDType: VisitorIDType, - val offlineStorageMode: OfflineStorageMode, - val visitorStorageMode: VisitorStorageMode, - val eventsOfflineStorageLifetime: Int, - val privacyStorageLifetime: Int, - val visitorStorageLifetime: Int, - val userStorageLifetime: Int, - val sessionBackgroundDuration: Int, - val detectCrashes: Boolean, - val ignoreLimitedAdTracking: Boolean, - val sendEventWhenOptOut: Boolean, +public class Configuration private constructor( + public val reportUrlProvider: ReportUrlProvider, + public val defaultPrivacyMode: PrivacyMode, + public val visitorIDType: VisitorIDType, + public val offlineStorageMode: OfflineStorageMode, + public val visitorStorageMode: VisitorStorageMode, + public val eventsOfflineStorageLifetime: Int, + public val privacyStorageLifetime: Int, + public val visitorStorageLifetime: Int, + public val userStorageLifetime: Int, + public val sessionBackgroundDuration: Int, + public val detectCrashes: Boolean, + public val ignoreLimitedAdTracking: Boolean, + public val sendEventWhenOptOut: Boolean, ) : ReportUrlProvider by reportUrlProvider { - class Builder @JvmOverloads constructor( - var collectDomain: String = "", - var site: Int = 0, - var path: String = DEFAULT_PATH, - var defaultPrivacyMode: PrivacyMode = PrivacyMode.OPTIN, - var visitorIDType: VisitorIDType = VisitorIDType.UUID, - var offlineStorageMode: OfflineStorageMode = OfflineStorageMode.REQUIRED, - var visitorStorageMode: VisitorStorageMode = VisitorStorageMode.FIXED, - var eventsOfflineStorageLifetime: Int = DEFAULT_EVENTS_OFFLINE_STORAGE_LIFETIME, - var privacyStorageLifetime: Int = DEFAULT_PRIVACY_STORAGE_LIFETIME, - var visitorStorageLifetime: Int = DEFAULT_VISITOR_STORAGE_LIFETIME, - var userStorageLifetime: Int = DEFAULT_USER_STORAGE_LIFETIME, - var sessionBackgroundDuration: Int = DEFAULT_SESSION_BACKGROUND_DURATION, - var detectCrashes: Boolean = true, - var ignoreLimitedAdTracking: Boolean = false, - var sendEventWhenOptOut: Boolean = true, - var reportUrlProvider: ReportUrlProvider? = null, + public class Builder @JvmOverloads constructor( + public var collectDomain: String = "", + public var site: Int = 0, + public var path: String = DEFAULT_PATH, + public var defaultPrivacyMode: PrivacyMode = PrivacyMode.OPTIN, + public var visitorIDType: VisitorIDType = VisitorIDType.UUID, + public var offlineStorageMode: OfflineStorageMode = OfflineStorageMode.REQUIRED, + public var visitorStorageMode: VisitorStorageMode = VisitorStorageMode.FIXED, + public var eventsOfflineStorageLifetime: Int = DEFAULT_EVENTS_OFFLINE_STORAGE_LIFETIME, + public var privacyStorageLifetime: Int = DEFAULT_PRIVACY_STORAGE_LIFETIME, + public var visitorStorageLifetime: Int = DEFAULT_VISITOR_STORAGE_LIFETIME, + public var userStorageLifetime: Int = DEFAULT_USER_STORAGE_LIFETIME, + public var sessionBackgroundDuration: Int = DEFAULT_SESSION_BACKGROUND_DURATION, + public var detectCrashes: Boolean = true, + public var ignoreLimitedAdTracking: Boolean = false, + public var sendEventWhenOptOut: Boolean = true, + public var reportUrlProvider: ReportUrlProvider? = null, ) { /** @@ -48,7 +48,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun collectDomain(collectDomain: String) = apply { this.collectDomain = collectDomain } + public fun collectDomain(collectDomain: String): Builder = apply { this.collectDomain = collectDomain } /** * Set a new site ID @@ -56,7 +56,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun site(site: Int) = apply { this.site = site } + public fun site(site: Int): Builder = apply { this.site = site } /** * Set a new pixel path, to prevent potential tracking blockers by resource @@ -64,7 +64,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun path(path: String) = apply { this.path = path } + public fun path(path: String): Builder = apply { this.path = path } /** * Set a default privacy mode, that will be used on sent event(s) if privacy mode is empty @@ -72,7 +72,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun defaultPrivacyMode(defaultPrivacyMode: PrivacyMode) = apply { + public fun defaultPrivacyMode(defaultPrivacyMode: PrivacyMode): Builder = apply { this.defaultPrivacyMode = defaultPrivacyMode } @@ -82,7 +82,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun visitorIDType(visitorIDType: VisitorIDType) = apply { this.visitorIDType = visitorIDType } + public fun visitorIDType(visitorIDType: VisitorIDType): Builder = apply { this.visitorIDType = visitorIDType } /** * Set an offline mode @@ -90,7 +90,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun offlineStorageMode(offlineStorageMode: OfflineStorageMode) = apply { + public fun offlineStorageMode(offlineStorageMode: OfflineStorageMode): Builder = apply { this.offlineStorageMode = offlineStorageMode } @@ -100,7 +100,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun visitorStorageMode(visitorStorageMode: VisitorStorageMode) = apply { + public fun visitorStorageMode(visitorStorageMode: VisitorStorageMode): Builder = apply { this.visitorStorageMode = visitorStorageMode } @@ -110,7 +110,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun eventsOfflineStorageLifetime(eventsOfflineStorageLifetime: Int) = apply { + public fun eventsOfflineStorageLifetime(eventsOfflineStorageLifetime: Int): Builder = apply { this.eventsOfflineStorageLifetime = eventsOfflineStorageLifetime } @@ -120,7 +120,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun privacyStorageLifetime(privacyStorageLifetime: Int) = apply { + public fun privacyStorageLifetime(privacyStorageLifetime: Int): Builder = apply { this.privacyStorageLifetime = privacyStorageLifetime } @@ -130,7 +130,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun visitorStorageLifetime(visitorStorageLifetime: Int) = apply { + public fun visitorStorageLifetime(visitorStorageLifetime: Int): Builder = apply { this.visitorStorageLifetime = visitorStorageLifetime } @@ -140,7 +140,9 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun userStorageLifetime(userStorageLifetime: Int) = apply { this.userStorageLifetime = userStorageLifetime } + public fun userStorageLifetime(userStorageLifetime: Int): Builder = apply { + this.userStorageLifetime = userStorageLifetime + } /** * Set a new session background duration before a new session will be created @@ -148,7 +150,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun sessionBackgroundDuration(sessionBackgroundDuration: Int) = apply { + public fun sessionBackgroundDuration(sessionBackgroundDuration: Int): Builder = apply { this.sessionBackgroundDuration = sessionBackgroundDuration } @@ -158,7 +160,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun detectCrashes(detectCrashes: Boolean) = apply { this.detectCrashes = detectCrashes } + public fun detectCrashes(detectCrashes: Boolean): Builder = apply { this.detectCrashes = detectCrashes } /** * Enable/disable ignorance advertising tracking limitation @@ -166,7 +168,7 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun ignoreLimitedAdTracking(ignoreLimitedAdTracking: Boolean) = apply { + public fun ignoreLimitedAdTracking(ignoreLimitedAdTracking: Boolean): Builder = apply { this.ignoreLimitedAdTracking = ignoreLimitedAdTracking } @@ -176,14 +178,16 @@ class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. - fun sendEventWhenOptOut(sendEventWhenOptOut: Boolean) = apply { this.sendEventWhenOptOut = sendEventWhenOptOut } + public fun sendEventWhenOptOut(sendEventWhenOptOut: Boolean): Builder = apply { + this.sendEventWhenOptOut = sendEventWhenOptOut + } /** * Sets a custom [ReportUrlProvider], which overrides [collectDomain], [site] and [path] for [Configuration] * @param reportUrlProvider [ReportUrlProvider] instance * @return updated Builder instance */ - fun reportUrlProvider(reportUrlProvider: ReportUrlProvider?) = apply { + public fun reportUrlProvider(reportUrlProvider: ReportUrlProvider?): Builder = apply { this.reportUrlProvider = reportUrlProvider } @@ -192,7 +196,7 @@ class Configuration private constructor( * @return an Configuration instance */ @Suppress("unused") // Public API. - fun build(): Configuration { + public fun build(): Configuration { check(reportUrlProvider != null || (collectDomain.isNotEmpty() && site > 0)) { "You have to provide collectDomain and site or reportUrlProvider" } @@ -214,13 +218,13 @@ class Configuration private constructor( } } - companion object { - const val DEFAULT_PATH = "event" - const val MIN_SESSION_BACKGROUND_DURATION = 2 - const val DEFAULT_SESSION_BACKGROUND_DURATION = 30 - const val DEFAULT_EVENTS_OFFLINE_STORAGE_LIFETIME = 7 - const val DEFAULT_PRIVACY_STORAGE_LIFETIME = 395 - const val DEFAULT_VISITOR_STORAGE_LIFETIME = 395 - const val DEFAULT_USER_STORAGE_LIFETIME = 395 + public companion object { + public const val DEFAULT_PATH: String = "event" + public const val MIN_SESSION_BACKGROUND_DURATION: Int = 2 + public const val DEFAULT_SESSION_BACKGROUND_DURATION: Int = 30 + public const val DEFAULT_EVENTS_OFFLINE_STORAGE_LIFETIME: Int = 7 + public const val DEFAULT_PRIVACY_STORAGE_LIFETIME: Int = 395 + public const val DEFAULT_VISITOR_STORAGE_LIFETIME: Int = 395 + public const val DEFAULT_USER_STORAGE_LIFETIME: Int = 395 } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/ContextPropertiesStorage.kt b/piano-analytics/src/main/java/io/piano/android/analytics/ContextPropertiesStorage.kt index 2f19f30..778491e 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/ContextPropertiesStorage.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/ContextPropertiesStorage.kt @@ -8,7 +8,7 @@ import io.piano.android.analytics.model.PropertyName /** * Stores all customer context properties. Automatically removes non-persistent properties at adding them to event */ -class ContextPropertiesStorage internal constructor( +public class ContextPropertiesStorage internal constructor( private val contextProperties: MutableList = mutableListOf(), ) { @@ -16,13 +16,13 @@ class ContextPropertiesStorage internal constructor( * Clears storage */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun clear() = contextProperties.clear() + public fun clear(): Unit = contextProperties.clear() /** * Adds a [ContextProperty] into storage */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun add(property: ContextProperty) { + public fun add(property: ContextProperty) { val p = if (property.eventNames.isEmpty()) property.copy(eventNames = listOf(Event.ANY)) else property contextProperties.add(p) } @@ -32,7 +32,7 @@ class ContextPropertiesStorage internal constructor( * @param key property key */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun deleteByKey(key: PropertyName) { + public fun deleteByKey(key: PropertyName) { contextProperties.forEachIndexed { index, contextProperty -> contextProperty.properties.filterNotTo(mutableSetOf()) { it.name == key diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/DataEncoder.kt b/piano-analytics/src/main/java/io/piano/android/analytics/DataEncoder.kt index eb112a5..39d6128 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/DataEncoder.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/DataEncoder.kt @@ -4,7 +4,7 @@ package io.piano.android.analytics * An events data encoder. Can be used for encrypting/decrypting events' data at saving in device storage * Your implementation must satisfy condition `decode(encode(data)) == data` for any `data` */ -interface DataEncoder { - fun encode(data: String): String - fun decode(data: String): String +public interface DataEncoder { + public fun encode(data: String): String + public fun decode(data: String): String } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/MediaHelper.kt b/piano-analytics/src/main/java/io/piano/android/analytics/MediaHelper.kt index 1f256ce..e56d63d 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/MediaHelper.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/MediaHelper.kt @@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit /** * Helper for AV Insights */ -class MediaHelper internal constructor( +public class MediaHelper internal constructor( sessionId: String, private val contentId: String, private val pianoAnalytics: PianoAnalytics, @@ -55,14 +55,14 @@ class MediaHelper internal constructor( * Current session id */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - var sessionId: String = sessionId + public var sessionId: String = sessionId private set /** * Current playback speed */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - var playbackSpeed: Double = 1.0 + public var playbackSpeed: Double = 1.0 set(value) { require(value > 0) { "Speed can be only greater than 0" @@ -92,7 +92,7 @@ class MediaHelper internal constructor( * @return this [MediaHelper] instance */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun setHeartbeat(values: SparseLongArray) = apply { + public fun setHeartbeat(values: SparseLongArray): MediaHelper = apply { require(values.size() > 0) { "Can't set empty heartbeat values" } @@ -107,7 +107,7 @@ class MediaHelper internal constructor( * @return this [MediaHelper] instance */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun setBufferHeartbeat(values: SparseLongArray) = apply { + public fun setBufferHeartbeat(values: SparseLongArray): MediaHelper = apply { require(values.size() > 0) { "Can't set empty buffer heartbeat values" } @@ -121,7 +121,7 @@ class MediaHelper internal constructor( * @return this [MediaHelper] instance */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun setExtraProps(vararg extraProps: Property): MediaHelper = apply { + public fun setExtraProps(vararg extraProps: Property): MediaHelper = apply { this.extraProps = extraProps.copyOf() } @@ -132,7 +132,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun heartbeat(cursorPosition: Int, vararg properties: Property) = + public fun heartbeat(cursorPosition: Int, vararg properties: Property): Unit = processHeartbeat(cursorPosition, false, *properties) /** @@ -141,7 +141,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun bufferHeartbeat(vararg properties: Property) = processBufferHeartbeat(false, *properties) + public fun bufferHeartbeat(vararg properties: Property): Unit = processBufferHeartbeat(false, *properties) /** * Generate heartbeat during rebuffering. @@ -149,7 +149,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun rebufferHeartbeat(vararg properties: Property) = processRebufferHeartbeat(false, *properties) + public fun rebufferHeartbeat(vararg properties: Property): Unit = processRebufferHeartbeat(false, *properties) /** * Generate play event (play attempt). @@ -158,7 +158,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun play(cursorPosition: Int, vararg properties: Property) { + public fun play(cursorPosition: Int, vararg properties: Property) { eventDurationMillis = 0 previousCursorPositionMillis = cursorPosition.coerceAtLeast(0) currentCursorPositionMillis = previousCursorPositionMillis @@ -177,7 +177,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun bufferStart(cursorPosition: Int, vararg properties: Property) { + public fun bufferStart(cursorPosition: Int, vararg properties: Property) { val (eventName, runnable) = if (isPlaybackActivated) { AV_REBUFFER_START to rebufferHeartbeatRunnable } else { @@ -208,7 +208,10 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun playbackStart(cursorPosition: Int, vararg properties: Property) = processEvent(AV_START, properties) { + public fun playbackStart(cursorPosition: Int, vararg properties: Property): Unit = processEvent( + AV_START, + properties + ) { previousCursorPositionMillis = cursorPosition.coerceAtLeast(0) currentCursorPositionMillis = previousCursorPositionMillis bufferTimeMillis = 0 @@ -234,7 +237,10 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun playbackPaused(cursorPosition: Int, vararg properties: Property) = processEvent(AV_PAUSE, properties) { + public fun playbackPaused(cursorPosition: Int, vararg properties: Property): Unit = processEvent( + AV_PAUSE, + properties + ) { previousCursorPositionMillis = currentCursorPositionMillis currentCursorPositionMillis = cursorPosition.coerceAtLeast(0) bufferTimeMillis = 0 @@ -250,7 +256,10 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun playbackResumed(cursorPosition: Int, vararg properties: Property) = processEvent(AV_RESUME, properties) { + public fun playbackResumed(cursorPosition: Int, vararg properties: Property): Unit = processEvent( + AV_RESUME, + properties + ) { previousCursorPositionMillis = currentCursorPositionMillis currentCursorPositionMillis = cursorPosition.coerceAtLeast(0) bufferTimeMillis = 0 @@ -276,7 +285,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun playbackStopped(cursorPosition: Int, vararg properties: Property) { + public fun playbackStopped(cursorPosition: Int, vararg properties: Property) { processEvent(AV_STOP, properties) { previousCursorPositionMillis = currentCursorPositionMillis currentCursorPositionMillis = cursorPosition.coerceAtLeast(0) @@ -306,7 +315,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun seek(oldCursorPosition: Int, newCursorPosition: Int, vararg properties: Property) = + public fun seek(oldCursorPosition: Int, newCursorPosition: Int, vararg properties: Property): Unit = if (oldCursorPosition > newCursorPosition) { seekBackward(oldCursorPosition, newCursorPosition, *properties) } else { @@ -321,7 +330,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun seekBackward(oldCursorPosition: Int, newCursorPosition: Int, vararg properties: Property) = + public fun seekBackward(oldCursorPosition: Int, newCursorPosition: Int, vararg properties: Property): Unit = processSeek(AV_BACKWARD, oldCursorPosition, newCursorPosition, properties) /** @@ -332,7 +341,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun seekForward(oldCursorPosition: Int, newCursorPosition: Int, vararg properties: Property) = + public fun seekForward(oldCursorPosition: Int, newCursorPosition: Int, vararg properties: Property): Unit = processSeek(AV_FORWARD, oldCursorPosition, newCursorPosition, properties) /** @@ -342,7 +351,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun seekStart(oldCursorPosition: Int, vararg properties: Property) = + public fun seekStart(oldCursorPosition: Int, vararg properties: Property): Unit = pianoAnalytics.sendEvents(buildSeekStartEvent(oldCursorPosition, properties)) /** @@ -351,7 +360,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun adClick(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_AD_CLICK, false, *properties)) + public fun adClick(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_AD_CLICK, false, *properties) + ) /** * Measuring media skip (especially for ads). @@ -359,7 +370,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun adSkip(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_AD_SKIP, false, *properties)) + public fun adSkip(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_AD_SKIP, false, *properties) + ) /** * Measuring reco or Ad display. @@ -367,7 +380,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun display(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_DISPLAY, false, *properties)) + public fun display(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_DISPLAY, false, *properties) + ) /** * Measuring close action. @@ -375,7 +390,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun close(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_CLOSE, false, *properties)) + public fun close(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_CLOSE, false, *properties) + ) /** * Measurement of a volume change action. @@ -383,7 +400,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun volume(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_VOLUME, false, *properties)) + public fun volume(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_VOLUME, false, *properties) + ) /** * Measurement of activated subtitles. @@ -391,7 +410,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun subtitleOn(vararg properties: Property) = + public fun subtitleOn(vararg properties: Property): Unit = pianoAnalytics.sendEvents(buildEvent(AV_SUBTITLE_ON, false, *properties)) /** @@ -400,7 +419,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun subtitleOff(vararg properties: Property) = + public fun subtitleOff(vararg properties: Property): Unit = pianoAnalytics.sendEvents(buildEvent(AV_SUBTITLE_OFF, false, *properties)) /** @@ -409,7 +428,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun fullscreenOn(vararg properties: Property) = + public fun fullscreenOn(vararg properties: Property): Unit = pianoAnalytics.sendEvents(buildEvent(AV_FULLSCREEN_ON, false, *properties)) /** @@ -418,7 +437,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun fullscreenOff(vararg properties: Property) = + public fun fullscreenOff(vararg properties: Property): Unit = pianoAnalytics.sendEvents(buildEvent(AV_FULLSCREEN_OFF, false, *properties)) /** @@ -427,7 +446,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun quality(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_QUALITY, false, *properties)) + public fun quality(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_QUALITY, false, *properties) + ) /** * Measurement of a speed change action. @@ -435,7 +456,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun speed(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_SPEED, false, *properties)) + public fun speed(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_SPEED, false, *properties) + ) /** * Measurement of a sharing action. @@ -443,7 +466,9 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun share(vararg properties: Property) = pianoAnalytics.sendEvents(buildEvent(AV_SHARE, false, *properties)) + public fun share(vararg properties: Property): Unit = pianoAnalytics.sendEvents( + buildEvent(AV_SHARE, false, *properties) + ) /** * Error measurement preventing reading from continuing. @@ -452,7 +477,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun error(message: String, vararg properties: Property) = pianoAnalytics.sendEvents( + public fun error(message: String, vararg properties: Property): Unit = pianoAnalytics.sendEvents( buildEvent( AV_ERROR, false, @@ -468,7 +493,7 @@ class MediaHelper internal constructor( * @param properties extra properties for event */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - fun track(eventName: String, vararg properties: Property) { + public fun track(eventName: String, vararg properties: Property) { require(eventName !in BUILTIN_EVENTS) { "customEvent should be used only for custom events, not for built-in" } @@ -620,7 +645,7 @@ class MediaHelper internal constructor( @Suppress("NOTHING_TO_INLINE") internal inline fun getCurrentTimestamp() = System.currentTimeMillis() - companion object { + internal companion object { internal const val MIN_HEARTBEAT_DURATION = 5L internal const val MIN_BUFFER_HEARTBEAT_DURATION = 1L private const val AV_PLAY = "av.play" diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt index cac6453..367f12c 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt @@ -21,7 +21,7 @@ import java.util.concurrent.TimeUnit * @property contextPropertiesStorage Storage for context properties * @property userStorage Storage for user data */ -class PianoAnalytics internal constructor( +public class PianoAnalytics internal constructor( private val executorProvider: () -> ScheduledExecutorService, private val configuration: Configuration, private val screenNameProvider: ScreenNameProvider, @@ -33,13 +33,13 @@ class PianoAnalytics internal constructor( customEventProcessorsGroup: GroupEventProcessor, // Public API. @Suppress("unused", "MemberVisibilityCanBePrivate") - val privacyModesStorage: PrivacyModesStorage, + public val privacyModesStorage: PrivacyModesStorage, // Public API. @Suppress("unused", "MemberVisibilityCanBePrivate") - val contextPropertiesStorage: ContextPropertiesStorage, + public val contextPropertiesStorage: ContextPropertiesStorage, // Public API. @Suppress("unused", "MemberVisibilityCanBePrivate") - val userStorage: UserStorage, + public val userStorage: UserStorage, ) { private val executor: ScheduledExecutorService = executorProvider() @@ -47,13 +47,13 @@ class PianoAnalytics internal constructor( * Current visitor id, depends on [Configuration.visitorIDType] */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - val visitorId: String? by visitorIdProvider::visitorId + public val visitorId: String? by visitorIdProvider::visitorId /** * Custom visitor id, will be used if [Configuration.visitorIDType] is set to [VisitorIDType.CUSTOM] */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - var customVisitorId: String? by customIdProvider::visitorId + public var customVisitorId: String? by customIdProvider::visitorId /** * List of custom event processors, which can change sending events. @@ -62,12 +62,12 @@ class PianoAnalytics internal constructor( * @see [EventProcessor] */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - val customEventProcessors: MutableList = customEventProcessorsGroup + public val customEventProcessors: MutableList = customEventProcessorsGroup /** * Callback, which will be called after all events' processors and before sending event. */ - var eventProcessorCallback: EventProcessorCallback = EventProcessorCallback { _ -> } + public var eventProcessorCallback: EventProcessorCallback = EventProcessorCallback { _ -> } /** * Sets current screen name. @@ -76,7 +76,7 @@ class PianoAnalytics internal constructor( * @param name screen name */ @Suppress("unused") // Public API. - fun screenName(name: String) { + public fun screenName(name: String) { screenNameProvider.customScreenName = name contextPropertiesStorage.add( ContextProperty( @@ -95,7 +95,7 @@ class PianoAnalytics internal constructor( */ @Suppress("unused") // Public API. @JvmOverloads - fun mediaHelper( + public fun mediaHelper( contentId: String, mediaSessionId: String = UUID.randomUUID().toString(), ): MediaHelper { @@ -119,7 +119,7 @@ class PianoAnalytics internal constructor( * @param events a custom event list */ @Suppress("unused") // Public API. - fun sendEvents(vararg events: Event) { + public fun sendEvents(vararg events: Event) { // delay is required, see androidx.lifecycle.ProcessLifecycleOwner.TIMEOUT_MS executor.schedule( { @@ -139,7 +139,7 @@ class PianoAnalytics internal constructor( * Send offline data stored on device */ @Suppress("unused") // Public API. - fun sendOfflineData() { + public fun sendOfflineData() { executor.submit(sendTask) } @@ -149,17 +149,17 @@ class PianoAnalytics internal constructor( * @param remaining age of data which have to be kept (in days) */ @Suppress("unused") // Public API. - fun deleteOfflineStorage(remaining: Int = 0) { + public fun deleteOfflineStorage(remaining: Int = 0) { executor.submit { eventRepository.deleteOldEvents(remaining) } } - fun interface EventProcessorCallback { - fun onProcess(events: List) + public fun interface EventProcessorCallback { + public fun onProcess(events: List) } - companion object { + public companion object { /** * Initializes Piano Analytics SDK * @@ -170,7 +170,7 @@ class PianoAnalytics internal constructor( @Suppress("unused") // Public API. @JvmStatic @JvmOverloads - fun init( + public fun init( context: Context, configuration: Configuration, dataEncoder: DataEncoder = PlainDataEncoder, @@ -181,6 +181,6 @@ class PianoAnalytics internal constructor( @Suppress("unused") // Public API. @JvmStatic - fun getInstance(): PianoAnalytics = DependenciesProvider.getInstance().pianoAnalytics + public fun getInstance(): PianoAnalytics = DependenciesProvider.getInstance().pianoAnalytics } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PlainDataEncoder.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PlainDataEncoder.kt index 0d52609..75746be 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PlainDataEncoder.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PlainDataEncoder.kt @@ -1,6 +1,6 @@ package io.piano.android.analytics -object PlainDataEncoder : DataEncoder { +public object PlainDataEncoder : DataEncoder { override fun encode(data: String): String = data override fun decode(data: String): String = data diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt index 21f3e63..4715862 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt @@ -7,7 +7,7 @@ import java.util.concurrent.TimeUnit /** * Stores information about privacy modes */ -class PrivacyModesStorage internal constructor( +public class PrivacyModesStorage internal constructor( private val configuration: Configuration, private val prefsStorage: PrefsStorage, ) { @@ -26,7 +26,7 @@ class PrivacyModesStorage internal constructor( * All registered privacy modes. Add a [PrivacyMode] instance into [allModes] for registering it */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - val allModes = mutableSetOf( + public val allModes: MutableSet = mutableSetOf( PrivacyMode.NO_CONSENT, PrivacyMode.NO_STORAGE, PrivacyMode.OPTIN, @@ -38,7 +38,7 @@ class PrivacyModesStorage internal constructor( * Current privacy visitor mode */ @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. - var currentMode: PrivacyMode = configuration.defaultPrivacyMode + public var currentMode: PrivacyMode = configuration.defaultPrivacyMode get() { if (field != PrivacyMode.NO_CONSENT && field != PrivacyMode.NO_STORAGE) { if (prefsStorage.privacyExpirationTimestamp in 1..System.currentTimeMillis()) { @@ -81,7 +81,7 @@ class PrivacyModesStorage internal constructor( } } - companion object { + private companion object { @JvmStatic private val cachedPrivacyStorageFeatures = enumValues().filter { it != PrivacyStorageFeature.ALL diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/RawJson.kt b/piano-analytics/src/main/java/io/piano/android/analytics/RawJson.kt index 2eb4de3..ba5bb81 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/RawJson.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/RawJson.kt @@ -4,4 +4,4 @@ import com.squareup.moshi.JsonQualifier @Retention(AnnotationRetention.RUNTIME) @JsonQualifier -annotation class RawJson +internal annotation class RawJson diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/RawJsonAdapter.kt b/piano-analytics/src/main/java/io/piano/android/analytics/RawJsonAdapter.kt index 792b271..4f1e156 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/RawJsonAdapter.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/RawJsonAdapter.kt @@ -6,7 +6,7 @@ import com.squareup.moshi.JsonWriter import com.squareup.moshi.ToJson import okio.Buffer -object RawJsonAdapter { +internal object RawJsonAdapter { @FromJson @RawJson fun fromJson(reader: JsonReader): List = buildList { diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/ReportUrlProvider.kt b/piano-analytics/src/main/java/io/piano/android/analytics/ReportUrlProvider.kt index 421fffa..5b882d6 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/ReportUrlProvider.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/ReportUrlProvider.kt @@ -4,28 +4,28 @@ package io.piano.android.analytics * Interface for providing URL parts like [collectDomain], [site] adn [path] * SDK doesn't cache results from these methods, which allows you to dynamically change values */ -interface ReportUrlProvider { +public interface ReportUrlProvider { /** * fully qualified domain name (FQDN) collect */ - val collectDomain: String + public val collectDomain: String /** * site identifier */ - val site: Int + public val site: Int /** * a resource name string prefixed by '/' */ - val path: String + public val path: String get() = Configuration.DEFAULT_PATH } /** * Implementation of [ReportUrlProvider], that return static values */ -class StaticReportUrlProvider( +public class StaticReportUrlProvider( override val collectDomain: String, override val site: Int, override val path: String = Configuration.DEFAULT_PATH, diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/UserStorage.kt b/piano-analytics/src/main/java/io/piano/android/analytics/UserStorage.kt index 18ddac8..0cd9696 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/UserStorage.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/UserStorage.kt @@ -7,7 +7,7 @@ import java.util.concurrent.TimeUnit /** * Stores user information */ -class UserStorage internal constructor( +public class UserStorage internal constructor( private val configuration: Configuration, private val prefsStorage: PrefsStorage, private val userJsonAdapter: JsonAdapter, @@ -36,7 +36,7 @@ class UserStorage internal constructor( /** * Current [User], set null for removing */ - var currentUser: User? = null + public var currentUser: User? = null get() = field ?: storedUser set(value) { userRecognized = false @@ -48,7 +48,7 @@ class UserStorage internal constructor( /** * Returns true, if [currentUser] was loaded from storage */ - var userRecognized: Boolean = storedUser != null + public var userRecognized: Boolean = storedUser != null private set @Suppress("NOTHING_TO_INLINE") diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/eventprocessors/EventProcessor.kt b/piano-analytics/src/main/java/io/piano/android/analytics/eventprocessors/EventProcessor.kt index 10d9a85..d9739bf 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/eventprocessors/EventProcessor.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/eventprocessors/EventProcessor.kt @@ -5,7 +5,7 @@ import io.piano.android.analytics.model.Event /** * An event processor. Can change any data in events */ -fun interface EventProcessor { +public fun interface EventProcessor { /** * You can add, remove or change events here. * Return list (can be empty) of events, which will be pushed to next [EventProcessor]. @@ -13,5 +13,5 @@ fun interface EventProcessor { * @param events immutable list of events, which should be processed * @return list of events, which should be sent. */ - fun process(events: List): List + public fun process(events: List): List } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/idproviders/IdProvider.kt b/piano-analytics/src/main/java/io/piano/android/analytics/idproviders/IdProvider.kt index 77e30e3..d12c1ed 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/idproviders/IdProvider.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/idproviders/IdProvider.kt @@ -1,6 +1,6 @@ package io.piano.android.analytics.idproviders -interface IdProvider { +internal interface IdProvider { val visitorId: String? val isLimitAdTrackingEnabled: Boolean } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/ContextProperty.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/ContextProperty.kt index e2118b6..04b7cf9 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/ContextProperty.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/ContextProperty.kt @@ -8,7 +8,7 @@ package io.piano.android.analytics.model * @param eventNames specifies with which events the [properties] will be sent * @constructor Creates a customer context property */ -data class ContextProperty @JvmOverloads constructor( +public data class ContextProperty @JvmOverloads constructor( val properties: Set, val persistent: Boolean = false, val eventNames: Collection = emptyList(), diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt index d6a7cc7..a57210f 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/Enums.kt @@ -7,7 +7,7 @@ internal enum class ConnectionType(val key: String) { UNKNOWN("UNKNOWN"), } -enum class VisitorIDType { +public enum class VisitorIDType { ADVERTISING_ID, GOOGLE_ADVERTISING_ID, HUAWEI_OPEN_ADVERTISING_ID, @@ -15,7 +15,7 @@ enum class VisitorIDType { CUSTOM, } -enum class PrivacyStorageFeature { +public enum class PrivacyStorageFeature { VISITOR, CRASH, LIFECYCLE, @@ -24,7 +24,7 @@ enum class PrivacyStorageFeature { ALL, } -enum class OfflineStorageMode { +public enum class OfflineStorageMode { /** * Hits are stored in all cases and requires calling method to send */ @@ -36,7 +36,7 @@ enum class OfflineStorageMode { REQUIRED, } -enum class VisitorStorageMode { +public enum class VisitorStorageMode { /** * FIXED : UUID will expires in all cases */ diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/Event.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/Event.kt index ca370b2..58c9710 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/Event.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/Event.kt @@ -2,21 +2,21 @@ package io.piano.android.analytics.model import java.util.Collections -class Event private constructor( - val name: String, - val properties: Set, +public class Event private constructor( + public val name: String, + public val properties: Set, ) { - fun newBuilder(): Builder = Builder(name, properties.toMutableSet()) + public fun newBuilder(): Builder = Builder(name, properties.toMutableSet()) - data class Builder constructor( + public data class Builder constructor( var name: String, val properties: MutableSet = mutableSetOf(), ) { - fun name(name: String) = apply { this.name = name } - fun properties(vararg properties: Property) = apply { this.properties.addAll(properties) } - fun properties(properties: Collection) = apply { this.properties.addAll(properties) } + public fun name(name: String): Builder = apply { this.name = name } + public fun properties(vararg properties: Property): Builder = apply { this.properties.addAll(properties) } + public fun properties(properties: Collection): Builder = apply { this.properties.addAll(properties) } - fun build(): Event { + public fun build(): Event { check(name.isNotBlank()) { "Event name should be filled" } @@ -27,19 +27,19 @@ class Event private constructor( } } - companion object { - const val ANY = "*" - const val PAGE_DISPLAY = "page.display" - const val CLICK_ACTION = "click.action" - const val CLICK_NAVIGATION = "click.navigation" - const val CLICK_DOWNLOAD = "click.download" - const val CLICK_EXIT = "click.exit" - const val PUBLISHER_IMPRESSION = "publisher.impression" - const val PUBLISHER_CLICK = "publisher.click" - const val SELF_PROMOTION_IMPRESSION = "self_promotion.impression" - const val SELF_PROMOTION_CLICK = "self_promotion.click" - const val INTERNAL_SEARCH_RESULT_DISPLAY = "internal_search_result.display" - const val INTERNAL_SEARCH_RESULT_CLICK = "internal_search_result.click" - const val MV_TEST_DISPLAY = "mv_test.display" + public companion object { + public const val ANY: String = "*" + public const val PAGE_DISPLAY: String = "page.display" + public const val CLICK_ACTION: String = "click.action" + public const val CLICK_NAVIGATION: String = "click.navigation" + public const val CLICK_DOWNLOAD: String = "click.download" + public const val CLICK_EXIT: String = "click.exit" + public const val PUBLISHER_IMPRESSION: String = "publisher.impression" + public const val PUBLISHER_CLICK: String = "publisher.click" + public const val SELF_PROMOTION_IMPRESSION: String = "self_promotion.impression" + public const val SELF_PROMOTION_CLICK: String = "self_promotion.click" + public const val INTERNAL_SEARCH_RESULT_DISPLAY: String = "internal_search_result.display" + public const val INTERNAL_SEARCH_RESULT_CLICK: String = "internal_search_result.click" + public const val MV_TEST_DISPLAY: String = "mv_test.display" } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt index 8ff70ee..397be53 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt @@ -13,17 +13,17 @@ package io.piano.android.analytics.model * @param forbiddenPropertyKeys set of forbidden property names for mode * @constructor Creates a new privacy mode */ -class PrivacyMode( - val visitorMode: String, - val visitorConsent: Boolean = false, - val allowedEventNames: MutableSet = DEFAULT_EVENT_NAMES.toMutableSet(), - val forbiddenEventNames: MutableSet = mutableSetOf(), - val allowedStorageFeatures: MutableSet = DEFAULT_STORAGE_FEATURES.toMutableSet(), - val forbiddenStorageFeatures: MutableSet = mutableSetOf(), - val allowedPropertyKeys: MutableMap> = mutableMapOf( +public class PrivacyMode( + public val visitorMode: String, + public val visitorConsent: Boolean = false, + public val allowedEventNames: MutableSet = DEFAULT_EVENT_NAMES.toMutableSet(), + public val forbiddenEventNames: MutableSet = mutableSetOf(), + public val allowedStorageFeatures: MutableSet = DEFAULT_STORAGE_FEATURES.toMutableSet(), + public val forbiddenStorageFeatures: MutableSet = mutableSetOf(), + public val allowedPropertyKeys: MutableMap> = mutableMapOf( Event.ANY to EXEMPT_DEFAULT_PROPERTY_KEYS.toMutableSet() ), - val forbiddenPropertyKeys: MutableMap> = mutableMapOf(), + public val forbiddenPropertyKeys: MutableMap> = mutableMapOf(), ) { override fun equals(other: Any?): Boolean { @@ -37,7 +37,7 @@ class PrivacyMode( override fun toString(): String = visitorMode - companion object { + public companion object { @JvmStatic internal val DEFAULT_EVENT_NAMES = setOf( Event.CLICK_ACTION, @@ -159,7 +159,7 @@ class PrivacyMode( * Opt-in privacy mode */ @JvmStatic - val OPTIN = PrivacyMode( + public val OPTIN: PrivacyMode = PrivacyMode( visitorMode = "optin", visitorConsent = true, allowedEventNames = mutableSetOf(Event.ANY), @@ -171,7 +171,7 @@ class PrivacyMode( * Opt-out privacy mode */ @JvmStatic - val OPTOUT = PrivacyMode( + public val OPTOUT: PrivacyMode = PrivacyMode( visitorMode = "optout", allowedEventNames = mutableSetOf(Event.ANY), allowedPropertyKeys = mutableMapOf(Event.ANY to MINIMUM_DEFAULT_PROPERTY_KEYS.toMutableSet()) @@ -181,13 +181,13 @@ class PrivacyMode( * Exempt privacy mode */ @JvmStatic - val EXEMPT = PrivacyMode(visitorMode = "exempt") + public val EXEMPT: PrivacyMode = PrivacyMode(visitorMode = "exempt") /** * No consent privacy mode */ @JvmStatic - val NO_CONSENT = PrivacyMode( + public val NO_CONSENT: PrivacyMode = PrivacyMode( visitorMode = "no-consent", allowedEventNames = mutableSetOf(Event.ANY), allowedStorageFeatures = mutableSetOf(), @@ -199,7 +199,7 @@ class PrivacyMode( * No storage privacy mode */ @JvmStatic - val NO_STORAGE = PrivacyMode( + public val NO_STORAGE: PrivacyMode = PrivacyMode( visitorMode = "no-storage", allowedEventNames = mutableSetOf(Event.ANY), allowedStorageFeatures = mutableSetOf(), diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt index 07ce45d..9972837 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt @@ -5,10 +5,10 @@ import java.util.Date /** * Event property */ -class Property { - val name: PropertyName - val value: Any - val forceType: Type? +public class Property { + public val name: PropertyName + public val value: Any + public val forceType: Type? override fun equals(other: Any?): Boolean { if (this === other) return true @@ -31,7 +31,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: String, forceType: Type? = null) { + public constructor(name: PropertyName, value: String, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -44,7 +44,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Int, forceType: Type? = null) { + public constructor(name: PropertyName, value: Int, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -57,7 +57,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Long, forceType: Type? = null) { + public constructor(name: PropertyName, value: Long, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -70,7 +70,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Double, forceType: Type? = null) { + public constructor(name: PropertyName, value: Double, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -83,7 +83,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Date) : this(name, value.time / 1000, Type.DATE) + public constructor(name: PropertyName, value: Date) : this(name, value.time / 1000, Type.DATE) /** * Creates a new property @@ -91,7 +91,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Boolean, forceType: Type? = null) { + public constructor(name: PropertyName, value: Boolean, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -104,7 +104,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Array, forceType: Type? = null) { + public constructor(name: PropertyName, value: Array, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -117,7 +117,7 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Array, forceType: Type? = null) { + public constructor(name: PropertyName, value: Array, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value @@ -130,14 +130,14 @@ class Property { * @param name property name * @param value property value */ - constructor(name: PropertyName, value: Array, forceType: Type? = null) { + public constructor(name: PropertyName, value: Array, forceType: Type? = null) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value this.forceType = forceType } - enum class Type(val prefix: String) { + public enum class Type(public val prefix: String) { STRING("s"), INTEGER("n"), FLOAT("f"), diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/PropertyName.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/PropertyName.kt index a39c1d1..a4b60d1 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/PropertyName.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/PropertyName.kt @@ -1,8 +1,8 @@ package io.piano.android.analytics.model @JvmInline -value class PropertyName( - val key: String, +public value class PropertyName( + public val key: String, ) { init { require( @@ -16,7 +16,7 @@ value class PropertyName( } } - companion object { + public companion object { internal const val PREFIX_M = "m_" internal const val PREFIX_VISIT = "visit_" internal const val MAX_LENGTH = 40 @@ -30,336 +30,336 @@ value class PropertyName( } @JvmStatic - val ANY_PROPERTY = PropertyName("*") + public val ANY_PROPERTY: PropertyName = PropertyName("*") @JvmStatic - val APP_CRASH = PropertyName("app_crash") + public val APP_CRASH: PropertyName = PropertyName("app_crash") @JvmStatic - val APP_CRASH_CLASS = PropertyName("app_crash_class") + public val APP_CRASH_CLASS: PropertyName = PropertyName("app_crash_class") @JvmStatic - val APP_CRASH_SCREEN = PropertyName("app_crash_screen") + public val APP_CRASH_SCREEN: PropertyName = PropertyName("app_crash_screen") @JvmStatic - val APP_DAYS_SINCE_FIRST_SESSION = PropertyName("app_dsfs") + public val APP_DAYS_SINCE_FIRST_SESSION: PropertyName = PropertyName("app_dsfs") @JvmStatic - val APP_DAYS_SINCE_LAST_SESSION = PropertyName("app_dsls") + public val APP_DAYS_SINCE_LAST_SESSION: PropertyName = PropertyName("app_dsls") @JvmStatic - val APP_DAYS_SINCE_UPDATE = PropertyName("app_dsu") + public val APP_DAYS_SINCE_UPDATE: PropertyName = PropertyName("app_dsu") @JvmStatic - val APP_ID = PropertyName("app_id") + public val APP_ID: PropertyName = PropertyName("app_id") @JvmStatic - val APP_FIRST_SESSION = PropertyName("app_fs") + public val APP_FIRST_SESSION: PropertyName = PropertyName("app_fs") @JvmStatic - val APP_FIRST_SESSION_AFTER_UPDATE = PropertyName("app_fsau") + public val APP_FIRST_SESSION_AFTER_UPDATE: PropertyName = PropertyName("app_fsau") @JvmStatic - val APP_FIRST_SESSION_DATE = PropertyName("app_fsd") + public val APP_FIRST_SESSION_DATE: PropertyName = PropertyName("app_fsd") @JvmStatic - val APP_FIRST_SESSION_DATE_AFTER_UPDATE = PropertyName("app_fsdau") + public val APP_FIRST_SESSION_DATE_AFTER_UPDATE: PropertyName = PropertyName("app_fsdau") @JvmStatic - val APP_SESSION_COUNT = PropertyName("app_sc") + public val APP_SESSION_COUNT: PropertyName = PropertyName("app_sc") @JvmStatic - val APP_SESSION_COUNT_SINCE_UPDATE = PropertyName("app_scsu") + public val APP_SESSION_COUNT_SINCE_UPDATE: PropertyName = PropertyName("app_scsu") @JvmStatic - val APP_SESSION_ID = PropertyName("app_sessionid") + public val APP_SESSION_ID: PropertyName = PropertyName("app_sessionid") @JvmStatic - val APP_VERSION = PropertyName("app_version") + public val APP_VERSION: PropertyName = PropertyName("app_version") @JvmStatic - val BROWSER = PropertyName("browser") + public val BROWSER: PropertyName = PropertyName("browser") @JvmStatic - val BROWSER_LANGUAGE = PropertyName("browser_language") + public val BROWSER_LANGUAGE: PropertyName = PropertyName("browser_language") @JvmStatic - val BROWSER_LANGUAGE_LOCAL = PropertyName("browser_language_local") + public val BROWSER_LANGUAGE_LOCAL: PropertyName = PropertyName("browser_language_local") @JvmStatic - val BROWSER_COOKIE_ACCEPTANCE = PropertyName("browser_cookie_acceptance") + public val BROWSER_COOKIE_ACCEPTANCE: PropertyName = PropertyName("browser_cookie_acceptance") @JvmStatic - val BROWSER_GROUP = PropertyName("browser_group") + public val BROWSER_GROUP: PropertyName = PropertyName("browser_group") @JvmStatic - val BROWSER_VERSION = PropertyName("browser_version") + public val BROWSER_VERSION: PropertyName = PropertyName("browser_version") @JvmStatic - val CLICK = PropertyName("click") + public val CLICK: PropertyName = PropertyName("click") @JvmStatic - val CLICK_CHAPTER1 = PropertyName("click_chapter1") + public val CLICK_CHAPTER1: PropertyName = PropertyName("click_chapter1") @JvmStatic - val CLICK_CHAPTER2 = PropertyName("click_chapter2") + public val CLICK_CHAPTER2: PropertyName = PropertyName("click_chapter2") @JvmStatic - val CLICK_CHAPTER3 = PropertyName("click_chapter3") + public val CLICK_CHAPTER3: PropertyName = PropertyName("click_chapter3") @JvmStatic - val CLICK_FULL_NAME = PropertyName("click_full_name") + public val CLICK_FULL_NAME: PropertyName = PropertyName("click_full_name") @JvmStatic - val CONNECTION_MONITOR = PropertyName("connection_monitor") + public val CONNECTION_MONITOR: PropertyName = PropertyName("connection_monitor") @JvmStatic - val CONNECTION_ORGANISATION = PropertyName("connection_organisation") + public val CONNECTION_ORGANISATION: PropertyName = PropertyName("connection_organisation") @JvmStatic - val CONNECTION_TYPE = PropertyName("connection_type") + public val CONNECTION_TYPE: PropertyName = PropertyName("connection_type") @JvmStatic - val DATE = PropertyName("date") + public val DATE: PropertyName = PropertyName("date") @JvmStatic - val DATE_DAY = PropertyName("date_day") + public val DATE_DAY: PropertyName = PropertyName("date_day") @JvmStatic - val DATE_DAYNUMBER = PropertyName("date_daynumber") + public val DATE_DAYNUMBER: PropertyName = PropertyName("date_daynumber") @JvmStatic - val DATE_MONTH = PropertyName("date_month") + public val DATE_MONTH: PropertyName = PropertyName("date_month") @JvmStatic - val DATE_MONTHNUMBER = PropertyName("date_monthnumber") + public val DATE_MONTHNUMBER: PropertyName = PropertyName("date_monthnumber") @JvmStatic - val DATE_WEEK = PropertyName("date_week") + public val DATE_WEEK: PropertyName = PropertyName("date_week") @JvmStatic - val DATE_YEAR = PropertyName("date_year") + public val DATE_YEAR: PropertyName = PropertyName("date_year") @JvmStatic - val DATE_YEAROFWEEK = PropertyName("date_yearofweek") + public val DATE_YEAROFWEEK: PropertyName = PropertyName("date_yearofweek") @JvmStatic - val DEVICE_BRAND = PropertyName("device_brand") + public val DEVICE_BRAND: PropertyName = PropertyName("device_brand") @JvmStatic - val DEVICE_DISPLAY_HEIGHT = PropertyName("device_display_height") + public val DEVICE_DISPLAY_HEIGHT: PropertyName = PropertyName("device_display_height") @JvmStatic - val DEVICE_DISPLAY_WIDTH = PropertyName("device_display_width") + public val DEVICE_DISPLAY_WIDTH: PropertyName = PropertyName("device_display_width") @JvmStatic - val DEVICE_NAME = PropertyName("device_name") + public val DEVICE_NAME: PropertyName = PropertyName("device_name") @JvmStatic - val DEVICE_NAME_TECH = PropertyName("device_name_tech") + public val DEVICE_NAME_TECH: PropertyName = PropertyName("device_name_tech") @JvmStatic - val DEVICE_SCREEN_DIAGONAL = PropertyName("device_screen_diagonal") + public val DEVICE_SCREEN_DIAGONAL: PropertyName = PropertyName("device_screen_diagonal") @JvmStatic - val DEVICE_SCREEN_HEIGHT = PropertyName("device_screen_height") + public val DEVICE_SCREEN_HEIGHT: PropertyName = PropertyName("device_screen_height") @JvmStatic - val DEVICE_SCREEN_WIDTH = PropertyName("device_screen_width") + public val DEVICE_SCREEN_WIDTH: PropertyName = PropertyName("device_screen_width") @JvmStatic - val DEVICE_TIMESTAMP_UTC = PropertyName("device_timestamp_utc") + public val DEVICE_TIMESTAMP_UTC: PropertyName = PropertyName("device_timestamp_utc") @JvmStatic - val DEVICE_TYPE = PropertyName("device_type") + public val DEVICE_TYPE: PropertyName = PropertyName("device_type") @JvmStatic - val EVENT_COLLECTION_PLATFORM = PropertyName("event_collection_platform") + public val EVENT_COLLECTION_PLATFORM: PropertyName = PropertyName("event_collection_platform") @JvmStatic - val EVENT_COLLECTION_VERSION = PropertyName("event_collection_version") + public val EVENT_COLLECTION_VERSION: PropertyName = PropertyName("event_collection_version") @JvmStatic - val EVENT_HOUR = PropertyName("event_hour") + public val EVENT_HOUR: PropertyName = PropertyName("event_hour") @JvmStatic - val EVENT_ID = PropertyName("event_id") + public val EVENT_ID: PropertyName = PropertyName("event_id") @JvmStatic - val EVENT_MINUTE = PropertyName("event_minute") + public val EVENT_MINUTE: PropertyName = PropertyName("event_minute") @JvmStatic - val EVENT_NAME = PropertyName("event_name") + public val EVENT_NAME: PropertyName = PropertyName("event_name") @JvmStatic - val EVENT_POSITION = PropertyName("event_position") + public val EVENT_POSITION: PropertyName = PropertyName("event_position") @JvmStatic - val EVENT_SECOND = PropertyName("event_second") + public val EVENT_SECOND: PropertyName = PropertyName("event_second") @JvmStatic - val EVENT_TIME = PropertyName("event_time") + public val EVENT_TIME: PropertyName = PropertyName("event_time") @JvmStatic - val EVENT_TIME_UTC = PropertyName("event_time_utc") + public val EVENT_TIME_UTC: PropertyName = PropertyName("event_time_utc") @JvmStatic - val EVENT_URL = PropertyName("event_url") + public val EVENT_URL: PropertyName = PropertyName("event_url") @JvmStatic - val EVENT_URL_DOMAIN = PropertyName("event_url_domain") + public val EVENT_URL_DOMAIN: PropertyName = PropertyName("event_url_domain") @JvmStatic - val EVENT_URL_FULL = PropertyName("event_url_full") + public val EVENT_URL_FULL: PropertyName = PropertyName("event_url_full") @JvmStatic - val EXCLUSION_CAUSE = PropertyName("exclusion_cause") + public val EXCLUSION_CAUSE: PropertyName = PropertyName("exclusion_cause") @JvmStatic - val EXCLUSION_TYPE = PropertyName("exclusion_type") + public val EXCLUSION_TYPE: PropertyName = PropertyName("exclusion_type") @JvmStatic - val GEO_CITY = PropertyName("geo_city") + public val GEO_CITY: PropertyName = PropertyName("geo_city") @JvmStatic - val GEO_CONTINENT = PropertyName("geo_continent") + public val GEO_CONTINENT: PropertyName = PropertyName("geo_continent") @JvmStatic - val GEO_COUNTRY = PropertyName("geo_country") + public val GEO_COUNTRY: PropertyName = PropertyName("geo_country") @JvmStatic - val GEO_METRO = PropertyName("geo_metro") + public val GEO_METRO: PropertyName = PropertyName("geo_metro") @JvmStatic - val GEO_REGION = PropertyName("geo_region") + public val GEO_REGION: PropertyName = PropertyName("geo_region") @JvmStatic - val HIT_TIME_UTC = PropertyName("hit_time_utc") + public val HIT_TIME_UTC: PropertyName = PropertyName("hit_time_utc") @JvmStatic - val DEVICE_MANUFACTURER = PropertyName("device_manufacturer") + public val DEVICE_MANUFACTURER: PropertyName = PropertyName("device_manufacturer") @JvmStatic - val DEVICE_MODEL = PropertyName("device_model") + public val DEVICE_MODEL: PropertyName = PropertyName("device_model") @JvmStatic - val OS = PropertyName("os") + public val OS: PropertyName = PropertyName("os") @JvmStatic - val OS_GROUP = PropertyName("os_group") + public val OS_GROUP: PropertyName = PropertyName("os_group") @JvmStatic - val OS_VERSION = PropertyName("os_version") + public val OS_VERSION: PropertyName = PropertyName("os_version") @JvmStatic - val OS_VERSION_NAME = PropertyName("os_version_name") + public val OS_VERSION_NAME: PropertyName = PropertyName("os_version_name") @JvmStatic - val PAGE = PropertyName("page") + public val PAGE: PropertyName = PropertyName("page") @JvmStatic - val PAGE_CHAPTER1 = PropertyName("page_chapter1") + public val PAGE_CHAPTER1: PropertyName = PropertyName("page_chapter1") @JvmStatic - val PAGE_CHAPTER2 = PropertyName("page_chapter2") + public val PAGE_CHAPTER2: PropertyName = PropertyName("page_chapter2") @JvmStatic - val PAGE_CHAPTER3 = PropertyName("page_chapter3") + public val PAGE_CHAPTER3: PropertyName = PropertyName("page_chapter3") @JvmStatic - val PAGE_DURATION = PropertyName("page_duration") + public val PAGE_DURATION: PropertyName = PropertyName("page_duration") @JvmStatic - val PAGE_FULL_NAME = PropertyName("page_full_name") + public val PAGE_FULL_NAME: PropertyName = PropertyName("page_full_name") @JvmStatic - val PAGE_POSITION = PropertyName("page_position") + public val PAGE_POSITION: PropertyName = PropertyName("page_position") @JvmStatic - val PRIVACY_STATUS = PropertyName("privacy_status") + public val PRIVACY_STATUS: PropertyName = PropertyName("privacy_status") @JvmStatic - val SITE = PropertyName("site") + public val SITE: PropertyName = PropertyName("site") @JvmStatic - val SITE_ENV = PropertyName("site_env") + public val SITE_ENV: PropertyName = PropertyName("site_env") @JvmStatic - val SITE_ID = PropertyName("site_id") + public val SITE_ID: PropertyName = PropertyName("site_id") @JvmStatic - val SITE_PLATFORM = PropertyName("site_platform") + public val SITE_PLATFORM: PropertyName = PropertyName("site_platform") @JvmStatic - val SRC = PropertyName("src") + public val SRC: PropertyName = PropertyName("src") @JvmStatic - val SRC_DETAIL = PropertyName("src_detail") + public val SRC_DETAIL: PropertyName = PropertyName("src_detail") @JvmStatic - val SRC_DIRECT_ACCESS = PropertyName("src_direct_access") + public val SRC_DIRECT_ACCESS: PropertyName = PropertyName("src_direct_access") @JvmStatic - val SRC_ORGANIC = PropertyName("src_organic") + public val SRC_ORGANIC: PropertyName = PropertyName("src_organic") @JvmStatic - val SRC_ORGANIC_DETAIL = PropertyName("src_organic_detail") + public val SRC_ORGANIC_DETAIL: PropertyName = PropertyName("src_organic_detail") @JvmStatic - val SRC_PORTAL_DOMAIN = PropertyName("src_portal_domain") + public val SRC_PORTAL_DOMAIN: PropertyName = PropertyName("src_portal_domain") @JvmStatic - val SRC_PORTAL_SITE = PropertyName("src_portal_site") + public val SRC_PORTAL_SITE: PropertyName = PropertyName("src_portal_site") @JvmStatic - val SRC_PORTAL_SITE_ID = PropertyName("src_portal_site_id") + public val SRC_PORTAL_SITE_ID: PropertyName = PropertyName("src_portal_site_id") @JvmStatic - val SRC_PORTAL_URL = PropertyName("src_portal_url") + public val SRC_PORTAL_URL: PropertyName = PropertyName("src_portal_url") @JvmStatic - val SRC_REFERRER_SITE_DOMAIN = PropertyName("src_referrer_site_domain") + public val SRC_REFERRER_SITE_DOMAIN: PropertyName = PropertyName("src_referrer_site_domain") @JvmStatic - val SRC_REFERRER_SITE_URL = PropertyName("src_referrer_site_url") + public val SRC_REFERRER_SITE_URL: PropertyName = PropertyName("src_referrer_site_url") @JvmStatic - val SRC_REFERRER_URL = PropertyName("src_referrer_url") + public val SRC_REFERRER_URL: PropertyName = PropertyName("src_referrer_url") @JvmStatic - val SRC_SE = PropertyName("src_se") + public val SRC_SE: PropertyName = PropertyName("src_se") @JvmStatic - val SRC_SE_CATEGORY = PropertyName("src_se_category") + public val SRC_SE_CATEGORY: PropertyName = PropertyName("src_se_category") @JvmStatic - val SRC_SE_COUNTRY = PropertyName("src_se_country") + public val SRC_SE_COUNTRY: PropertyName = PropertyName("src_se_country") @JvmStatic - val SRC_TYPE = PropertyName("src_type") + public val SRC_TYPE: PropertyName = PropertyName("src_type") @JvmStatic - val SRC_URL = PropertyName("src_url") + public val SRC_URL: PropertyName = PropertyName("src_url") @JvmStatic - val SRC_URL_DOMAIN = PropertyName("src_url_domain") + public val SRC_URL_DOMAIN: PropertyName = PropertyName("src_url_domain") @JvmStatic - val SRC_WEBMAIL = PropertyName("src_webmail") + public val SRC_WEBMAIL: PropertyName = PropertyName("src_webmail") @JvmStatic - val USER_ID = PropertyName("user_id") + public val USER_ID: PropertyName = PropertyName("user_id") @JvmStatic - val USER_RECOGNITION = PropertyName("user_recognition") + public val USER_RECOGNITION: PropertyName = PropertyName("user_recognition") @JvmStatic - val USER_CATEGORY = PropertyName("user_category") + public val USER_CATEGORY: PropertyName = PropertyName("user_category") @JvmStatic - val VISITOR_PRIVACY_CONSENT = PropertyName("visitor_privacy_consent") + public val VISITOR_PRIVACY_CONSENT: PropertyName = PropertyName("visitor_privacy_consent") @JvmStatic - val VISITOR_PRIVACY_MODE = PropertyName("visitor_privacy_mode") + public val VISITOR_PRIVACY_MODE: PropertyName = PropertyName("visitor_privacy_mode") } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/User.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/User.kt index bf2bc52..8529ab2 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/User.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/User.kt @@ -12,11 +12,11 @@ import com.squareup.moshi.JsonClass * @constructor Creates user object */ @JsonClass(generateAdapter = true) -class User( +public class User( @Json(name = "id") - val id: String, + public val id: String, @Json(name = "category") - val category: String?, + public val category: String?, @Json(ignore = true) - val shouldBeStored: Boolean = true, + public val shouldBeStored: Boolean = true, ) From 91d1fe57d64a301aaf68ba4d718cd085b726f30b Mon Sep 17 00:00:00 2001 From: DeKaN Date: Tue, 16 Apr 2024 13:48:23 +0400 Subject: [PATCH 4/8] Migrate to PIano Consents library --- .github/workflows/build.yml | 2 + CHANGELOG.md | 9 +- app/src/main/AndroidManifest.xml | 2 +- .../java/com/example/pianoanalytics/App.kt | 8 +- .../example/pianoanalytics/MainActivity.kt | 40 ++ app/src/main/res/menu/main_menu.xml | 18 + build.gradle.kts | 1 + gradle/libs.versions.toml | 8 +- piano-analytics/api/piano-analytics.api | 674 ++++++++++++++++++ piano-analytics/build.gradle.kts | 2 + piano-analytics/gradle.properties | 2 +- .../piano/android/analytics/Configuration.kt | 6 + .../android/analytics/DependenciesProvider.kt | 21 +- .../analytics/EventPropertiesJsonAdapter.kt | 2 +- .../piano/android/analytics/PianoAnalytics.kt | 10 +- .../android/analytics/PrivacyModesStorage.kt | 22 +- .../android/analytics/model/PrivacyMode.kt | 17 + .../piano/android/analytics/model/Property.kt | 2 +- settings.gradle.kts | 9 +- 19 files changed, 840 insertions(+), 15 deletions(-) create mode 100644 app/src/main/res/menu/main_menu.xml create mode 100644 piano-analytics/api/piano-analytics.api diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6943c7b..b347b6c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,8 @@ jobs: run: chmod +x gradlew - name: Check code style run: ./gradlew ktlintCheck --continue + - name: Check API binary compatibility + run: ./gradlew apiCheck - name: Run tests run: ./gradlew testDebug - name: Build project diff --git a/CHANGELOG.md b/CHANGELOG.md index 24da932..464c651 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,15 @@ # Piano Analytics SDK for Android -## v3.3.6-SNAPSHOT +## v3.4.0-SNAPSHOT +* Updated to Kotlin 1.9 +* Added support for `PianoConsents` +* Added `PrivacyMode.CUSTOM`, that will be used if set `ConsentMode.CUSTOM` +* Deprecated `PrivacyModesStorage`, use `PianoConsents` instead * Removed requirement for `READ_PHONE_STATE` permission for Android 6-9 * Updated dependencies: + - Kotlin [1.8.22 -> 1.9.23] + - com.squareup.moshi:moshi [1.15.0 -> 1.15.1] + https://github.com/square/moshi/ - androidx.lifecycle:lifecycle-process [2.6.2 -> 2.7.0] https://developer.android.com/jetpack/androidx/releases/lifecycle#2.7.0 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10f6562..a0ccacd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,7 @@ + android:theme="@style/Theme.Pianoanlayticsandroid"> diff --git a/app/src/main/java/com/example/pianoanalytics/App.kt b/app/src/main/java/com/example/pianoanalytics/App.kt index cf14254..afa2083 100644 --- a/app/src/main/java/com/example/pianoanalytics/App.kt +++ b/app/src/main/java/com/example/pianoanalytics/App.kt @@ -4,6 +4,8 @@ import android.app.Application import io.piano.android.analytics.Configuration import io.piano.android.analytics.PianoAnalytics import io.piano.android.analytics.model.VisitorIDType +import io.piano.android.consents.PianoConsents +import io.piano.android.consents.models.ConsentConfiguration import timber.log.Timber class App: Application() { @@ -15,7 +17,11 @@ class App: Application() { site = 552987, visitorIDType = VisitorIDType.ADVERTISING_ID ).ignoreLimitedAdTracking(true).build() - PianoAnalytics.init(applicationContext, configuration).apply { + val pianoConsents = PianoConsents.init( + applicationContext, + ConsentConfiguration(requireConsent = true) + ) + PianoAnalytics.init(applicationContext, configuration, pianoConsents).apply { // just an example of callback eventProcessorCallback = PianoAnalytics.EventProcessorCallback { events -> events.forEach { event -> diff --git a/app/src/main/java/com/example/pianoanalytics/MainActivity.kt b/app/src/main/java/com/example/pianoanalytics/MainActivity.kt index 9b11e0b..28f278c 100644 --- a/app/src/main/java/com/example/pianoanalytics/MainActivity.kt +++ b/app/src/main/java/com/example/pianoanalytics/MainActivity.kt @@ -2,6 +2,8 @@ package com.example.pianoanalytics import android.content.Intent import android.os.Bundle +import android.view.Menu +import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import by.kirich1409.viewbindingdelegate.viewBinding @@ -10,9 +12,13 @@ import io.piano.android.analytics.PianoAnalytics import io.piano.android.analytics.model.Event import io.piano.android.analytics.model.Property import io.piano.android.analytics.model.PropertyName +import io.piano.android.consents.PianoConsents +import io.piano.android.consents.models.ConsentMode +import io.piano.android.consents.models.Purpose class MainActivity : AppCompatActivity(R.layout.activity_main) { private val binding: ActivityMainBinding by viewBinding(R.id.recyclerview) + private val pianoConsents by lazy { PianoConsents.getInstance() } private val animals = listOf( "___media___", @@ -43,6 +49,40 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) { ) } + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.main_menu, menu) + return true + } + + override fun onPrepareOptionsMenu(menu: Menu): Boolean { + val currentPaConsent = requireNotNull(pianoConsents.consents[Purpose.AUDIENCE_MEASUREMENT]).mode + val chosenItem = when (currentPaConsent) { + ConsentMode.OPT_IN -> R.id.consent_opt_in + ConsentMode.ESSENTIAL -> R.id.consent_essential + ConsentMode.OPT_OUT -> R.id.consent_opt_out + ConsentMode.CUSTOM -> R.id.consent_custom + ConsentMode.NOT_ACQUIRED -> null + } + if (chosenItem != null) { + menu.findItem(chosenItem).isChecked = true + } + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val newMode = when (item.itemId) { + R.id.consent_opt_in -> ConsentMode.OPT_IN + R.id.consent_essential -> ConsentMode.ESSENTIAL + R.id.consent_opt_out -> ConsentMode.OPT_OUT + R.id.consent_custom -> ConsentMode.CUSTOM + else -> null + } + return if (newMode != null) { + pianoConsents.set(Purpose.AUDIENCE_MEASUREMENT, newMode) + true + } else super.onOptionsItemSelected(item) + } + private fun onItemClick(item: String) { PianoAnalytics.getInstance().sendEvents( Event.Builder(Event.CLICK_NAVIGATION) diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml new file mode 100644 index 0000000..6174f54 --- /dev/null +++ b/app/src/main/res/menu/main_menu.xml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/build.gradle.kts b/build.gradle.kts index 7d66eac..9eec0af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.ktlint) apply false + alias(libs.plugins.binaryCompatibility) apply false alias(libs.plugins.mavenRelease) apply false alias(libs.plugins.moshiIR) apply false alias(libs.plugins.versionUpdater) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bc8b104..72d7883 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ # Plugins kotlin = "1.9.23" android = "8.3.2" +binaryCompatibility = "0.14.0" versionUpdater = "0.51.0" ktlint = "12.1.0" mavenRelease = "0.28.0" @@ -16,8 +17,9 @@ materialLibrary = "1.11.0" # Third party Libraries googleAdsId = "18.0.1" huaweiAdsId = "3.4.26.303" -okhttp = "4.12.0" moshi = "1.15.1" +okhttp = "4.12.0" +pianoConsents = "1.0.0" timber = "5.0.1" viewBindingProperty = "1.5.9" @@ -30,6 +32,7 @@ mockitoCore = "5.11.0" [plugins] android-library = { id = "com.android.library", version.ref = "android" } android-app = { id = "com.android.application", version.ref = "android" } +binaryCompatibility = {id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binaryCompatibility" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } @@ -43,10 +46,11 @@ lifecycleProcess = { module = "androidx.lifecycle:lifecycle-process", version.re material = { module = "com.google.android.material:material", version.ref = "materialLibrary" } googleAdsId = { module = "com.google.android.gms:play-services-ads-identifier", version.ref = "googleAdsId" } huaweiAdsId = { module = "com.huawei.hms:hms-ads-identifier", version.ref = "huaweiAdsId" } +moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttpLogging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" } +pianoConsents = { module = "io.piano.android:consents", version.ref = "pianoConsents" } timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } -moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" } viewBindingProperty = { module = "com.github.kirich1409:viewbindingpropertydelegate", version.ref = "viewBindingProperty" } kotlinJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } diff --git a/piano-analytics/api/piano-analytics.api b/piano-analytics/api/piano-analytics.api new file mode 100644 index 0000000..45d0a2e --- /dev/null +++ b/piano-analytics/api/piano-analytics.api @@ -0,0 +1,674 @@ +public final class io/piano/android/analytics/BuildConfig { + public static final field BUILD_TYPE Ljava/lang/String; + public static final field DEBUG Z + public static final field LIBRARY_PACKAGE_NAME Ljava/lang/String; + public static final field SDK_VERSION Ljava/lang/String; + public fun ()V +} + +public final class io/piano/android/analytics/Configuration : io/piano/android/analytics/ReportUrlProvider { + public static final field Companion Lio/piano/android/analytics/Configuration$Companion; + public static final field DEFAULT_EVENTS_OFFLINE_STORAGE_LIFETIME I + public static final field DEFAULT_PATH Ljava/lang/String; + public static final field DEFAULT_PRIVACY_STORAGE_LIFETIME I + public static final field DEFAULT_SESSION_BACKGROUND_DURATION I + public static final field DEFAULT_USER_STORAGE_LIFETIME I + public static final field DEFAULT_VISITOR_STORAGE_LIFETIME I + public static final field MIN_SESSION_BACKGROUND_DURATION I + public synthetic fun (Lio/piano/android/analytics/ReportUrlProvider;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIIIZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun getCollectDomain ()Ljava/lang/String; + public final fun getDefaultPrivacyMode ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getDetectCrashes ()Z + public final fun getEventsOfflineStorageLifetime ()I + public final fun getIgnoreLimitedAdTracking ()Z + public final fun getOfflineStorageMode ()Lio/piano/android/analytics/model/OfflineStorageMode; + public fun getPath ()Ljava/lang/String; + public final fun getPrivacyStorageLifetime ()I + public final fun getReportUrlProvider ()Lio/piano/android/analytics/ReportUrlProvider; + public final fun getSendEventWhenOptOut ()Z + public final fun getSessionBackgroundDuration ()I + public fun getSite ()I + public final fun getUserStorageLifetime ()I + public final fun getVisitorIDType ()Lio/piano/android/analytics/model/VisitorIDType; + public final fun getVisitorStorageLifetime ()I + public final fun getVisitorStorageMode ()Lio/piano/android/analytics/model/VisitorStorageMode; +} + +public final class io/piano/android/analytics/Configuration$Builder { + public fun ()V + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;I)V + public fun (Ljava/lang/String;ILjava/lang/String;)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;I)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;II)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;III)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIII)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIII)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIIIZ)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIIIZZ)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIIIZZZ)V + public fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIIIZZZLio/piano/android/analytics/ReportUrlProvider;)V + public synthetic fun (Ljava/lang/String;ILjava/lang/String;Lio/piano/android/analytics/model/PrivacyMode;Lio/piano/android/analytics/model/VisitorIDType;Lio/piano/android/analytics/model/OfflineStorageMode;Lio/piano/android/analytics/model/VisitorStorageMode;IIIIIZZZLio/piano/android/analytics/ReportUrlProvider;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lio/piano/android/analytics/Configuration; + public final fun collectDomain (Ljava/lang/String;)Lio/piano/android/analytics/Configuration$Builder; + public final fun defaultPrivacyMode (Lio/piano/android/analytics/model/PrivacyMode;)Lio/piano/android/analytics/Configuration$Builder; + public final fun detectCrashes (Z)Lio/piano/android/analytics/Configuration$Builder; + public final fun eventsOfflineStorageLifetime (I)Lio/piano/android/analytics/Configuration$Builder; + public final fun getCollectDomain ()Ljava/lang/String; + public final fun getDefaultPrivacyMode ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getDetectCrashes ()Z + public final fun getEventsOfflineStorageLifetime ()I + public final fun getIgnoreLimitedAdTracking ()Z + public final fun getOfflineStorageMode ()Lio/piano/android/analytics/model/OfflineStorageMode; + public final fun getPath ()Ljava/lang/String; + public final fun getPrivacyStorageLifetime ()I + public final fun getReportUrlProvider ()Lio/piano/android/analytics/ReportUrlProvider; + public final fun getSendEventWhenOptOut ()Z + public final fun getSessionBackgroundDuration ()I + public final fun getSite ()I + public final fun getUserStorageLifetime ()I + public final fun getVisitorIDType ()Lio/piano/android/analytics/model/VisitorIDType; + public final fun getVisitorStorageLifetime ()I + public final fun getVisitorStorageMode ()Lio/piano/android/analytics/model/VisitorStorageMode; + public final fun ignoreLimitedAdTracking (Z)Lio/piano/android/analytics/Configuration$Builder; + public final fun offlineStorageMode (Lio/piano/android/analytics/model/OfflineStorageMode;)Lio/piano/android/analytics/Configuration$Builder; + public final fun path (Ljava/lang/String;)Lio/piano/android/analytics/Configuration$Builder; + public final fun privacyStorageLifetime (I)Lio/piano/android/analytics/Configuration$Builder; + public final fun reportUrlProvider (Lio/piano/android/analytics/ReportUrlProvider;)Lio/piano/android/analytics/Configuration$Builder; + public final fun sendEventWhenOptOut (Z)Lio/piano/android/analytics/Configuration$Builder; + public final fun sessionBackgroundDuration (I)Lio/piano/android/analytics/Configuration$Builder; + public final fun setCollectDomain (Ljava/lang/String;)V + public final fun setDefaultPrivacyMode (Lio/piano/android/analytics/model/PrivacyMode;)V + public final fun setDetectCrashes (Z)V + public final fun setEventsOfflineStorageLifetime (I)V + public final fun setIgnoreLimitedAdTracking (Z)V + public final fun setOfflineStorageMode (Lio/piano/android/analytics/model/OfflineStorageMode;)V + public final fun setPath (Ljava/lang/String;)V + public final fun setPrivacyStorageLifetime (I)V + public final fun setReportUrlProvider (Lio/piano/android/analytics/ReportUrlProvider;)V + public final fun setSendEventWhenOptOut (Z)V + public final fun setSessionBackgroundDuration (I)V + public final fun setSite (I)V + public final fun setUserStorageLifetime (I)V + public final fun setVisitorIDType (Lio/piano/android/analytics/model/VisitorIDType;)V + public final fun setVisitorStorageLifetime (I)V + public final fun setVisitorStorageMode (Lio/piano/android/analytics/model/VisitorStorageMode;)V + public final fun site (I)Lio/piano/android/analytics/Configuration$Builder; + public final fun userStorageLifetime (I)Lio/piano/android/analytics/Configuration$Builder; + public final fun visitorIDType (Lio/piano/android/analytics/model/VisitorIDType;)Lio/piano/android/analytics/Configuration$Builder; + public final fun visitorStorageLifetime (I)Lio/piano/android/analytics/Configuration$Builder; + public final fun visitorStorageMode (Lio/piano/android/analytics/model/VisitorStorageMode;)Lio/piano/android/analytics/Configuration$Builder; +} + +public final class io/piano/android/analytics/Configuration$Companion { +} + +public final class io/piano/android/analytics/ContextPropertiesStorage { + public fun ()V + public final fun add (Lio/piano/android/analytics/model/ContextProperty;)V + public final fun clear ()V + public final fun deleteByKey-z4gBv5U (Ljava/lang/String;)V +} + +public abstract interface class io/piano/android/analytics/DataEncoder { + public abstract fun decode (Ljava/lang/String;)Ljava/lang/String; + public abstract fun encode (Ljava/lang/String;)Ljava/lang/String; +} + +public final class io/piano/android/analytics/MediaHelper { + public final fun adClick ([Lio/piano/android/analytics/model/Property;)V + public final fun adSkip ([Lio/piano/android/analytics/model/Property;)V + public final fun bufferHeartbeat ([Lio/piano/android/analytics/model/Property;)V + public final fun bufferStart (I[Lio/piano/android/analytics/model/Property;)V + public final fun close ([Lio/piano/android/analytics/model/Property;)V + public final fun display ([Lio/piano/android/analytics/model/Property;)V + public final fun error (Ljava/lang/String;[Lio/piano/android/analytics/model/Property;)V + public final fun fullscreenOff ([Lio/piano/android/analytics/model/Property;)V + public final fun fullscreenOn ([Lio/piano/android/analytics/model/Property;)V + public final fun getPlaybackSpeed ()D + public final fun getSessionId ()Ljava/lang/String; + public final fun heartbeat (I[Lio/piano/android/analytics/model/Property;)V + public final fun play (I[Lio/piano/android/analytics/model/Property;)V + public final fun playbackPaused (I[Lio/piano/android/analytics/model/Property;)V + public final fun playbackResumed (I[Lio/piano/android/analytics/model/Property;)V + public final fun playbackStart (I[Lio/piano/android/analytics/model/Property;)V + public final fun playbackStopped (I[Lio/piano/android/analytics/model/Property;)V + public final fun quality ([Lio/piano/android/analytics/model/Property;)V + public final fun rebufferHeartbeat ([Lio/piano/android/analytics/model/Property;)V + public final fun seek (II[Lio/piano/android/analytics/model/Property;)V + public final fun seekBackward (II[Lio/piano/android/analytics/model/Property;)V + public final fun seekForward (II[Lio/piano/android/analytics/model/Property;)V + public final fun seekStart (I[Lio/piano/android/analytics/model/Property;)V + public final fun setBufferHeartbeat (Landroid/util/SparseLongArray;)Lio/piano/android/analytics/MediaHelper; + public final fun setExtraProps ([Lio/piano/android/analytics/model/Property;)Lio/piano/android/analytics/MediaHelper; + public final fun setHeartbeat (Landroid/util/SparseLongArray;)Lio/piano/android/analytics/MediaHelper; + public final fun setPlaybackSpeed (D)V + public final fun share ([Lio/piano/android/analytics/model/Property;)V + public final fun speed ([Lio/piano/android/analytics/model/Property;)V + public final fun subtitleOff ([Lio/piano/android/analytics/model/Property;)V + public final fun subtitleOn ([Lio/piano/android/analytics/model/Property;)V + public final fun track (Ljava/lang/String;[Lio/piano/android/analytics/model/Property;)V + public final fun volume ([Lio/piano/android/analytics/model/Property;)V +} + +public final class io/piano/android/analytics/PianoAnalytics { + public static final field Companion Lio/piano/android/analytics/PianoAnalytics$Companion; + public final fun deleteOfflineStorage (I)V + public static synthetic fun deleteOfflineStorage$default (Lio/piano/android/analytics/PianoAnalytics;IILjava/lang/Object;)V + public final fun getContextPropertiesStorage ()Lio/piano/android/analytics/ContextPropertiesStorage; + public final fun getCustomEventProcessors ()Ljava/util/List; + public final fun getCustomVisitorId ()Ljava/lang/String; + public final fun getEventProcessorCallback ()Lio/piano/android/analytics/PianoAnalytics$EventProcessorCallback; + public static final fun getInstance ()Lio/piano/android/analytics/PianoAnalytics; + public final fun getPianoConsents ()Lio/piano/android/consents/PianoConsents; + public final fun getPrivacyModesStorage ()Lio/piano/android/analytics/PrivacyModesStorage; + public final fun getUserStorage ()Lio/piano/android/analytics/UserStorage; + public final fun getVisitorId ()Ljava/lang/String; + public static final fun init (Landroid/content/Context;Lio/piano/android/analytics/Configuration;)Lio/piano/android/analytics/PianoAnalytics; + public static final fun init (Landroid/content/Context;Lio/piano/android/analytics/Configuration;Lio/piano/android/consents/PianoConsents;)Lio/piano/android/analytics/PianoAnalytics; + public static final fun init (Landroid/content/Context;Lio/piano/android/analytics/Configuration;Lio/piano/android/consents/PianoConsents;Lio/piano/android/analytics/DataEncoder;)Lio/piano/android/analytics/PianoAnalytics; + public final fun mediaHelper (Ljava/lang/String;)Lio/piano/android/analytics/MediaHelper; + public final fun mediaHelper (Ljava/lang/String;Ljava/lang/String;)Lio/piano/android/analytics/MediaHelper; + public static synthetic fun mediaHelper$default (Lio/piano/android/analytics/PianoAnalytics;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/piano/android/analytics/MediaHelper; + public final fun screenName (Ljava/lang/String;)V + public final fun sendEvents ([Lio/piano/android/analytics/model/Event;)V + public final fun sendOfflineData ()V + public final fun setCustomVisitorId (Ljava/lang/String;)V + public final fun setEventProcessorCallback (Lio/piano/android/analytics/PianoAnalytics$EventProcessorCallback;)V +} + +public final class io/piano/android/analytics/PianoAnalytics$Companion { + public final fun getInstance ()Lio/piano/android/analytics/PianoAnalytics; + public final fun init (Landroid/content/Context;Lio/piano/android/analytics/Configuration;)Lio/piano/android/analytics/PianoAnalytics; + public final fun init (Landroid/content/Context;Lio/piano/android/analytics/Configuration;Lio/piano/android/consents/PianoConsents;)Lio/piano/android/analytics/PianoAnalytics; + public final fun init (Landroid/content/Context;Lio/piano/android/analytics/Configuration;Lio/piano/android/consents/PianoConsents;Lio/piano/android/analytics/DataEncoder;)Lio/piano/android/analytics/PianoAnalytics; + public static synthetic fun init$default (Lio/piano/android/analytics/PianoAnalytics$Companion;Landroid/content/Context;Lio/piano/android/analytics/Configuration;Lio/piano/android/consents/PianoConsents;Lio/piano/android/analytics/DataEncoder;ILjava/lang/Object;)Lio/piano/android/analytics/PianoAnalytics; +} + +public abstract interface class io/piano/android/analytics/PianoAnalytics$EventProcessorCallback { + public abstract fun onProcess (Ljava/util/List;)V +} + +public final class io/piano/android/analytics/PlainDataEncoder : io/piano/android/analytics/DataEncoder { + public static final field INSTANCE Lio/piano/android/analytics/PlainDataEncoder; + public fun decode (Ljava/lang/String;)Ljava/lang/String; + public fun encode (Ljava/lang/String;)Ljava/lang/String; +} + +public final class io/piano/android/analytics/PrivacyModesStorage { + public final fun getAllModes ()Ljava/util/Set; + public final fun getCurrentMode ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun setCurrentMode (Lio/piano/android/analytics/model/PrivacyMode;)V +} + +public abstract interface class io/piano/android/analytics/ReportUrlProvider { + public abstract fun getCollectDomain ()Ljava/lang/String; + public abstract fun getPath ()Ljava/lang/String; + public abstract fun getSite ()I +} + +public final class io/piano/android/analytics/ReportUrlProvider$DefaultImpls { + public static fun getPath (Lio/piano/android/analytics/ReportUrlProvider;)Ljava/lang/String; +} + +public final class io/piano/android/analytics/StaticReportUrlProvider : io/piano/android/analytics/ReportUrlProvider { + public fun (Ljava/lang/String;ILjava/lang/String;)V + public synthetic fun (Ljava/lang/String;ILjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun getCollectDomain ()Ljava/lang/String; + public fun getPath ()Ljava/lang/String; + public fun getSite ()I +} + +public final class io/piano/android/analytics/UserStorage { + public final fun getCurrentUser ()Lio/piano/android/analytics/model/User; + public final fun getUserRecognized ()Z + public final fun setCurrentUser (Lio/piano/android/analytics/model/User;)V +} + +public abstract interface class io/piano/android/analytics/eventprocessors/EventProcessor { + public abstract fun process (Ljava/util/List;)Ljava/util/List; +} + +public final class io/piano/android/analytics/model/ContextProperty { + public fun (Ljava/util/Set;)V + public fun (Ljava/util/Set;Z)V + public fun (Ljava/util/Set;ZLjava/util/Collection;)V + public synthetic fun (Ljava/util/Set;ZLjava/util/Collection;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/Set; + public final fun component2 ()Z + public final fun component3 ()Ljava/util/Collection; + public final fun copy (Ljava/util/Set;ZLjava/util/Collection;)Lio/piano/android/analytics/model/ContextProperty; + public static synthetic fun copy$default (Lio/piano/android/analytics/model/ContextProperty;Ljava/util/Set;ZLjava/util/Collection;ILjava/lang/Object;)Lio/piano/android/analytics/model/ContextProperty; + public fun equals (Ljava/lang/Object;)Z + public final fun getEventNames ()Ljava/util/Collection; + public final fun getPersistent ()Z + public final fun getProperties ()Ljava/util/Set; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/Event { + public static final field ANY Ljava/lang/String; + public static final field CLICK_ACTION Ljava/lang/String; + public static final field CLICK_DOWNLOAD Ljava/lang/String; + public static final field CLICK_EXIT Ljava/lang/String; + public static final field CLICK_NAVIGATION Ljava/lang/String; + public static final field Companion Lio/piano/android/analytics/model/Event$Companion; + public static final field INTERNAL_SEARCH_RESULT_CLICK Ljava/lang/String; + public static final field INTERNAL_SEARCH_RESULT_DISPLAY Ljava/lang/String; + public static final field MV_TEST_DISPLAY Ljava/lang/String; + public static final field PAGE_DISPLAY Ljava/lang/String; + public static final field PUBLISHER_CLICK Ljava/lang/String; + public static final field PUBLISHER_IMPRESSION Ljava/lang/String; + public static final field SELF_PROMOTION_CLICK Ljava/lang/String; + public static final field SELF_PROMOTION_IMPRESSION Ljava/lang/String; + public synthetic fun (Ljava/lang/String;Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getName ()Ljava/lang/String; + public final fun getProperties ()Ljava/util/Set; + public final fun newBuilder ()Lio/piano/android/analytics/model/Event$Builder; +} + +public final class io/piano/android/analytics/model/Event$Builder { + public fun (Ljava/lang/String;Ljava/util/Set;)V + public synthetic fun (Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lio/piano/android/analytics/model/Event; + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/Set; + public final fun copy (Ljava/lang/String;Ljava/util/Set;)Lio/piano/android/analytics/model/Event$Builder; + public static synthetic fun copy$default (Lio/piano/android/analytics/model/Event$Builder;Ljava/lang/String;Ljava/util/Set;ILjava/lang/Object;)Lio/piano/android/analytics/model/Event$Builder; + public fun equals (Ljava/lang/Object;)Z + public final fun getName ()Ljava/lang/String; + public final fun getProperties ()Ljava/util/Set; + public fun hashCode ()I + public final fun name (Ljava/lang/String;)Lio/piano/android/analytics/model/Event$Builder; + public final fun properties (Ljava/util/Collection;)Lio/piano/android/analytics/model/Event$Builder; + public final fun properties ([Lio/piano/android/analytics/model/Property;)Lio/piano/android/analytics/model/Event$Builder; + public final fun setName (Ljava/lang/String;)V + public fun toString ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/Event$Companion { +} + +public final class io/piano/android/analytics/model/EventsRequestJsonAdapter : com/squareup/moshi/JsonAdapter { + public fun (Lcom/squareup/moshi/Moshi;)V + public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/lang/Object; + public fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V + public fun toString ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/OfflineStorageMode : java/lang/Enum { + public static final field ALWAYS Lio/piano/android/analytics/model/OfflineStorageMode; + public static final field REQUIRED Lio/piano/android/analytics/model/OfflineStorageMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lio/piano/android/analytics/model/OfflineStorageMode; + public static fun values ()[Lio/piano/android/analytics/model/OfflineStorageMode; +} + +public final class io/piano/android/analytics/model/PrivacyMode { + public static final field Companion Lio/piano/android/analytics/model/PrivacyMode$Companion; + public fun (Ljava/lang/String;ZLjava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Map;Ljava/util/Map;)V + public synthetic fun (Ljava/lang/String;ZLjava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Ljava/util/Map;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public final fun getAllowedEventNames ()Ljava/util/Set; + public final fun getAllowedPropertyKeys ()Ljava/util/Map; + public final fun getAllowedStorageFeatures ()Ljava/util/Set; + public static final fun getCUSTOM ()Lio/piano/android/analytics/model/PrivacyMode; + public static final fun getDEFAULT_EVENT_NAMES$piano_analytics_release ()Ljava/util/Set; + public static final fun getDEFAULT_STORAGE_FEATURES$piano_analytics_release ()Ljava/util/Set; + public static final fun getEXEMPT ()Lio/piano/android/analytics/model/PrivacyMode; + public static final fun getEXEMPT_DEFAULT_PROPERTY_KEYS$piano_analytics_release ()Ljava/util/Set; + public final fun getForbiddenEventNames ()Ljava/util/Set; + public final fun getForbiddenPropertyKeys ()Ljava/util/Map; + public final fun getForbiddenStorageFeatures ()Ljava/util/Set; + public static final fun getMINIMUM_DEFAULT_PROPERTY_KEYS$piano_analytics_release ()Ljava/util/Set; + public static final fun getNO_CONSENT ()Lio/piano/android/analytics/model/PrivacyMode; + public static final fun getNO_STORAGE ()Lio/piano/android/analytics/model/PrivacyMode; + public static final fun getOPTIN ()Lio/piano/android/analytics/model/PrivacyMode; + public static final fun getOPTOUT ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getVisitorConsent ()Z + public final fun getVisitorMode ()Ljava/lang/String; + public fun hashCode ()I + public static final fun toPrivacyMode$piano_analytics_release (Lio/piano/android/consents/models/ConsentMode;)Lio/piano/android/analytics/model/PrivacyMode; + public fun toString ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/PrivacyMode$Companion { + public final fun getCUSTOM ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getEXEMPT ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getNO_CONSENT ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getNO_STORAGE ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getOPTIN ()Lio/piano/android/analytics/model/PrivacyMode; + public final fun getOPTOUT ()Lio/piano/android/analytics/model/PrivacyMode; +} + +public final class io/piano/android/analytics/model/PrivacyStorageFeature : java/lang/Enum { + public static final field ALL Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static final field CRASH Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static final field LIFECYCLE Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static final field PRIVACY Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static final field USER Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static final field VISITOR Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lio/piano/android/analytics/model/PrivacyStorageFeature; + public static fun values ()[Lio/piano/android/analytics/model/PrivacyStorageFeature; +} + +public final class io/piano/android/analytics/model/Property { + public synthetic fun (Ljava/lang/String;DLio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;DLio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;ILio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;ILio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;JLio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;JLio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/util/Date;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;ZLio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;ZLio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;[Ljava/lang/Double;Lio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;[Ljava/lang/Double;Lio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;[Ljava/lang/Integer;Lio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;[Ljava/lang/Integer;Lio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;[Ljava/lang/String;Lio/piano/android/analytics/model/Property$Type;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;[Ljava/lang/String;Lio/piano/android/analytics/model/Property$Type;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public final fun getForceType ()Lio/piano/android/analytics/model/Property$Type; + public final fun getName-t5hdzdk ()Ljava/lang/String; + public final fun getValue ()Ljava/lang/Object; + public fun hashCode ()I +} + +public final class io/piano/android/analytics/model/Property$Type : java/lang/Enum { + public static final field BOOLEAN Lio/piano/android/analytics/model/Property$Type; + public static final field DATE Lio/piano/android/analytics/model/Property$Type; + public static final field FLOAT Lio/piano/android/analytics/model/Property$Type; + public static final field FLOAT_ARRAY Lio/piano/android/analytics/model/Property$Type; + public static final field INTEGER Lio/piano/android/analytics/model/Property$Type; + public static final field INTEGER_ARRAY Lio/piano/android/analytics/model/Property$Type; + public static final field STRING Lio/piano/android/analytics/model/Property$Type; + public static final field STRING_ARRAY Lio/piano/android/analytics/model/Property$Type; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public final fun getPrefix ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Lio/piano/android/analytics/model/Property$Type; + public static fun values ()[Lio/piano/android/analytics/model/Property$Type; +} + +public final class io/piano/android/analytics/model/PropertyName { + public static final field Companion Lio/piano/android/analytics/model/PropertyName$Companion; + public static final synthetic fun box-impl (Ljava/lang/String;)Lio/piano/android/analytics/model/PropertyName; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public static final fun getANY_PROPERTY-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_CRASH-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_CRASH_CLASS-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_CRASH_SCREEN-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_DAYS_SINCE_FIRST_SESSION-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_DAYS_SINCE_LAST_SESSION-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_DAYS_SINCE_UPDATE-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_FIRST_SESSION-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_FIRST_SESSION_AFTER_UPDATE-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_FIRST_SESSION_DATE-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_FIRST_SESSION_DATE_AFTER_UPDATE-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_ID-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_SESSION_COUNT-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_SESSION_COUNT_SINCE_UPDATE-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_SESSION_ID-t5hdzdk ()Ljava/lang/String; + public static final fun getAPP_VERSION-t5hdzdk ()Ljava/lang/String; + public static final fun getBROWSER-t5hdzdk ()Ljava/lang/String; + public static final fun getBROWSER_COOKIE_ACCEPTANCE-t5hdzdk ()Ljava/lang/String; + public static final fun getBROWSER_GROUP-t5hdzdk ()Ljava/lang/String; + public static final fun getBROWSER_LANGUAGE-t5hdzdk ()Ljava/lang/String; + public static final fun getBROWSER_LANGUAGE_LOCAL-t5hdzdk ()Ljava/lang/String; + public static final fun getBROWSER_VERSION-t5hdzdk ()Ljava/lang/String; + public static final fun getCLICK-t5hdzdk ()Ljava/lang/String; + public static final fun getCLICK_CHAPTER1-t5hdzdk ()Ljava/lang/String; + public static final fun getCLICK_CHAPTER2-t5hdzdk ()Ljava/lang/String; + public static final fun getCLICK_CHAPTER3-t5hdzdk ()Ljava/lang/String; + public static final fun getCLICK_FULL_NAME-t5hdzdk ()Ljava/lang/String; + public static final fun getCONNECTION_MONITOR-t5hdzdk ()Ljava/lang/String; + public static final fun getCONNECTION_ORGANISATION-t5hdzdk ()Ljava/lang/String; + public static final fun getCONNECTION_TYPE-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_DAY-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_DAYNUMBER-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_MONTH-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_MONTHNUMBER-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_WEEK-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_YEAR-t5hdzdk ()Ljava/lang/String; + public static final fun getDATE_YEAROFWEEK-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_BRAND-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_DISPLAY_HEIGHT-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_DISPLAY_WIDTH-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_MANUFACTURER-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_MODEL-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_NAME-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_NAME_TECH-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_SCREEN_DIAGONAL-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_SCREEN_HEIGHT-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_SCREEN_WIDTH-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_TIMESTAMP_UTC-t5hdzdk ()Ljava/lang/String; + public static final fun getDEVICE_TYPE-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_COLLECTION_PLATFORM-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_COLLECTION_VERSION-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_HOUR-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_ID-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_MINUTE-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_NAME-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_POSITION-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_SECOND-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_TIME-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_TIME_UTC-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_URL-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_URL_DOMAIN-t5hdzdk ()Ljava/lang/String; + public static final fun getEVENT_URL_FULL-t5hdzdk ()Ljava/lang/String; + public static final fun getEXCLUSION_CAUSE-t5hdzdk ()Ljava/lang/String; + public static final fun getEXCLUSION_TYPE-t5hdzdk ()Ljava/lang/String; + public static final fun getGEO_CITY-t5hdzdk ()Ljava/lang/String; + public static final fun getGEO_CONTINENT-t5hdzdk ()Ljava/lang/String; + public static final fun getGEO_COUNTRY-t5hdzdk ()Ljava/lang/String; + public static final fun getGEO_METRO-t5hdzdk ()Ljava/lang/String; + public static final fun getGEO_REGION-t5hdzdk ()Ljava/lang/String; + public static final fun getHIT_TIME_UTC-t5hdzdk ()Ljava/lang/String; + public final fun getKey ()Ljava/lang/String; + public static final fun getOS-t5hdzdk ()Ljava/lang/String; + public static final fun getOS_GROUP-t5hdzdk ()Ljava/lang/String; + public static final fun getOS_VERSION-t5hdzdk ()Ljava/lang/String; + public static final fun getOS_VERSION_NAME-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE_CHAPTER1-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE_CHAPTER2-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE_CHAPTER3-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE_DURATION-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE_FULL_NAME-t5hdzdk ()Ljava/lang/String; + public static final fun getPAGE_POSITION-t5hdzdk ()Ljava/lang/String; + public static final fun getPRIVACY_STATUS-t5hdzdk ()Ljava/lang/String; + public static final fun getSITE-t5hdzdk ()Ljava/lang/String; + public static final fun getSITE_ENV-t5hdzdk ()Ljava/lang/String; + public static final fun getSITE_ID-t5hdzdk ()Ljava/lang/String; + public static final fun getSITE_PLATFORM-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_DETAIL-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_DIRECT_ACCESS-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_ORGANIC-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_ORGANIC_DETAIL-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_PORTAL_DOMAIN-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_PORTAL_SITE-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_PORTAL_SITE_ID-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_PORTAL_URL-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_REFERRER_SITE_DOMAIN-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_REFERRER_SITE_URL-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_REFERRER_URL-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_SE-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_SE_CATEGORY-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_SE_COUNTRY-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_TYPE-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_URL-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_URL_DOMAIN-t5hdzdk ()Ljava/lang/String; + public static final fun getSRC_WEBMAIL-t5hdzdk ()Ljava/lang/String; + public static final fun getUSER_CATEGORY-t5hdzdk ()Ljava/lang/String; + public static final fun getUSER_ID-t5hdzdk ()Ljava/lang/String; + public static final fun getUSER_RECOGNITION-t5hdzdk ()Ljava/lang/String; + public static final fun getVISITOR_PRIVACY_CONSENT-t5hdzdk ()Ljava/lang/String; + public static final fun getVISITOR_PRIVACY_MODE-t5hdzdk ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/PropertyName$Companion { + public final fun getANY_PROPERTY-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_CRASH-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_CRASH_CLASS-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_CRASH_SCREEN-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_DAYS_SINCE_FIRST_SESSION-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_DAYS_SINCE_LAST_SESSION-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_DAYS_SINCE_UPDATE-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_FIRST_SESSION-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_FIRST_SESSION_AFTER_UPDATE-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_FIRST_SESSION_DATE-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_FIRST_SESSION_DATE_AFTER_UPDATE-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_ID-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_SESSION_COUNT-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_SESSION_COUNT_SINCE_UPDATE-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_SESSION_ID-t5hdzdk ()Ljava/lang/String; + public final fun getAPP_VERSION-t5hdzdk ()Ljava/lang/String; + public final fun getBROWSER-t5hdzdk ()Ljava/lang/String; + public final fun getBROWSER_COOKIE_ACCEPTANCE-t5hdzdk ()Ljava/lang/String; + public final fun getBROWSER_GROUP-t5hdzdk ()Ljava/lang/String; + public final fun getBROWSER_LANGUAGE-t5hdzdk ()Ljava/lang/String; + public final fun getBROWSER_LANGUAGE_LOCAL-t5hdzdk ()Ljava/lang/String; + public final fun getBROWSER_VERSION-t5hdzdk ()Ljava/lang/String; + public final fun getCLICK-t5hdzdk ()Ljava/lang/String; + public final fun getCLICK_CHAPTER1-t5hdzdk ()Ljava/lang/String; + public final fun getCLICK_CHAPTER2-t5hdzdk ()Ljava/lang/String; + public final fun getCLICK_CHAPTER3-t5hdzdk ()Ljava/lang/String; + public final fun getCLICK_FULL_NAME-t5hdzdk ()Ljava/lang/String; + public final fun getCONNECTION_MONITOR-t5hdzdk ()Ljava/lang/String; + public final fun getCONNECTION_ORGANISATION-t5hdzdk ()Ljava/lang/String; + public final fun getCONNECTION_TYPE-t5hdzdk ()Ljava/lang/String; + public final fun getDATE-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_DAY-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_DAYNUMBER-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_MONTH-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_MONTHNUMBER-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_WEEK-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_YEAR-t5hdzdk ()Ljava/lang/String; + public final fun getDATE_YEAROFWEEK-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_BRAND-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_DISPLAY_HEIGHT-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_DISPLAY_WIDTH-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_MANUFACTURER-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_MODEL-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_NAME-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_NAME_TECH-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_SCREEN_DIAGONAL-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_SCREEN_HEIGHT-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_SCREEN_WIDTH-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_TIMESTAMP_UTC-t5hdzdk ()Ljava/lang/String; + public final fun getDEVICE_TYPE-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_COLLECTION_PLATFORM-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_COLLECTION_VERSION-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_HOUR-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_ID-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_MINUTE-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_NAME-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_POSITION-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_SECOND-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_TIME-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_TIME_UTC-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_URL-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_URL_DOMAIN-t5hdzdk ()Ljava/lang/String; + public final fun getEVENT_URL_FULL-t5hdzdk ()Ljava/lang/String; + public final fun getEXCLUSION_CAUSE-t5hdzdk ()Ljava/lang/String; + public final fun getEXCLUSION_TYPE-t5hdzdk ()Ljava/lang/String; + public final fun getGEO_CITY-t5hdzdk ()Ljava/lang/String; + public final fun getGEO_CONTINENT-t5hdzdk ()Ljava/lang/String; + public final fun getGEO_COUNTRY-t5hdzdk ()Ljava/lang/String; + public final fun getGEO_METRO-t5hdzdk ()Ljava/lang/String; + public final fun getGEO_REGION-t5hdzdk ()Ljava/lang/String; + public final fun getHIT_TIME_UTC-t5hdzdk ()Ljava/lang/String; + public final fun getOS-t5hdzdk ()Ljava/lang/String; + public final fun getOS_GROUP-t5hdzdk ()Ljava/lang/String; + public final fun getOS_VERSION-t5hdzdk ()Ljava/lang/String; + public final fun getOS_VERSION_NAME-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE_CHAPTER1-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE_CHAPTER2-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE_CHAPTER3-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE_DURATION-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE_FULL_NAME-t5hdzdk ()Ljava/lang/String; + public final fun getPAGE_POSITION-t5hdzdk ()Ljava/lang/String; + public final fun getPRIVACY_STATUS-t5hdzdk ()Ljava/lang/String; + public final fun getSITE-t5hdzdk ()Ljava/lang/String; + public final fun getSITE_ENV-t5hdzdk ()Ljava/lang/String; + public final fun getSITE_ID-t5hdzdk ()Ljava/lang/String; + public final fun getSITE_PLATFORM-t5hdzdk ()Ljava/lang/String; + public final fun getSRC-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_DETAIL-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_DIRECT_ACCESS-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_ORGANIC-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_ORGANIC_DETAIL-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_PORTAL_DOMAIN-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_PORTAL_SITE-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_PORTAL_SITE_ID-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_PORTAL_URL-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_REFERRER_SITE_DOMAIN-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_REFERRER_SITE_URL-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_REFERRER_URL-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_SE-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_SE_CATEGORY-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_SE_COUNTRY-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_TYPE-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_URL-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_URL_DOMAIN-t5hdzdk ()Ljava/lang/String; + public final fun getSRC_WEBMAIL-t5hdzdk ()Ljava/lang/String; + public final fun getUSER_CATEGORY-t5hdzdk ()Ljava/lang/String; + public final fun getUSER_ID-t5hdzdk ()Ljava/lang/String; + public final fun getUSER_RECOGNITION-t5hdzdk ()Ljava/lang/String; + public final fun getVISITOR_PRIVACY_CONSENT-t5hdzdk ()Ljava/lang/String; + public final fun getVISITOR_PRIVACY_MODE-t5hdzdk ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/User { + public fun (Ljava/lang/String;Ljava/lang/String;Z)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getCategory ()Ljava/lang/String; + public final fun getId ()Ljava/lang/String; + public final fun getShouldBeStored ()Z +} + +public final class io/piano/android/analytics/model/UserJsonAdapter : com/squareup/moshi/JsonAdapter { + public fun (Lcom/squareup/moshi/Moshi;)V + public fun fromJson (Lcom/squareup/moshi/JsonReader;)Ljava/lang/Object; + public fun toJson (Lcom/squareup/moshi/JsonWriter;Ljava/lang/Object;)V + public fun toString ()Ljava/lang/String; +} + +public final class io/piano/android/analytics/model/VisitorIDType : java/lang/Enum { + public static final field ADVERTISING_ID Lio/piano/android/analytics/model/VisitorIDType; + public static final field CUSTOM Lio/piano/android/analytics/model/VisitorIDType; + public static final field GOOGLE_ADVERTISING_ID Lio/piano/android/analytics/model/VisitorIDType; + public static final field HUAWEI_OPEN_ADVERTISING_ID Lio/piano/android/analytics/model/VisitorIDType; + public static final field UUID Lio/piano/android/analytics/model/VisitorIDType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lio/piano/android/analytics/model/VisitorIDType; + public static fun values ()[Lio/piano/android/analytics/model/VisitorIDType; +} + +public final class io/piano/android/analytics/model/VisitorStorageMode : java/lang/Enum { + public static final field FIXED Lio/piano/android/analytics/model/VisitorStorageMode; + public static final field RELATIVE Lio/piano/android/analytics/model/VisitorStorageMode; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lio/piano/android/analytics/model/VisitorStorageMode; + public static fun values ()[Lio/piano/android/analytics/model/VisitorStorageMode; +} + diff --git a/piano-analytics/build.gradle.kts b/piano-analytics/build.gradle.kts index 9e4dfd5..f7eb250 100644 --- a/piano-analytics/build.gradle.kts +++ b/piano-analytics/build.gradle.kts @@ -3,6 +3,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.ksp) alias(libs.plugins.moshiIR) + alias(libs.plugins.binaryCompatibility) alias(libs.plugins.ktlint) alias(libs.plugins.mavenRelease) } @@ -58,6 +59,7 @@ ktlint { dependencies { compileOnly(libs.googleAdsId) compileOnly(libs.huaweiAdsId) + api(libs.pianoConsents) implementation(libs.lifecycleProcess) implementation(libs.timber) implementation(libs.okhttp) diff --git a/piano-analytics/gradle.properties b/piano-analytics/gradle.properties index 8d9ecff..b36dbb4 100644 --- a/piano-analytics/gradle.properties +++ b/piano-analytics/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=3.3.6-SNAPSHOT +VERSION_NAME=3.4.0-SNAPSHOT GROUP=io.piano.android POM_NAME=Analytics POM_ARTIFACT_ID=analytics diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt b/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt index f080036..e39e50c 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/Configuration.kt @@ -10,11 +10,13 @@ import io.piano.android.analytics.model.VisitorStorageMode */ public class Configuration private constructor( public val reportUrlProvider: ReportUrlProvider, + @Deprecated("Use `PianoConsents` for managing consents instead") public val defaultPrivacyMode: PrivacyMode, public val visitorIDType: VisitorIDType, public val offlineStorageMode: OfflineStorageMode, public val visitorStorageMode: VisitorStorageMode, public val eventsOfflineStorageLifetime: Int, + @Deprecated("Use `PianoConsents` for managing consents instead") public val privacyStorageLifetime: Int, public val visitorStorageLifetime: Int, public val userStorageLifetime: Int, @@ -27,11 +29,13 @@ public class Configuration private constructor( public var collectDomain: String = "", public var site: Int = 0, public var path: String = DEFAULT_PATH, + @Deprecated("Use `PianoConsents` for managing consents instead") public var defaultPrivacyMode: PrivacyMode = PrivacyMode.OPTIN, public var visitorIDType: VisitorIDType = VisitorIDType.UUID, public var offlineStorageMode: OfflineStorageMode = OfflineStorageMode.REQUIRED, public var visitorStorageMode: VisitorStorageMode = VisitorStorageMode.FIXED, public var eventsOfflineStorageLifetime: Int = DEFAULT_EVENTS_OFFLINE_STORAGE_LIFETIME, + @Deprecated("Use `PianoConsents` for managing consents instead") public var privacyStorageLifetime: Int = DEFAULT_PRIVACY_STORAGE_LIFETIME, public var visitorStorageLifetime: Int = DEFAULT_VISITOR_STORAGE_LIFETIME, public var userStorageLifetime: Int = DEFAULT_USER_STORAGE_LIFETIME, @@ -72,6 +76,7 @@ public class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. + @Deprecated("Use `PianoConsents` for managing consents instead") public fun defaultPrivacyMode(defaultPrivacyMode: PrivacyMode): Builder = apply { this.defaultPrivacyMode = defaultPrivacyMode } @@ -120,6 +125,7 @@ public class Configuration private constructor( * @return updated Builder instance */ @Suppress("unused") // Public API. + @Deprecated("Use `PianoConsents` for managing consents instead") public fun privacyStorageLifetime(privacyStorageLifetime: Int): Builder = apply { this.privacyStorageLifetime = privacyStorageLifetime } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/DependenciesProvider.kt b/piano-analytics/src/main/java/io/piano/android/analytics/DependenciesProvider.kt index ea676a3..74774bc 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/DependenciesProvider.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/DependenciesProvider.kt @@ -19,6 +19,7 @@ import io.piano.android.analytics.model.Event import io.piano.android.analytics.model.EventsRequest import io.piano.android.analytics.model.User import io.piano.android.analytics.model.VisitorIDType +import io.piano.android.consents.PianoConsents import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import java.util.concurrent.Executors @@ -29,12 +30,13 @@ import java.util.concurrent.TimeUnit internal class DependenciesProvider private constructor( context: Context, configuration: Configuration, + pianoConsents: PianoConsents? = null, dataEncoder: DataEncoder, ) { private val userAgent = "Piano Analytics SDK ${BuildConfig.SDK_VERSION}" private val executorProvider: () -> ScheduledExecutorService = { Executors.newSingleThreadScheduledExecutor() } private val prefsStorage = PrefsStorage(context) - private val privacyModesStorage = PrivacyModesStorage(configuration, prefsStorage) + private val privacyModesStorage = PrivacyModesStorage(configuration, prefsStorage, pianoConsents) private val screenNameProvider = ScreenNameProvider() private val contextPropertiesStorage = ContextPropertiesStorage() @@ -146,7 +148,8 @@ internal class DependenciesProvider private constructor( customEventProcessors, privacyModesStorage, contextPropertiesStorage, - userStorage + userStorage, + pianoConsents ) companion object { @@ -155,11 +158,21 @@ internal class DependenciesProvider private constructor( private var instance: DependenciesProvider? = null @JvmStatic - internal fun init(context: Context, configuration: Configuration, dataEncoder: DataEncoder) { + internal fun init( + context: Context, + configuration: Configuration, + pianoConsents: PianoConsents?, + dataEncoder: DataEncoder, + ) { if (instance == null) { synchronized(this) { if (instance == null) { - instance = DependenciesProvider(context.applicationContext, configuration, dataEncoder).also { + instance = DependenciesProvider( + context.applicationContext, + configuration, + pianoConsents, + dataEncoder + ).also { Thread.setDefaultUncaughtExceptionHandler(it.crashHandler) } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/EventPropertiesJsonAdapter.kt b/piano-analytics/src/main/java/io/piano/android/analytics/EventPropertiesJsonAdapter.kt index 3806c91..9ff7624 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/EventPropertiesJsonAdapter.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/EventPropertiesJsonAdapter.kt @@ -25,7 +25,7 @@ internal class EventPropertiesJsonAdapter( val key = entry.key.substring(delimiterIndex + 1) val type = if (delimiterIndex != -1) { val prefix = entry.key.substring(0, delimiterIndex) - Property.Type.values().firstOrNull { it.prefix == prefix } + Property.Type.entries.firstOrNull { it.prefix == prefix } } else { null } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt index 367f12c..e86b254 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt @@ -10,6 +10,7 @@ import io.piano.android.analytics.model.Event import io.piano.android.analytics.model.OfflineStorageMode import io.piano.android.analytics.model.Property import io.piano.android.analytics.model.PropertyName +import io.piano.android.consents.PianoConsents import java.util.UUID import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.TimeUnit @@ -20,6 +21,7 @@ import java.util.concurrent.TimeUnit * @property privacyModesStorage Storage for privacy modes * @property contextPropertiesStorage Storage for context properties * @property userStorage Storage for user data + * @property pianoConsents [PianoConsents] instance for managing user consent. */ public class PianoAnalytics internal constructor( private val executorProvider: () -> ScheduledExecutorService, @@ -33,6 +35,7 @@ public class PianoAnalytics internal constructor( customEventProcessorsGroup: GroupEventProcessor, // Public API. @Suppress("unused", "MemberVisibilityCanBePrivate") + @Deprecated("Use `pianoConsents` for managing consents instead") public val privacyModesStorage: PrivacyModesStorage, // Public API. @Suppress("unused", "MemberVisibilityCanBePrivate") @@ -40,6 +43,9 @@ public class PianoAnalytics internal constructor( // Public API. @Suppress("unused", "MemberVisibilityCanBePrivate") public val userStorage: UserStorage, + // Public API. + @Suppress("unused", "MemberVisibilityCanBePrivate") + public val pianoConsents: PianoConsents?, ) { private val executor: ScheduledExecutorService = executorProvider() @@ -165,6 +171,7 @@ public class PianoAnalytics internal constructor( * * @param context Activity or Application context * @param configuration [Configuration] object + * @param pianoConsents [PianoConsents] instance for managing user consent. Default is null. * @param dataEncoder custom [DataEncoder] for encrypting/decrypting events' data, default is [PlainDataEncoder] */ @Suppress("unused") // Public API. @@ -173,9 +180,10 @@ public class PianoAnalytics internal constructor( public fun init( context: Context, configuration: Configuration, + pianoConsents: PianoConsents? = null, dataEncoder: DataEncoder = PlainDataEncoder, ): PianoAnalytics { - DependenciesProvider.init(context, configuration, dataEncoder) + DependenciesProvider.init(context, configuration, pianoConsents, dataEncoder) return getInstance() } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt index 4715862..91a10aa 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt @@ -1,16 +1,24 @@ package io.piano.android.analytics import io.piano.android.analytics.model.PrivacyMode +import io.piano.android.analytics.model.PrivacyMode.Companion.NO_CONSENT +import io.piano.android.analytics.model.PrivacyMode.Companion.toPrivacyMode import io.piano.android.analytics.model.PrivacyStorageFeature +import io.piano.android.consents.PianoConsents +import io.piano.android.consents.models.Product +import timber.log.Timber import java.util.concurrent.TimeUnit /** * Stores information about privacy modes */ +@Deprecated("Use `PianoConsents` for managing consents instead") public class PrivacyModesStorage internal constructor( private val configuration: Configuration, private val prefsStorage: PrefsStorage, + private val pianoConsents: PianoConsents?, ) { + private val consentsEnabled = pianoConsents?.consentConfiguration?.requireConsent == true init { prefsStorage.privacyStorageFilter = ::isFeatureAllowed } @@ -31,7 +39,8 @@ public class PrivacyModesStorage internal constructor( PrivacyMode.NO_STORAGE, PrivacyMode.OPTIN, PrivacyMode.OPTOUT, - PrivacyMode.EXEMPT + PrivacyMode.EXEMPT, + PrivacyMode.CUSTOM ) /** @@ -40,6 +49,11 @@ public class PrivacyModesStorage internal constructor( @Suppress("unused", "MemberVisibilityCanBePrivate") // Public API. public var currentMode: PrivacyMode = configuration.defaultPrivacyMode get() { + if (consentsEnabled) { + return pianoConsents?.let { + it.consents[it.productsToPurposesMapping[Product.PA]]?.mode + }?.toPrivacyMode() ?: NO_CONSENT + } if (field != PrivacyMode.NO_CONSENT && field != PrivacyMode.NO_STORAGE) { if (prefsStorage.privacyExpirationTimestamp in 1..System.currentTimeMillis()) { currentMode = configuration.defaultPrivacyMode @@ -53,6 +67,9 @@ public class PrivacyModesStorage internal constructor( return field } set(value) { + if (consentsEnabled) { + Timber.w("Calling deprecated privacy mode setter while consents enabled") + } require(value in allModes) { "Privacy mode ${value.visitorMode} is not registered." } @@ -69,6 +86,9 @@ public class PrivacyModesStorage internal constructor( System.currentTimeMillis() + TimeUnit.DAYS.toMillis(configuration.privacyStorageLifetime.toLong()) internal fun updatePrefs(mode: PrivacyMode) { + if (consentsEnabled) { + return + } prefsStorage.apply { privacyMode = mode.visitorMode privacyExpirationTimestamp = getNewExpirationTimestamp() diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt index 397be53..e176072 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/PrivacyMode.kt @@ -1,5 +1,7 @@ package io.piano.android.analytics.model +import io.piano.android.consents.models.ConsentMode + /** * A privacy visitor mode * @@ -183,6 +185,12 @@ public class PrivacyMode( @JvmStatic public val EXEMPT: PrivacyMode = PrivacyMode(visitorMode = "exempt") + /** + * Custom privacy mode + */ + @JvmStatic + public val CUSTOM: PrivacyMode = PrivacyMode(visitorMode = "custom") + /** * No consent privacy mode */ @@ -206,5 +214,14 @@ public class PrivacyMode( forbiddenStorageFeatures = mutableSetOf(PrivacyStorageFeature.ALL), allowedPropertyKeys = mutableMapOf(Event.ANY to mutableSetOf(PropertyName.ANY_PROPERTY)) ) + + @JvmStatic + internal fun ConsentMode.toPrivacyMode(): PrivacyMode = when (this) { + ConsentMode.OPT_IN -> OPTIN + ConsentMode.ESSENTIAL -> EXEMPT + ConsentMode.OPT_OUT -> OPTOUT + ConsentMode.NOT_ACQUIRED -> NO_CONSENT + ConsentMode.CUSTOM -> CUSTOM + } } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt b/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt index 9972837..d62eb77 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/model/Property.kt @@ -18,7 +18,7 @@ public class Property { override fun hashCode(): Int = name.key.lowercase().hashCode() - internal constructor(name: PropertyName, value: Any, forceType: Type? = null) { + internal constructor(name: PropertyName, value: Any, forceType: Type?) { require(name != PropertyName.ANY_PROPERTY) this.name = name this.value = value diff --git a/settings.gradle.kts b/settings.gradle.kts index 1be30fd..1b59195 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,8 +16,15 @@ dependencyResolutionManagement { } plugins { - id("com.gradle.develocity") version "3.17" + id("com.gradle.develocity") version "3.17.1" } + +develocity { + buildScan { + publishing.onlyIf { false } + } +} + include( ":app", ":piano-analytics" From 4ad952239dbad7d6e55a53e167094087cb8a5b06 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Mon, 22 Apr 2024 11:18:02 +0400 Subject: [PATCH 5/8] Fix import --- .../java/io/piano/android/analytics/PrivacyModesStorage.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt index 91a10aa..fec2996 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PrivacyModesStorage.kt @@ -1,7 +1,6 @@ package io.piano.android.analytics import io.piano.android.analytics.model.PrivacyMode -import io.piano.android.analytics.model.PrivacyMode.Companion.NO_CONSENT import io.piano.android.analytics.model.PrivacyMode.Companion.toPrivacyMode import io.piano.android.analytics.model.PrivacyStorageFeature import io.piano.android.consents.PianoConsents @@ -52,7 +51,7 @@ public class PrivacyModesStorage internal constructor( if (consentsEnabled) { return pianoConsents?.let { it.consents[it.productsToPurposesMapping[Product.PA]]?.mode - }?.toPrivacyMode() ?: NO_CONSENT + }?.toPrivacyMode() ?: PrivacyMode.NO_CONSENT } if (field != PrivacyMode.NO_CONSENT && field != PrivacyMode.NO_STORAGE) { if (prefsStorage.privacyExpirationTimestamp in 1..System.currentTimeMillis()) { From 2e35a4b55c3afdcfa8029985ddee1ef5a9b824b1 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Mon, 22 Apr 2024 15:06:40 +0400 Subject: [PATCH 6/8] Use consents, if initialized, but not supplied --- .../main/java/io/piano/android/analytics/PianoAnalytics.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt b/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt index e86b254..bf109f2 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/PianoAnalytics.kt @@ -183,7 +183,12 @@ public class PianoAnalytics internal constructor( pianoConsents: PianoConsents? = null, dataEncoder: DataEncoder = PlainDataEncoder, ): PianoAnalytics { - DependenciesProvider.init(context, configuration, pianoConsents, dataEncoder) + DependenciesProvider.init( + context, + configuration, + pianoConsents ?: runCatching { PianoConsents.getInstance() }.getOrNull(), + dataEncoder + ) return getInstance() } From d2cb8747abd4546044cfd374bc9f56f17f0ed6c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 26 Apr 2024 17:33:21 +0400 Subject: [PATCH 7/8] Add switching to main thread, if we're on another thread --- .../io/piano/android/analytics/SessionStorage.kt | 3 ++- .../main/java/io/piano/android/analytics/Utils.kt | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/SessionStorage.kt b/piano-analytics/src/main/java/io/piano/android/analytics/SessionStorage.kt index 911e83a..92c2b39 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/SessionStorage.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/SessionStorage.kt @@ -92,6 +92,7 @@ internal class SessionStorage( internal inline fun getCurrentTimestamp() = System.currentTimeMillis() // for mocking in tests - internal fun addLifecycleObserver(observer: DefaultLifecycleObserver) = + internal fun addLifecycleObserver(observer: DefaultLifecycleObserver) = runOnMainThread { ProcessLifecycleOwner.get().lifecycle.addObserver(observer) + } } diff --git a/piano-analytics/src/main/java/io/piano/android/analytics/Utils.kt b/piano-analytics/src/main/java/io/piano/android/analytics/Utils.kt index e098773..9463ec2 100644 --- a/piano-analytics/src/main/java/io/piano/android/analytics/Utils.kt +++ b/piano-analytics/src/main/java/io/piano/android/analytics/Utils.kt @@ -1,6 +1,8 @@ package io.piano.android.analytics import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper import timber.log.Timber internal fun String.wildcardMatches(string: String): Boolean { @@ -21,3 +23,14 @@ private fun getProperty(key: String): String? = runCatching { }.getOrNull() private const val LOG_HTTP_KEY = "debug.piano.sdk" + +internal fun runOnMainThread(action: () -> Unit) { + val mainLooper = Looper.getMainLooper() + if (mainLooper.thread == Thread.currentThread()) { + action() + } else { + Handler(mainLooper).post { + action() + } + } +} From 565d4f31af68e156f7b340cde2d8621c3abc209a Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Thu, 2 May 2024 11:11:50 +0400 Subject: [PATCH 8/8] Prepare release --- CHANGELOG.md | 3 ++- piano-analytics/gradle.properties | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 464c651..4824ed6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Piano Analytics SDK for Android -## v3.4.0-SNAPSHOT +## v3.4.0 * Updated to Kotlin 1.9 * Added support for `PianoConsents` * Added `PrivacyMode.CUSTOM`, that will be used if set `ConsentMode.CUSTOM` * Deprecated `PrivacyModesStorage`, use `PianoConsents` instead +* Added switching to main thread when required * Removed requirement for `READ_PHONE_STATE` permission for Android 6-9 * Updated dependencies: - Kotlin [1.8.22 -> 1.9.23] diff --git a/piano-analytics/gradle.properties b/piano-analytics/gradle.properties index b36dbb4..a7642cf 100644 --- a/piano-analytics/gradle.properties +++ b/piano-analytics/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=3.4.0-SNAPSHOT +VERSION_NAME=3.4.0 GROUP=io.piano.android POM_NAME=Analytics POM_ARTIFACT_ID=analytics