From e7d6cc10bc911c53d7e0d7070e1e1d0481131e1a Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Wed, 20 Sep 2023 17:33:30 +0200 Subject: [PATCH] fix api calls --- .../com/posthog/android/PostHogAndroid.kt | 7 +- .../android/internal/PostHogAndroidContext.kt | 59 ++++++++-- .../internal/PostHogSharedPreferences.kt | 12 --- .../posthog/android/internal/PostHogUtils.kt | 15 ++- .../posthog/android/sample/MainActivity.kt | 1 + .../java/com/posthog/android/sample/MyApp.kt | 2 +- posthog-v3/posthog/api/posthog.api | 28 ++--- .../src/main/java/com/posthog/PostHog.kt | 101 +++++++++++------- .../main/java/com/posthog/PostHogConfig.kt | 10 +- .../main/java/com/posthog/PostHogContext.kt | 4 +- .../src/main/java/com/posthog/PostHogEvent.kt | 8 +- .../com/posthog/internal/PostHogBatchEvent.kt | 1 - .../java/com/posthog/internal/PostHogQueue.kt | 2 +- .../posthog/internal/PostHogSessionManager.kt | 11 +- .../com/posthog/internal/PostHogStorage.kt | 32 ------ .../src/test/resources/json/alias.json | 33 ++++++ .../test/resources/json/batch-request.json | 1 - .../src/test/resources/json/capture.json | 36 +++++++ .../test/resources/json/decide-request.json | 14 ++- .../test/resources/json/decide-response.json | 23 ++-- .../src/test/resources/json/group.json | 36 +++++++ .../src/test/resources/json/identify.json | 35 ++++++ .../src/test/resources/json/screen.json | 33 ++++++ 23 files changed, 366 insertions(+), 138 deletions(-) delete mode 100644 posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt create mode 100644 posthog-v3/posthog/src/test/resources/json/alias.json create mode 100644 posthog-v3/posthog/src/test/resources/json/capture.json create mode 100644 posthog-v3/posthog/src/test/resources/json/group.json create mode 100644 posthog-v3/posthog/src/test/resources/json/identify.json create mode 100644 posthog-v3/posthog/src/test/resources/json/screen.json diff --git a/posthog-v3/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt index c72a311b..55ae083b 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/PostHogAndroid.kt @@ -9,6 +9,7 @@ import com.posthog.android.internal.PostHogActivityLifecycleCallback import com.posthog.android.internal.PostHogAndroidContext import com.posthog.android.internal.PostHogAndroidLogger import com.posthog.android.internal.PostHogSharedPreferences +import com.posthog.android.internal.appContext import java.io.File public class PostHogAndroid private constructor() { @@ -30,7 +31,7 @@ public class PostHogAndroid private constructor() { private fun setAndroidConfig(context: Context, config: PostHogConfig) { config.logger = if (config.logger is PostHogPrintLogger) PostHogAndroidLogger(config) else config.logger - config.context = config.context ?: PostHogAndroidContext(context) + config.context = config.context ?: PostHogAndroidContext(context, config) val legacyPath = context.getDir("app_posthog-disk-queue", Context.MODE_PRIVATE) val path = File(context.cacheDir, "posthog-disk-queue") @@ -42,9 +43,5 @@ public class PostHogAndroid private constructor() { config.integrations.add(PostHogActivityLifecycleCallback(context)) } } - - private fun Context.appContext(): Context { - return applicationContext ?: this - } } } diff --git a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt index 2aea2fa9..02538145 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt @@ -1,16 +1,63 @@ package com.posthog.android.internal import android.content.Context +import android.os.Build +import com.posthog.PostHogConfig import com.posthog.PostHogContext +import java.util.Locale +import java.util.TimeZone -// PostHogContext +internal class PostHogAndroidContext(private val context: Context, private val config: PostHogConfig) : PostHogContext { -internal class PostHogAndroidContext(context: Context) : PostHogContext { - override fun getStaticContext(): Map? { - return null + private val cacheStaticContext by lazy { + val staticContext = mutableMapOf() + val displayMetrics = context.displayMetrics() + staticContext["\$screen_density"] = displayMetrics.density + staticContext["\$screen_height"] = displayMetrics.heightPixels + staticContext["\$screen_width"] = displayMetrics.widthPixels + + val packageInfo = getPackageInfo(context, config) + packageInfo?.let { + // TODO: check if we should use getApplicationInfo instead + it.applicationInfo?.loadLabel(context.packageManager)?.let { name -> + staticContext["\$app_name"] = name + } + it.versionName?.let { name -> + staticContext["\$app_version"] = name + } + staticContext["\$app_namespace"] = it.packageName + // TODO: is it string instead? + staticContext["\$app_build"] = it.versionCodeCompat() + } + + staticContext["\$device_manufacturer"] = Build.MANUFACTURER + staticContext["\$device_model"] = Build.MODEL + staticContext["\$device_name"] = Build.DEVICE + staticContext["\$os_name"] = "Android" + staticContext["\$os_version"] = Build.VERSION.RELEASE + // TODO: $device_token? + + // TODO: read from metadata + staticContext["\$lib"] = config.enable + staticContext["\$lib_version"] = "version" + + staticContext } - override fun getDynamicContext(): Map? { - return null + override fun getStaticContext(): Map { + return cacheStaticContext + } + + override fun getDynamicContext(): Map { + val dynamicContext = mutableMapOf() + dynamicContext["\$locale"] = "${Locale.getDefault().language}-${Locale.getDefault().country}" + System.getProperty("http.agent")?.let { + dynamicContext["\$user_agent"] = it + } + dynamicContext["\$timezone"] = TimeZone.getDefault().id + + // TODO: "$network_bluetooth", "$network_carrier","$network_cellular","$network_wifi" + + return dynamicContext } } diff --git a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogSharedPreferences.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogSharedPreferences.kt index f5d94a2d..8c3c4828 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogSharedPreferences.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogSharedPreferences.kt @@ -9,7 +9,6 @@ internal class PostHogSharedPreferences(context: Context, config: PostHogConfig) PostHogPreferences { private val sharedPreferences = context.getSharedPreferences("posthog-android-${config.apiKey}", MODE_PRIVATE) - private val packageInfo = getPackageInfo(context, config) override fun getValue(key: String, defaultValue: Any?): Any? { return sharedPreferences.all[key] ?: defaultValue @@ -44,15 +43,4 @@ internal class PostHogSharedPreferences(context: Context, config: PostHogConfig) edit.clear() edit.apply() } - - fun init() { - packageInfo?.let { - // key= build - val versionCode = getVersionCode(it) - // key=version - val versioName = it.versionName - - // TODO: send application installed or updated event - } - } } diff --git a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogUtils.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogUtils.kt index f2385b9f..a2e14502 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogUtils.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogUtils.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Build +import android.util.DisplayMetrics import com.posthog.PostHogConfig internal fun getPackageInfo( @@ -27,11 +28,11 @@ internal fun getPackageInfo( } } -internal fun getVersionCode(packageInfo: PackageInfo): Long { +internal fun PackageInfo.versionCodeCompat(): Long { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - packageInfo.longVersionCode + longVersionCode } else { - packageInfo.versionCode.toLong() + versionCode.toLong() } } @@ -45,3 +46,11 @@ internal fun hasFeature(context: Context): Boolean { internal fun isConnected(context: Context): Boolean { return false } + +internal fun Context.displayMetrics(): DisplayMetrics { + return resources.displayMetrics +} + +internal fun Context.appContext(): Context { + return applicationContext ?: this +} diff --git a/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MainActivity.kt b/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MainActivity.kt index 6a46d965..cf1a38cf 100644 --- a/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MainActivity.kt +++ b/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MainActivity.kt @@ -39,6 +39,7 @@ fun Greeting(name: String, modifier: Modifier = Modifier) { modifier = modifier, onClick = { // PostHog.optOut() +// PostHog.optIn() PostHog.identify("my_distinct_id", properties = mapOf("my_property" to 1), userProperties = mapOf("name" to "hello")) // PostHog.capture("testEvent", mapOf("testProperty" to "testValue")) // PostHog.optIn() diff --git a/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MyApp.kt b/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MyApp.kt index efb6f096..4aa0d2f0 100644 --- a/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MyApp.kt +++ b/posthog-v3/posthog-samples/posthog-android-sample/src/main/java/com/posthog/android/sample/MyApp.kt @@ -12,7 +12,7 @@ class MyApp : Application() { debug = true // flushAt = 5 // flushIntervalSeconds = 5 -// flushAt = 1 + flushAt = 1 } PostHogAndroid.setup(this, config) diff --git a/posthog-v3/posthog/api/posthog.api b/posthog-v3/posthog/api/posthog.api index 33a81bbd..3311d8e0 100644 --- a/posthog-v3/posthog/api/posthog.api +++ b/posthog-v3/posthog/api/posthog.api @@ -2,8 +2,8 @@ public final class com/posthog/PostHog { public static final field Companion Lcom/posthog/PostHog$Companion; public final fun alias (Ljava/lang/String;Ljava/util/Map;)V public static synthetic fun alias$default (Lcom/posthog/PostHog;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)V - public final fun capture (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V - public static synthetic fun capture$default (Lcom/posthog/PostHog;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILjava/lang/Object;)V + public final fun capture (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V + public static synthetic fun capture$default (Lcom/posthog/PostHog;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;ILjava/lang/Object;)V public final fun close ()V public final fun flush ()V public final fun getAnonymousId ()Ljava/lang/String; @@ -19,13 +19,11 @@ public final class com/posthog/PostHog { public static synthetic fun isFeatureEnabled$default (Lcom/posthog/PostHog;Ljava/lang/String;ZILjava/lang/Object;)Z public final fun optIn ()V public final fun optOut ()V - public final fun register (Ljava/lang/String;Ljava/lang/Object;)V public final fun reloadFeatureFlagsRequest ()V public final fun reset ()V public final fun screen (Ljava/lang/String;Ljava/util/Map;)V public static synthetic fun screen$default (Lcom/posthog/PostHog;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)V public final fun setup (Lcom/posthog/PostHogConfig;)V - public final fun unregister (Ljava/lang/String;)V } public final class com/posthog/PostHog$Companion { @@ -68,6 +66,8 @@ public final class com/posthog/PostHogConfig { public final fun getMaxQueueSize ()I public final fun getPreferences ()Lcom/posthog/PostHogPreferences; public final fun getPreloadFeatureFlags ()Z + public final fun getSdkName ()Ljava/lang/String; + public final fun getSdkVersion ()Ljava/lang/String; public final fun getSendFeatureFlagEvent ()Z public final fun getStoragePrefix ()Ljava/lang/String; public final fun setContext (Lcom/posthog/PostHogContext;)V @@ -83,6 +83,8 @@ public final class com/posthog/PostHogConfig { public final fun setMaxQueueSize (I)V public final fun setPreferences (Lcom/posthog/PostHogPreferences;)V public final fun setPreloadFeatureFlags (Z)V + public final fun setSdkName (Ljava/lang/String;)V + public final fun setSdkVersion (Ljava/lang/String;)V public final fun setSendFeatureFlagEvent (Z)V public final fun setStoragePrefix (Ljava/lang/String;)V } @@ -106,20 +108,20 @@ public abstract class com/posthog/PostHogEncryption { } public final class com/posthog/PostHogEvent { - public fun (Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;Ljava/util/Map;)V - public synthetic fun (Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()Ljava/util/Map; - public final fun component3 ()Ljava/util/Date; - public final fun component4 ()Ljava/util/UUID; - public final fun component5 ()Ljava/util/Map; - public final fun copy (Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;Ljava/util/Map;)Lcom/posthog/PostHogEvent; - public static synthetic fun copy$default (Lcom/posthog/PostHogEvent;Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;Ljava/util/Map;ILjava/lang/Object;)Lcom/posthog/PostHogEvent; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/util/Map; + public final fun component4 ()Ljava/util/Date; + public final fun component5 ()Ljava/util/UUID; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;)Lcom/posthog/PostHogEvent; + public static synthetic fun copy$default (Lcom/posthog/PostHogEvent;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Date;Ljava/util/UUID;ILjava/lang/Object;)Lcom/posthog/PostHogEvent; public fun equals (Ljava/lang/Object;)Z + public final fun getDistinctId ()Ljava/lang/String; public final fun getEvent ()Ljava/lang/String; public final fun getProperties ()Ljava/util/Map; public final fun getTimestamp ()Ljava/util/Date; - public final fun getUserProperties ()Ljava/util/Map; public final fun getUuid ()Ljava/util/UUID; public fun hashCode ()I public fun toString ()Ljava/lang/String; diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt index f7fd5526..f84fd140 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt @@ -6,7 +6,6 @@ import com.posthog.internal.PostHogMemoryPreferences import com.posthog.internal.PostHogQueue import com.posthog.internal.PostHogSerializer import com.posthog.internal.PostHogSessionManager -import com.posthog.internal.PostHogStorage import com.posthog.internal.SendCachedEventsIntegration public class PostHog private constructor() { @@ -16,14 +15,12 @@ public class PostHog private constructor() { private val lock = Any() private var config: PostHogConfig? = null - private var storage: PostHogStorage? = null private var sessionManager: PostHogSessionManager? = null private var featureFlags: PostHogFeatureFlags? = null private var api: PostHogApi? = null private var queue: PostHogQueue? = null - private var context: PostHogContext? = null - // TODO: flushTimer, reachability, flagCallReported + // TODO: reachability public fun setup(config: PostHogConfig) { synchronized(lock) { @@ -32,13 +29,13 @@ public class PostHog private constructor() { return } - val storage = PostHogStorage(config) - sessionManager = PostHogSessionManager(storage) + val preferences = config.preferences ?: PostHogMemoryPreferences() + config.preferences = preferences + sessionManager = PostHogSessionManager(preferences) val serializer = PostHogSerializer(config) val api = PostHogApi(config, serializer) - val queue = PostHogQueue(config, storage, api, serializer) + val queue = PostHogQueue(config, api, serializer) val featureFlags = PostHogFeatureFlags(config, api) - config.preferences = config.preferences ?: PostHogMemoryPreferences() val enable = config.preferences?.getValue("opt-out", defaultValue = config.enable) as? Boolean enable?.let { @@ -48,7 +45,6 @@ public class PostHog private constructor() { val sendCachedEventsIntegration = SendCachedEventsIntegration(config, api, serializer) this.api = api - this.storage = storage this.config = config this.queue = queue this.featureFlags = featureFlags @@ -62,8 +58,9 @@ public class PostHog private constructor() { queue.start() - // TODO: guarded by preloadFeatureFlags - loadFeatureFlagsRequest() + if (config.preloadFeatureFlags) { + loadFeatureFlagsRequest() + } } } @@ -87,39 +84,50 @@ public class PostHog private constructor() { return sessionManager?.anonymousId } - public val distinctId: String? + public val distinctId: String get() { if (!isEnabled()) { - return null + return "" } - return sessionManager?.distinctId + return sessionManager?.distinctId ?: "" } - private fun buildProperties(properties: Map?): Map { + private fun buildProperties(distinctId: String, properties: Map?, userProperties: Map?, groupProperties: Map?): Map { val props = mutableMapOf() - properties?.let { + config?.context?.getStaticContext()?.let { props.putAll(it) } - context?.getStaticContext()?.let { + config?.context?.getDynamicContext()?.let { props.putAll(it) } - context?.getDynamicContext()?.let { + // TODO: $feature/* properties, $active_feature_flags array + + // TODO: $set_once + userProperties?.let { + props["\$set"] = it + } + + groupProperties?.let { + props["\$groups"] = it + } + + properties?.let { props.putAll(it) } - // distinctId is always present but it has to be nullable because the SDK may be disabled - distinctId?.let { - props["distinct_id"] = it + // only set if not there. + props["distinct_id"]?.let { + props["distinct_id"] = distinctId } return props } // test: $merge_dangerously - public fun capture(event: String, properties: Map? = null, userProperties: Map? = null) { + public fun capture(event: String, properties: Map? = null, userProperties: Map? = null, groupProperties: Map? = null) { if (!isEnabled()) { return } @@ -128,7 +136,7 @@ public class PostHog private constructor() { return } - val postHogEvent = PostHogEvent(event, buildProperties(properties), userProperties = userProperties) + val postHogEvent = PostHogEvent(event, distinctId, properties = buildProperties(distinctId, properties, userProperties, groupProperties)) queue?.add(postHogEvent) } @@ -150,11 +158,11 @@ public class PostHog private constructor() { config?.preferences?.setValue("opt-out", false) } - public fun register(key: String, value: Any) { - } - - public fun unregister(key: String) { - } +// public fun register(key: String, value: Any) { +// } +// +// public fun unregister(key: String) { +// } public fun screen(screenTitle: String, properties: Map? = null) { if (!isEnabled()) { @@ -165,7 +173,6 @@ public class PostHog private constructor() { props["\$screen_name"] = screenTitle properties?.let { - // TODO: who has precedence here? the given props or the built ones props.putAll(it) } @@ -192,26 +199,38 @@ public class PostHog private constructor() { return } - // TODO: reset feature flags, set anonymousId and distinctId -// val oldDistinctId = this.distinctId + val oldDistinctId = this.distinctId val props = mutableMapOf() - props["distinct_id"] = distinctId anonymousId?.let { props["\$anon_distinct_id"] = it } + props["distinct_id"] = distinctId + properties?.let { props.putAll(it) } capture("\$identify", properties = props, userProperties = userProperties) + + if (oldDistinctId != distinctId) { + reloadFeatureFlagsRequest() + } } - public fun group(type: String, key: String, properties: Map? = null) { + public fun group(type: String, key: String, groupProperties: Map? = null) { if (!isEnabled()) { return } - // TODO: groupProperties, event $groupidentify + + val props = mutableMapOf() + props["\$group_type"] = type + props["\$group_key"] = key + groupProperties?.let { + props["\$group_set"] = it + } + + capture("\$groupidentify", properties = props) } public fun reloadFeatureFlagsRequest() { @@ -223,7 +242,7 @@ public class PostHog private constructor() { private fun loadFeatureFlagsRequest() { val map = mapOf() - featureFlags?.loadFeatureFlags(buildProperties(map)) + featureFlags?.loadFeatureFlags(buildProperties(distinctId, map, null, null)) } public fun isFeatureEnabled(key: String, defaultValue: Boolean = false): Boolean { @@ -239,7 +258,15 @@ public class PostHog private constructor() { } val flag = featureFlags?.getFeatureFlag(key, defaultValue) ?: defaultValue - // TODO: reportFeatureFlagCalled, guarded by sendFeatureFlagEvent + if (config?.sendFeatureFlagEvent == true) { + val props = mutableMapOf() + props["\$feature_flag"] = key + flag?.let { + props["\$feature_flag_response"] = it + } + + capture("\$feature_flag_called", properties = props) + } return flag } @@ -268,8 +295,6 @@ public class PostHog private constructor() { queue?.clear() } - // TODO: groups, groupIdentify, group, feature flags, buildProperties (static context, dynamic context, distinct_id) - private fun isEnabled(): Boolean { if (!enabled) { config?.logger?.log("Setup isn't called.") diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt index 1dea4f6f..77e4a952 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt @@ -23,10 +23,18 @@ public class PostHogConfig( ) { @PostHogInternal public var logger: PostHogLogger = PostHogPrintLogger(this) + + @PostHogInternal public var context: PostHogContext? = null // TODO: read the repo name and version - internal var userAgent: String = "posthog-android/3.0.0" + @PostHogInternal + public var sdkName: String = "posthog-android" + + @PostHogInternal + public var sdkVersion: String = "3.0.0" + + internal val userAgent: String = "$sdkName/$sdkVersion" // should this be configurable by the user? @PostHogInternal diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt index 2b5f778c..c1a61fe5 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt @@ -1,7 +1,7 @@ package com.posthog public interface PostHogContext { - public fun getStaticContext(): Map? + public fun getStaticContext(): Map - public fun getDynamicContext(): Map? + public fun getDynamicContext(): Map } diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogEvent.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogEvent.kt index eb52606a..6fdf6551 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHogEvent.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogEvent.kt @@ -6,11 +6,9 @@ import java.util.UUID public data class PostHogEvent( val event: String, - val properties: Map, + @SerializedName("\$distinct_id") + val distinctId: String, + val properties: Map? = null, val timestamp: Date = Date(), val uuid: UUID = UUID.randomUUID(), - @SerializedName("\$set") - val userProperties: Map? = null, -// @SerializedName("\$set_once") -// val setOnce: Map? = null, ) diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogBatchEvent.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogBatchEvent.kt index 26a73ecd..a75243a4 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogBatchEvent.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogBatchEvent.kt @@ -8,7 +8,6 @@ internal data class PostHogBatchEvent( @SerializedName("api_key") val apiKey: String, val batch: List, - val timestamp: Date = Date(), @SerializedName("sent_at") var sentAt: Date? = null, ) diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt index a5c93f7d..441e1ba0 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt @@ -13,7 +13,7 @@ import java.util.concurrent.atomic.AtomicBoolean import kotlin.concurrent.schedule import kotlin.math.min -internal class PostHogQueue(private val config: PostHogConfig, private val storage: PostHogStorage, private val api: PostHogApi, private val serializer: PostHogSerializer) { +internal class PostHogQueue(private val config: PostHogConfig, private val api: PostHogApi, private val serializer: PostHogSerializer) { private val deque: ArrayDeque = ArrayDeque() private val dequeLock = Any() diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt index 05cbbd07..f2d8d100 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogSessionManager.kt @@ -1,9 +1,10 @@ package com.posthog.internal +import com.posthog.PostHogPreferences import java.util.UUID // TODO: think about stateless about posthog-java (js-lite) -internal class PostHogSessionManager(private val storage: PostHogStorage) { +internal class PostHogSessionManager(private val preferences: PostHogPreferences) { // TODO: thread safety @@ -12,7 +13,7 @@ internal class PostHogSessionManager(private val storage: PostHogStorage) { var anonymousId: String get() { - var anonymousId = storage.getString(anonymousKey) + var anonymousId = preferences.getValue(anonymousKey) as? String if (anonymousId == null) { anonymousId = UUID.randomUUID().toString() @@ -21,14 +22,14 @@ internal class PostHogSessionManager(private val storage: PostHogStorage) { return anonymousId } set(value) { - storage.setString(anonymousKey, value) + preferences.setValue(anonymousKey, value) } var distinctId: String get() { - return storage.getString(distinctIdKey, defaultValue = anonymousId) ?: anonymousId + return preferences.getValue(distinctIdKey, defaultValue = anonymousId) as? String ?: anonymousId } set(value) { - storage.setString(distinctIdKey, value) + preferences.setValue(distinctIdKey, value) } } diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt deleted file mode 100644 index f4c8d8a9..00000000 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.posthog.internal - -import com.posthog.PostHogConfig - -internal class PostHogStorage(private val config: PostHogConfig) { - // TODO: move to disk cache instead of memory cache - - // File folder = context.getDir("posthog-disk-queue"/tag(apiKey), Context.MODE_PRIVATE); - // /data/user/0/com.posthog.myapplication/app_posthog-disk-queue/_6SG-F7I1vCuZ-HdJL3VZQqjBlaSb1_20hDPwqMNnGI.tmp - // instead of https://developer.android.com/reference/android/content/Context#getCacheDir() - - // application.getSharedPreferences("posthog-android", Context.MODE_PRIVATE) - legacy - // context.getSharedPreferences("posthog-android-" + tag, MODE_PRIVATE) - // eg posthog-android-_6SG-F7I1vCuZ-HdJL3VZQqjBlaSb1_20hDPwqMNnGI - private val keyValues = mutableMapOf() - private val lock = Any() - - fun getString(key: String, defaultValue: String? = null): String? { - var value: String? - synchronized(lock) { - val tempValue = keyValues[key] - value = if (tempValue != null && tempValue is String) tempValue else tempValue?.toString() - } - return value ?: defaultValue - } - - fun setString(key: String, value: String) { - synchronized(lock) { - keyValues[key] = value - } - } -} diff --git a/posthog-v3/posthog/src/test/resources/json/alias.json b/posthog-v3/posthog/src/test/resources/json/alias.json new file mode 100644 index 00000000..e74ad04c --- /dev/null +++ b/posthog-v3/posthog/src/test/resources/json/alias.json @@ -0,0 +1,33 @@ +{ + "event": "$create_alias", + "uuid": "8c04e5c1-8f6e-4002-96fd-1804799b6ffe", + "timestamp": "2023-09-20T11:58:49Z", + "properties": { + "$device_manufacturer": "Google", + "$os_version": "13", + "$screen_density": 2.625, + "$timezone": "Europe/Vienna", + "$locale": "en-US", + "$screen_width": 1080, + "$os_name": "Android", + "$screen_height": 2274, + "$user_agent": "Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.012)", + "$app_version": "1.0", + "$lib": "posthog-android", + "$device_name": "emu64a", + "$network_carrier": "T-Mobile", + "$device_id": "51432a27add1fd4b", + "$app_name": "My Application", + "$device_model": "sdk_gphone64_arm64", + "$lib_version": "version", + "$app_namespace": "com.posthog.myapplication", + "$app_build": "1", + "distinct_id": "my_identify", + "$feature/4535-funnel-bar-viz": true, + "$active_feature_flags": [ + "4535-funnel-bar-viz" + ], + "alias": "myAlias" + }, + "distinct_id": "my_identify" +} diff --git a/posthog-v3/posthog/src/test/resources/json/batch-request.json b/posthog-v3/posthog/src/test/resources/json/batch-request.json index 8f2a88a2..380a3b02 100644 --- a/posthog-v3/posthog/src/test/resources/json/batch-request.json +++ b/posthog-v3/posthog/src/test/resources/json/batch-request.json @@ -11,6 +11,5 @@ "timestamp": "2023-09-19T07:23:00.165Z" } ], - "timestamp": "2023-09-13T12:05:30.326Z", "sent_at": "2023-09-13T12:05:30.326Z" } diff --git a/posthog-v3/posthog/src/test/resources/json/capture.json b/posthog-v3/posthog/src/test/resources/json/capture.json new file mode 100644 index 00000000..b759a012 --- /dev/null +++ b/posthog-v3/posthog/src/test/resources/json/capture.json @@ -0,0 +1,36 @@ +{ + "event": "test", + "uuid": "7e4caf53-ef84-43d8-bd76-5c013a3613be", + "timestamp": "2023-09-20T11:58:49Z", + "properties": { + "$device_manufacturer": "Google", + "$os_version": "13", + "$screen_density": 2.625, + "$timezone": "Europe/Vienna", + "$locale": "en-US", + "$screen_width": 1080, + "$os_name": "Android", + "$screen_height": 2274, + "$user_agent": "Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.012)", + "$app_version": "1.0", + "$lib": "posthog-android", + "$device_name": "emu64a", + "$network_carrier": "T-Mobile", + "$device_id": "51432a27add1fd4b", + "$app_name": "My Application", + "$device_model": "sdk_gphone64_arm64", + "$lib_version": "version", + "$app_namespace": "com.posthog.myapplication", + "$app_build": "1", + "myProperty": "myValue", + "$feature/4535-funnel-bar-viz": true, + "$active_feature_flags": [ + "4535-funnel-bar-viz" + ], + "distinct_id": "my_identify", + "$groups": { + "company": "company_id_in_your_db" + } + }, + "distinct_id": "my_identify" +} diff --git a/posthog-v3/posthog/src/test/resources/json/decide-request.json b/posthog-v3/posthog/src/test/resources/json/decide-request.json index 764d6799..78354943 100644 --- a/posthog-v3/posthog/src/test/resources/json/decide-request.json +++ b/posthog-v3/posthog/src/test/resources/json/decide-request.json @@ -1,4 +1,14 @@ { - "distinct_id": "1fc77c1a-5f98-43b3-bb77-7a2dd15fd13a", - "api_key": "_6SG-F7I1vCuZ-HdJL3VZQqjBlaSb1_20hDPwqMNnGI" + "token": "_6SG-F7I1vCuZ-HdJL3VZQqjBlaSb1_20hDPwqMNnGI", + "distinct_id": "my_identify", + "$anon_distinct_id": "da84731c-8e43-4724-a996-3f9fab19936d", + "groups": { + + }, + "person_properties": { + + }, + "group_properties": { + + } } diff --git a/posthog-v3/posthog/src/test/resources/json/decide-response.json b/posthog-v3/posthog/src/test/resources/json/decide-response.json index 136e7e66..199447d4 100644 --- a/posthog-v3/posthog/src/test/resources/json/decide-response.json +++ b/posthog-v3/posthog/src/test/resources/json/decide-response.json @@ -1,26 +1,29 @@ { - "config": { - "enable_collect_everything": true - }, + "autocaptureExceptions": false, "toolbarParams": {}, + "errorsWhileComputingFlags": false, + "capturePerformance": true, + "autocapture_opt_out": false, "isAuthenticated": false, "supportedCompression": [ "gzip", "gzip-js" ], + "config": { + "enable_collect_everything": true + }, + "featureFlagPayloads": {}, "featureFlags": { "4535-funnel-bar-viz": true }, "sessionRecording": false, - "errorsWhileComputingFlags": false, - "featureFlagPayloads": {}, - "capturePerformance": true, - "autocapture_opt_out": false, - "autocaptureExceptions": false, "siteApps": [ { - "id": 21039, + "id": 21039.0, "url": "/site_app/21039/EOsOSePYNyTzHkZ3f4mjrjUap8Hy8o2vUTAc6v1ZMFP/576ac89bc8aed72a21d9b19221c2c626/" } - ] + ], + "editorParams": { + + } } diff --git a/posthog-v3/posthog/src/test/resources/json/group.json b/posthog-v3/posthog/src/test/resources/json/group.json new file mode 100644 index 00000000..591eb531 --- /dev/null +++ b/posthog-v3/posthog/src/test/resources/json/group.json @@ -0,0 +1,36 @@ +{ + "event": "$groupidentify", + "uuid": "25f24a61-0b25-4a70-a95e-d77f91607d40", + "timestamp": "2023-09-20T11:58:49Z", + "properties": { + "$device_manufacturer": "Google", + "$os_version": "13", + "$screen_density": 2.625, + "$timezone": "Europe/Vienna", + "$locale": "en-US", + "$screen_width": 1080, + "$os_name": "Android", + "$screen_height": 2274, + "$user_agent": "Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.012)", + "$app_version": "1.0", + "$lib": "posthog-android", + "$device_name": "emu64a", + "$network_carrier": "T-Mobile", + "$device_id": "51432a27add1fd4b", + "$app_name": "My Application", + "$device_model": "sdk_gphone64_arm64", + "$lib_version": "version", + "$app_namespace": "com.posthog.myapplication", + "$app_build": "1", + "$feature/4535-funnel-bar-viz": true, + "$active_feature_flags": [ + "4535-funnel-bar-viz" + ], + "$group_type": "the_type", + "$group_key": "the_key", + "$group_set": { + "myProperty": "myValue" + } + }, + "distinct_id": "my_identify" +} diff --git a/posthog-v3/posthog/src/test/resources/json/identify.json b/posthog-v3/posthog/src/test/resources/json/identify.json new file mode 100644 index 00000000..8a125f83 --- /dev/null +++ b/posthog-v3/posthog/src/test/resources/json/identify.json @@ -0,0 +1,35 @@ +{ + "event": "$identify", + "uuid": "cf5aa826-46b7-45d2-aae8-f22458284da1", + "timestamp": "2023-09-20T11:58:49Z", + "properties": { + "$device_manufacturer": "Google", + "$os_version": "13", + "$screen_density": 2.625, + "$timezone": "Europe/Vienna", + "$locale": "en-US", + "$screen_width": 1080, + "$os_name": "Android", + "$screen_height": 2274, + "$user_agent": "Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.012)", + "$app_version": "1.0", + "$lib": "posthog-android", + "$device_name": "emu64a", + "$network_carrier": "T-Mobile", + "$device_id": "51432a27add1fd4b", + "$app_name": "My Application", + "$device_model": "sdk_gphone64_arm64", + "$lib_version": "version", + "$app_namespace": "com.posthog.myapplication", + "$app_build": "1", + "$anon_distinct_id": "da84731c-8e43-4724-a996-3f9fab19936d", + "$feature/4535-funnel-bar-viz": true, + "$active_feature_flags": [ + "4535-funnel-bar-viz" + ], + "$set": { + "myProperty": "myValue" + } + }, + "distinct_id": "my_identif$sety" +} diff --git a/posthog-v3/posthog/src/test/resources/json/screen.json b/posthog-v3/posthog/src/test/resources/json/screen.json new file mode 100644 index 00000000..c36f503f --- /dev/null +++ b/posthog-v3/posthog/src/test/resources/json/screen.json @@ -0,0 +1,33 @@ +{ + "event": "$screen", + "uuid": "9cf74087-356a-41c3-9ff5-754ed31dc320", + "timestamp": "2023-09-20T11:59:31Z", + "properties": { + "$device_manufacturer": "Google", + "$os_version": "13", + "$screen_density": 2.625, + "$timezone": "Europe/Vienna", + "$locale": "en-US", + "$screen_width": 1080, + "$os_name": "Android", + "$screen_height": 2274, + "$user_agent": "Dalvik/2.1.0 (Linux; U; Android 13; sdk_gphone64_arm64 Build/TE1A.220922.012)", + "$app_version": "1.0", + "$lib": "posthog-android", + "$device_name": "emu64a", + "$network_carrier": "T-Mobile", + "$device_id": "51432a27add1fd4b", + "$app_name": "My Application", + "$device_model": "sdk_gphone64_arm64", + "$lib_version": "version", + "$app_namespace": "com.posthog.myapplication", + "$app_build": "1", + "myProperty": "myValue", + "$feature/4535-funnel-bar-viz": true, + "$active_feature_flags": [ + "4535-funnel-bar-viz" + ], + "$screen_name": "sreeenn" + }, + "distinct_id": "my_identify" +}