Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,9 @@ class AmplitudePlugin: DestinationPlugin() {
### Advanced concepts
- [`setup(Analytics)`](https://github.com/segmentio/analytics-kotlin/blob/main/analytics-kotlin/src/main/java/com/segment/analytics/platform/Plugin.kt#L20-L24)
Use this function to setup your plugin. This will be implicitly called once the plugin is registered
- [`update(Settings)`](https://github.com/segmentio/analytics-kotlin/blob/main/analytics-kotlin/src/main/java/com/segment/analytics/platform/Plugin.kt#L31-L33)
Use this function to react to any settings updates. This will be implicitly called when settings are updated.
- [`update(Settings, UpdateType)`](https://github.com/segmentio/analytics-kotlin/blob/main/analytics-kotlin/src/main/java/com/segment/analytics/platform/Plugin.kt#L31-L33)
Use this function to react to any settings updates. This will be implicitly called when settings are updated. The `UpdateType` is used to indicate whether the settings change
is for initialization or refreshment, and you can use it to decide whether to update your plugins accordingly.
You can force a settings update by calling `analytics.checkSettings()`
- AndroidLifecycle hooks
Plugins can also hook into [`AndroidLifecycle`]() functions by implementing an interface. These functions will get called implicitly as the lifecycle events are processed.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.segment.analytics.kotlin.core

import com.segment.analytics.kotlin.core.platform.DestinationPlugin
import com.segment.analytics.kotlin.core.platform.Plugin
import com.segment.analytics.kotlin.core.platform.plugins.LogType
import com.segment.analytics.kotlin.core.platform.plugins.log
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -107,7 +108,7 @@ class SegmentDestination(
}
}

override fun update(settings: Settings) {
override fun update(settings: Settings, type: Plugin.UpdateType) {
settings.integrations[key]?.jsonObject?.let {
apiKey = it["apiKey"]?.jsonPrimitive?.content ?: apiKey
apiHost = it["apiHost"]?.jsonPrimitive?.content ?: apiHost
Expand Down
14 changes: 11 additions & 3 deletions core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.segment.analytics.kotlin.core

import com.segment.analytics.kotlin.core.platform.DestinationPlugin
import com.segment.analytics.kotlin.core.platform.Plugin
import com.segment.analytics.kotlin.core.platform.plugins.LogType
import com.segment.analytics.kotlin.core.platform.plugins.log
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -33,14 +34,14 @@ data class Settings(
}
}

internal fun Analytics.update(settings: Settings) {
internal fun Analytics.update(settings: Settings, type: Plugin.UpdateType) {
timeline.applyClosure { plugin ->
if (plugin is DestinationPlugin) {
plugin.enabled = settings.isDestinationEnabled(plugin.key)
}
// tell all top level plugins to update.
// For destination plugins they auto-handle propagation to sub-plugins
plugin.update(settings)
plugin.update(settings, type)
}
}

Expand All @@ -67,8 +68,15 @@ fun Analytics.checkSettings() {
}
settingsObj?.let {
log("Dispatching update settings on ${Thread.currentThread().name}")

// check current system state to determine whether it's initial or refresh
val systemState = store.currentState(System::class)
val hasSettings = systemState?.settings?.integrations != null &&
systemState.settings?.plan != null
val updateType = if (hasSettings) Plugin.UpdateType.Refresh else Plugin.UpdateType.Initial

store.dispatch(System.UpdateSettingsAction(settingsObj), System::class)
update(settingsObj)
update(settingsObj, updateType)
}

// we're good to go back to a running state.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ interface Plugin {
Utility // Executed only when called manually, such as Logging.
}

enum class UpdateType {
Initial,
Refresh
}

val type: Type
var analytics: Analytics // ideally will be auto-assigned by setup(), and can be declared as lateinit

Expand All @@ -33,7 +38,7 @@ interface Plugin {
return event
}

fun update(settings: Settings) {
fun update(settings: Settings, type: UpdateType) {
// empty body default
}
}
Expand Down Expand Up @@ -83,10 +88,10 @@ abstract class DestinationPlugin : EventPlugin {
timeline.remove(plugin)
}

override fun update(settings: Settings) {
override fun update(settings: Settings, type: Plugin.UpdateType) {
// Apply settings update to its own plugins
timeline.applyClosure {
it.update(settings)
it.update(settings, type)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal class Timeline {
plugins[plugin.type]?.add(plugin)
analytics.store.currentState(System::class)?.settings?.let {
// if we have settings then update plugin with it
plugin.update(it)
plugin.update(it, Plugin.UpdateType.Initial)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.segment.analytics.kotlin.core

import com.segment.analytics.kotlin.core.platform.Plugin
import com.segment.analytics.kotlin.core.utils.StubPlugin
import io.mockk.*
import kotlinx.coroutines.runBlocking
Expand Down Expand Up @@ -87,7 +88,8 @@ class SettingsTests {
},
plan = emptyJsonObject,
edgeFunction = emptyJsonObject
)
),
Plugin.UpdateType.Initial
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class AmplitudeSession : Plugin {
private var timer: TimerTask? = null
private val fireTime: Long = 300000

override fun update(settings: Settings) {
override fun update(settings: Settings, type:Plugin.UpdateType) {
active = settings.isDestinationEnabled(key)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.FirebaseAnalytics.Event
import com.google.firebase.analytics.FirebaseAnalytics.Param
import com.segment.analytics.kotlin.android.plugins.AndroidLifecycle
import com.segment.analytics.kotlin.core.Analytics
import com.segment.analytics.kotlin.core.BaseEvent
import com.segment.analytics.kotlin.core.IdentifyEvent
import com.segment.analytics.kotlin.core.Properties
import com.segment.analytics.kotlin.core.ScreenEvent
import com.segment.analytics.kotlin.core.TrackEvent
import com.segment.analytics.kotlin.core.*
import com.segment.analytics.kotlin.core.platform.DestinationPlugin
import com.segment.analytics.kotlin.core.platform.Plugin
import com.segment.analytics.kotlin.core.platform.plugins.log
import com.segment.analytics.kotlin.core.utilities.getDouble
import com.segment.analytics.kotlin.core.utilities.getMapSet
Expand Down Expand Up @@ -77,6 +73,13 @@ class FirebaseDestination(
firebaseAnalytics = FirebaseAnalytics.getInstance(context)
}

override fun update(settings: Settings, type: Plugin.UpdateType) {
// if we've already set up this singleton SDK, can't do it again, so skip.
if (type != Plugin.UpdateType.Initial) return

super.update(settings, type)
}

override fun identify(payload: IdentifyEvent): BaseEvent? {
var returnPayload = super.identify(payload)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.segment.analytics.kotlin.core.platform.DestinationPlugin
import com.segment.analytics.kotlin.core.platform.plugins.LogType
import com.segment.analytics.kotlin.android.plugins.AndroidLifecycle
import com.segment.analytics.kotlin.android.utilities.toJSONObject
import com.segment.analytics.kotlin.core.platform.Plugin
import com.segment.analytics.kotlin.core.platform.plugins.log
import com.segment.analytics.kotlin.core.utilities.*
import kotlinx.serialization.json.*
Expand Down Expand Up @@ -163,8 +164,11 @@ class MixpanelDestination(
return payload
}

override fun update(settings: Settings) {
super.update(settings)
override fun update(settings: Settings, type:Plugin.UpdateType) {
// if we've already set up this singleton SDK, can't do it again, so skip.
if (type != Plugin.UpdateType.Initial) return

super.update(settings, type)
val mixpanelSettings = settings.integrations[key]
mixpanelSettings?.jsonObject?.let {
analytics.log("mixpanel.received settings=$it", type = LogType.INFO)
Expand Down