diff --git a/android/src/main/java/com/amplitude/android/Amplitude.kt b/android/src/main/java/com/amplitude/android/Amplitude.kt index 9482d271..6c98c224 100644 --- a/android/src/main/java/com/amplitude/android/Amplitude.kt +++ b/android/src/main/java/com/amplitude/android/Amplitude.kt @@ -11,6 +11,7 @@ import com.amplitude.core.utilities.FileStorage import com.amplitude.id.FileIdentityStorageProvider import com.amplitude.id.IdentityConfiguration import com.amplitude.id.IdentityContainer +import com.amplitude.id.IdentityUpdateType import kotlinx.coroutines.launch open class Amplitude( @@ -34,7 +35,11 @@ open class Amplitude( storageDirectory = storageDirectory ) ) - idContainer.identityManager.addIdentityListener(AnalyticsIdentityListener(store)) + val listener = AnalyticsIdentityListener(store) + idContainer.identityManager.addIdentityListener(listener) + if (idContainer.identityManager.isInitialized()) { + listener.onIdentityChanged(idContainer.identityManager.getIdentity(), IdentityUpdateType.Initialized) + } amplitudeScope.launch(amplitudeDispatcher) { previousSessionId = storage.read(Storage.Constants.PREVIOUS_SESSION_ID) ?.let { it.toLong() @@ -49,9 +54,9 @@ open class Amplitude( it.toLong() } ?: -1 add(AndroidContextPlugin()) + add(AndroidLifecyclePlugin()) } add(AmplitudeDestination()) - add(AndroidLifecyclePlugin()) } fun onEnterForeground(timestamp: Long) { @@ -160,3 +165,21 @@ open class Amplitude( const val END_SESSION_EVENT = "session_end" } } +/** + * constructor function to build amplitude in dsl format with config options + * Usage: Amplitude("123", context) { + * this.flushQueueSize = 10 + * } + * + * NOTE: this method should only be used for Android application. + * + * @param apiKey Api Key + * @param context Android Context + * @param configs Configuration + * @return Amplitude Android Instance + */ +fun Amplitude(apiKey: String, context: Context, configs: Configuration.() -> Unit): com.amplitude.android.Amplitude { + val config = Configuration(apiKey, context) + configs.invoke(config) + return com.amplitude.android.Amplitude(config) +} diff --git a/android/src/main/java/com/amplitude/android/Configuration.kt b/android/src/main/java/com/amplitude/android/Configuration.kt index 5179ae15..db085750 100644 --- a/android/src/main/java/com/amplitude/android/Configuration.kt +++ b/android/src/main/java/com/amplitude/android/Configuration.kt @@ -1,6 +1,7 @@ package com.amplitude.android import android.content.Context +import com.amplitude.android.events.Plan import com.amplitude.android.utilities.AndroidLoggerProvider import com.amplitude.android.utilities.AndroidStorageProvider import com.amplitude.core.Configuration @@ -25,6 +26,7 @@ class Configuration @JvmOverloads constructor( useBatch: Boolean = false, serverZone: ServerZone = ServerZone.US, serverUrl: String? = null, + plan: Plan? = null, val useAdvertisingIdForDeviceId: Boolean = false, val useAppSetIdForDeviceId: Boolean = false, val newDeviceIdPerInstall: Boolean = false, @@ -34,7 +36,7 @@ class Configuration @JvmOverloads constructor( val flushEventsOnClose: Boolean = true, val minTimeBetweenSessionsMillis: Long = MIN_TIME_BETWEEN_SESSIONS_MILLIS, val trackingSessionEvents: Boolean = true -) : Configuration(apiKey, flushQueueSize, flushIntervalMillis, instanceName, optOut, storageProvider, loggerProvider, minIdLength, partnerId, callback, flushMaxRetries, useBatch, serverZone, serverUrl) { +) : Configuration(apiKey, flushQueueSize, flushIntervalMillis, instanceName, optOut, storageProvider, loggerProvider, minIdLength, partnerId, callback, flushMaxRetries, useBatch, serverZone, serverUrl, plan) { companion object { const val MIN_TIME_BETWEEN_SESSIONS_MILLIS: Long = 5 * 60 * 1000 } diff --git a/android/src/main/java/com/amplitude/android/events/Export.kt b/android/src/main/java/com/amplitude/android/events/Export.kt new file mode 100644 index 00000000..6d6d34e0 --- /dev/null +++ b/android/src/main/java/com/amplitude/android/events/Export.kt @@ -0,0 +1,24 @@ +package com.amplitude.android.events + +import com.amplitude.core.events.BaseEvent +import com.amplitude.core.events.EventOptions +import com.amplitude.core.events.GroupIdentifyEvent +import com.amplitude.core.events.Identify +import com.amplitude.core.events.IdentifyEvent +import com.amplitude.core.events.Plan +import com.amplitude.core.events.Revenue +import com.amplitude.core.events.RevenueEvent + +open class BaseEvent : BaseEvent() +open class IdentifyEvent : IdentifyEvent() +open class GroupIdentifyEvent : GroupIdentifyEvent() +open class EventOptions : EventOptions() +open class Identify : Identify() +open class Revenue : Revenue() +open class RevenueEvent : RevenueEvent() +open class Plan( + branch: String? = null, + source: String? = null, + version: String? = null, + versionId: String? = null +) : Plan(branch, source, version, versionId) diff --git a/android/src/main/java/com/amplitude/android/plugins/AndroidContextPlugin.kt b/android/src/main/java/com/amplitude/android/plugins/AndroidContextPlugin.kt index 38137e30..55f7251e 100644 --- a/android/src/main/java/com/amplitude/android/plugins/AndroidContextPlugin.kt +++ b/android/src/main/java/com/amplitude/android/plugins/AndroidContextPlugin.kt @@ -145,6 +145,11 @@ class AndroidContextPlugin : Plugin { event.partnerId = it } } + event.plan ?: let { + amplitude.configuration.plan ?. let { + event.plan = it + } + } } private fun getAndroidAmplitude(): com.amplitude.android.Amplitude { diff --git a/core/src/main/java/com/amplitude/core/Configuration.kt b/core/src/main/java/com/amplitude/core/Configuration.kt index 7203f7c7..4356ad7a 100644 --- a/core/src/main/java/com/amplitude/core/Configuration.kt +++ b/core/src/main/java/com/amplitude/core/Configuration.kt @@ -1,6 +1,7 @@ package com.amplitude.core import com.amplitude.core.events.BaseEvent +import com.amplitude.core.events.Plan import com.amplitude.core.utilities.ConsoleLoggerProvider import com.amplitude.core.utilities.InMemoryStorageProvider @@ -20,7 +21,8 @@ open class Configuration @JvmOverloads constructor( val flushMaxRetries: Int = FLUSH_MAX_RETRIES, var useBatch: Boolean = false, var serverZone: ServerZone = ServerZone.US, - var serverUrl: String? = null + var serverUrl: String? = null, + val plan: Plan? = null ) { companion object { diff --git a/core/src/main/java/com/amplitude/core/events/GroupIdentifyEvent.kt b/core/src/main/java/com/amplitude/core/events/GroupIdentifyEvent.kt index b20d0516..f697e5b5 100644 --- a/core/src/main/java/com/amplitude/core/events/GroupIdentifyEvent.kt +++ b/core/src/main/java/com/amplitude/core/events/GroupIdentifyEvent.kt @@ -2,7 +2,7 @@ package com.amplitude.core.events import com.amplitude.core.Constants -class GroupIdentifyEvent : BaseEvent() { +open class GroupIdentifyEvent : BaseEvent() { override var eventType = Constants.GROUP_IDENTIFY_EVENT override fun isValid(): Boolean { diff --git a/core/src/main/java/com/amplitude/core/events/Identify.kt b/core/src/main/java/com/amplitude/core/events/Identify.kt index e90e3716..1fa4340d 100644 --- a/core/src/main/java/com/amplitude/core/events/Identify.kt +++ b/core/src/main/java/com/amplitude/core/events/Identify.kt @@ -15,7 +15,7 @@ enum class IdentifyOperation(val operationType: String) { REMOVE("\$remove") } -class Identify() { +open class Identify() { private val propertySet: MutableSet = mutableSetOf() val properties = mutableMapOf() diff --git a/core/src/main/java/com/amplitude/core/events/IdentifyEvent.kt b/core/src/main/java/com/amplitude/core/events/IdentifyEvent.kt index fff639c9..97b6cf69 100644 --- a/core/src/main/java/com/amplitude/core/events/IdentifyEvent.kt +++ b/core/src/main/java/com/amplitude/core/events/IdentifyEvent.kt @@ -2,6 +2,6 @@ package com.amplitude.core.events import com.amplitude.core.Constants -class IdentifyEvent : BaseEvent() { +open class IdentifyEvent : BaseEvent() { override var eventType = Constants.IDENTIFY_EVENT } diff --git a/core/src/main/java/com/amplitude/core/events/Plan.kt b/core/src/main/java/com/amplitude/core/events/Plan.kt index 67c85745..543c5dde 100644 --- a/core/src/main/java/com/amplitude/core/events/Plan.kt +++ b/core/src/main/java/com/amplitude/core/events/Plan.kt @@ -4,7 +4,7 @@ import com.amplitude.common.jvm.ConsoleLogger import org.json.JSONException import org.json.JSONObject -data class Plan @JvmOverloads constructor( +open class Plan @JvmOverloads constructor( val branch: String? = null, val source: String? = null, val version: String? = null, diff --git a/core/src/main/java/com/amplitude/core/events/Revenue.kt b/core/src/main/java/com/amplitude/core/events/Revenue.kt index a5aa8228..c5f7245d 100644 --- a/core/src/main/java/com/amplitude/core/events/Revenue.kt +++ b/core/src/main/java/com/amplitude/core/events/Revenue.kt @@ -1,6 +1,6 @@ package com.amplitude.core.events -class Revenue { +open class Revenue { /** * The Product ID field. */ diff --git a/core/src/main/java/com/amplitude/core/events/RevenueEvent.kt b/core/src/main/java/com/amplitude/core/events/RevenueEvent.kt index 75ef27c6..b2249ba3 100644 --- a/core/src/main/java/com/amplitude/core/events/RevenueEvent.kt +++ b/core/src/main/java/com/amplitude/core/events/RevenueEvent.kt @@ -2,6 +2,6 @@ package com.amplitude.core.events import com.amplitude.core.Constants -class RevenueEvent : BaseEvent() { +open class RevenueEvent : BaseEvent() { override var eventType = Constants.AMP_REVENUE_EVENT } diff --git a/core/src/main/java/com/amplitude/core/platform/plugins/ContextPlugin.kt b/core/src/main/java/com/amplitude/core/platform/plugins/ContextPlugin.kt index a69cbb1d..0e76bca6 100644 --- a/core/src/main/java/com/amplitude/core/platform/plugins/ContextPlugin.kt +++ b/core/src/main/java/com/amplitude/core/platform/plugins/ContextPlugin.kt @@ -35,6 +35,11 @@ class ContextPlugin : Plugin { event.partnerId = it } } + event.plan ?: let { + amplitude.configuration.plan ?. let { + event.plan = it + } + } } override fun execute(event: BaseEvent): BaseEvent? { diff --git a/core/src/test/kotlin/com/amplitude/core/AmplitudeTest.kt b/core/src/test/kotlin/com/amplitude/core/AmplitudeTest.kt index 521b9ad2..c5626c71 100644 --- a/core/src/test/kotlin/com/amplitude/core/AmplitudeTest.kt +++ b/core/src/test/kotlin/com/amplitude/core/AmplitudeTest.kt @@ -6,6 +6,7 @@ import com.amplitude.core.events.GroupIdentifyEvent import com.amplitude.core.events.Identify import com.amplitude.core.events.IdentifyEvent import com.amplitude.core.events.IdentifyOperation +import com.amplitude.core.events.Plan import com.amplitude.core.events.Revenue import com.amplitude.core.events.RevenueEvent import com.amplitude.core.platform.Plugin @@ -36,7 +37,8 @@ internal class AmplitudeTest { fun setup() { mockHTTPClient(createSuccessResponse()) val testApiKey = "test-123" - amplitude = testAmplitude(Configuration(testApiKey)) + val plan = Plan("test-branch", "test") + amplitude = testAmplitude(Configuration(testApiKey, plan = plan)) } @Nested @@ -59,6 +61,7 @@ internal class AmplitudeTest { assertEquals("${Constants.SDK_LIBRARY}/${Constants.SDK_VERSION}", it.library) assertEquals(mapOf(Pair("foo", "bar")), it.eventProperties) assertEquals("CA", it.region) + assertEquals("test", it.plan?.source) } } } @@ -294,8 +297,8 @@ internal class AmplitudeTest { val event = BaseEvent() event.eventType = "test event" var callbackCalled = false - amplitude.track(event) { event, status, message -> - assertEquals("test event", event.eventType) + amplitude.track(event) { e, status, message -> + assertEquals("test event", e.eventType) assertEquals(200, status) assertEquals("Event sent success.", message) callbackCalled = true diff --git a/core/src/test/kotlin/com/amplitude/core/events/BaseEventTest.kt b/core/src/test/kotlin/com/amplitude/core/events/BaseEventTest.kt index 6671fccd..1fd4756c 100644 --- a/core/src/test/kotlin/com/amplitude/core/events/BaseEventTest.kt +++ b/core/src/test/kotlin/com/amplitude/core/events/BaseEventTest.kt @@ -15,11 +15,14 @@ class BaseEventTest { event.eventType = "test" event.country = "US" val eventOptions = EventOptions() + val plan = Plan(branch = "test") eventOptions.userId = "user_id" eventOptions.country = "DE" + eventOptions.plan = plan event.mergeEventOptions(eventOptions) assertEquals(event.userId, "user_id") assertEquals(event.country, "US") + assertEquals(event.plan, plan) } @Test diff --git a/core/src/test/kotlin/com/amplitude/core/events/PlanTest.kt b/core/src/test/kotlin/com/amplitude/core/events/PlanTest.kt index 893da4e0..93680181 100644 --- a/core/src/test/kotlin/com/amplitude/core/events/PlanTest.kt +++ b/core/src/test/kotlin/com/amplitude/core/events/PlanTest.kt @@ -34,7 +34,9 @@ class PlanTest { .put(Plan.AMP_PLAN_VERSION, version) .put(Plan.AMP_PLAN_VERSION_ID, versionId) val plan = Plan.fromJSONObject(jsonObject) - val expectedPlan = Plan(branch, source, version, versionId) - assertEquals(expectedPlan, plan) + assertEquals(branch, plan.branch) + assertEquals(source, plan.source) + assertEquals(version, plan.version) + assertEquals(versionId, plan.versionId) } } diff --git a/samples/kotlin-android-app/src/main/java/com/amplitude/android/sample/MainActivity.kt b/samples/kotlin-android-app/src/main/java/com/amplitude/android/sample/MainActivity.kt index 3e501579..b828576e 100644 --- a/samples/kotlin-android-app/src/main/java/com/amplitude/android/sample/MainActivity.kt +++ b/samples/kotlin-android-app/src/main/java/com/amplitude/android/sample/MainActivity.kt @@ -20,7 +20,7 @@ class MainActivity : AppCompatActivity() { .set("custom-properties", "sample") val options = EventOptions() options.plan = Plan(branch = "test") - amplitude.identify(identify, options) + amplitude.identify(identify) // set groups fro this user val groupType = "test-group-type" @@ -41,6 +41,6 @@ class MainActivity : AppCompatActivity() { amplitude.revenue(revenue) // track event with event properties - amplitude.track("test event properties", mutableMapOf("test" to "test event property value")) + amplitude.track("test event properties", mapOf("test" to "test event property value"), options) } }