diff --git a/posthog-v3/posthog-android/api/posthog-android.api b/posthog-v3/posthog-android/api/posthog-android.api index ca6c5b94..9bd82203 100644 --- a/posthog-v3/posthog-android/api/posthog-android.api +++ b/posthog-v3/posthog-android/api/posthog-android.api @@ -8,12 +8,3 @@ public final class com/posthog/android/PostHogAndroid$Companion { public final fun with (Landroid/content/Context;Lcom/posthog/PostHogConfig;)Lcom/posthog/PostHog; } -public final class com/posthog/android/internal/PostHogAdvertisingIdReader { - public fun ()V -} - -public final class com/posthog/android/internal/PostHogUtilsKt { - public static final fun getPackageInfo (Landroid/content/Context;Lcom/posthog/PostHogConfig;)Landroid/content/pm/PackageInfo; - public static final fun getVersionCode (Landroid/content/pm/PackageInfo;)J -} - diff --git a/posthog-v3/posthog-android/build.gradle.kts b/posthog-v3/posthog-android/build.gradle.kts index 9227e9b2..3df14faf 100644 --- a/posthog-v3/posthog-android/build.gradle.kts +++ b/posthog-v3/posthog-android/build.gradle.kts @@ -28,6 +28,8 @@ android { kotlinOptions { jvmTarget = PosthogBuildConfig.Build.JAVA_VERSION.toString() kotlinOptions.languageVersion = PosthogBuildConfig.Kotlin.KOTLIN_COMPATIBILITY + // remove when https://youtrack.jetbrains.com/issue/KT-37652 is fixed + freeCompilerArgs += "-Xexplicit-api=strict" } testOptions { @@ -47,6 +49,8 @@ android { } } +// See https://youtrack.jetbrains.com/issue/KT-37652 +// Also see kotlinOptions.freeCompilerArgs kotlin { explicitApi() } 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 623fcb9c..12cdc7cf 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 @@ -1,24 +1,42 @@ package com.posthog.android +import android.app.Application import android.content.Context import com.posthog.PostHog import com.posthog.PostHogConfig -import com.posthog.android.internal.PostHogLogger +import com.posthog.PostHogPrintLogger +import com.posthog.android.internal.PostHogActivityLifecycleCallback +import com.posthog.android.internal.PostHogAndroidContext +import com.posthog.android.internal.PostHogAndroidLogger public class PostHogAndroid { - companion object { + public companion object { private val lock = Any() public fun setup(context: Context, config: PostHogConfig) { synchronized(lock) { - config.logger = PostHogLogger(config) + setAndroidConfig(context.appContext(), config) + PostHog.setup(config) } } public fun with(context: Context, config: PostHogConfig): PostHog { - config.logger = PostHogLogger(config) + setAndroidConfig(context.appContext(), config) return PostHog.with(config) } + + 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) + + if (context is Application) { + 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/PostHogActivityLifecycleCallback.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogActivityLifecycleCallback.kt index b2a386d7..ad4b0259 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogActivityLifecycleCallback.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogActivityLifecycleCallback.kt @@ -1,6 +1,40 @@ package com.posthog.android.internal +import android.app.Activity +import android.app.Application +import android.app.Application.ActivityLifecycleCallbacks +import android.os.Bundle +import com.posthog.PostHogIntegration + // ActivityLifecycleCallbacks, IntegrationOperation, PostHogActivityLifecycleCallbacks -internal class PostHogActivityLifecycleCallback { +internal class PostHogActivityLifecycleCallback(private val application: Application) : ActivityLifecycleCallbacks, PostHogIntegration { // TODO: lifecycle events, deeplinks, record screen views + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + } + + override fun onActivityStarted(activity: Activity) { + } + + override fun onActivityResumed(activity: Activity) { + } + + override fun onActivityPaused(activity: Activity) { + } + + override fun onActivityStopped(activity: Activity) { + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + } + + override fun onActivityDestroyed(activity: Activity) { + } + + override fun install() { + application.registerActivityLifecycleCallbacks(this) + } + + override fun uninstall() { + application.unregisterActivityLifecycleCallbacks(this) + } } diff --git a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAdvertisingIdReader.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAdvertisingIdReader.kt index 8bfc580c..b7f9dabd 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAdvertisingIdReader.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAdvertisingIdReader.kt @@ -1,4 +1,19 @@ package com.posthog.android.internal -// GetAdvertisingIdTask -class PostHogAdvertisingIdReader +import android.content.Context + +// GetAdvertisingIdTask, Utils +internal class PostHogAdvertisingIdReader(context: Context) { + fun getGooglePlayServicesAdvertisingID(): Pair? { + return null + } + + fun getAmazonFireAdvertisingID(): Pair? { + return null + } + + fun getDeviceId(): String? { + // TODO depends on DEFAULT_COLLECT_DEVICE_ID + return null + } +} 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 new file mode 100644 index 00000000..2aea2fa9 --- /dev/null +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidContext.kt @@ -0,0 +1,16 @@ +package com.posthog.android.internal + +import android.content.Context +import com.posthog.PostHogContext + +// PostHogContext + +internal class PostHogAndroidContext(context: Context) : PostHogContext { + override fun getStaticContext(): Map? { + return null + } + + override fun getDynamicContext(): Map? { + return null + } +} diff --git a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogLogger.kt b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidLogger.kt similarity index 74% rename from posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogLogger.kt rename to posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidLogger.kt index 3bfac86d..1b2f92cc 100644 --- a/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogLogger.kt +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAndroidLogger.kt @@ -4,7 +4,7 @@ import android.util.Log import com.posthog.PostHogConfig import com.posthog.PostHogLogger -internal class PostHogLogger(private val config: PostHogConfig) : PostHogLogger { +internal class PostHogAndroidLogger(private val config: PostHogConfig) : PostHogLogger { override fun log(message: String) { if (config.debug) { Log.println(Log.DEBUG, null, message) 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 dd2f6a32..f2385b9f 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 @@ -6,7 +6,7 @@ import android.content.pm.PackageManager import android.os.Build import com.posthog.PostHogConfig -fun getPackageInfo( +internal fun getPackageInfo( context: Context, config: PostHogConfig, ): PackageInfo? { @@ -27,10 +27,21 @@ fun getPackageInfo( } } -fun getVersionCode(packageInfo: PackageInfo): Long { +internal fun getVersionCode(packageInfo: PackageInfo): Long { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { packageInfo.longVersionCode } else { packageInfo.versionCode.toLong() } } + +internal fun hasPermission(context: Context): Boolean { + return false +} +internal fun hasFeature(context: Context): Boolean { + return false +} + +internal fun isConnected(context: Context): Boolean { + return false +} diff --git a/posthog-v3/posthog/api/posthog.api b/posthog-v3/posthog/api/posthog.api index 9f6af9cd..1c5bee11 100644 --- a/posthog-v3/posthog/api/posthog.api +++ b/posthog-v3/posthog/api/posthog.api @@ -43,18 +43,21 @@ public final class com/posthog/PostHog$Companion { } public final class com/posthog/PostHogConfig { - public fun (Ljava/lang/String;Ljava/lang/String;ZIIIILcom/posthog/PostHogDataMode;Lcom/posthog/PostHogEncryption;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;ZIIIILcom/posthog/PostHogDataMode;Lcom/posthog/PostHogEncryption;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/String;ZIIIILcom/posthog/PostHogDataMode;Lcom/posthog/PostHogEncryption;Ljava/util/List;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;ZIIIILcom/posthog/PostHogDataMode;Lcom/posthog/PostHogEncryption;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getApiKey ()Ljava/lang/String; + public final fun getContext ()Lcom/posthog/PostHogContext; public final fun getDataMode ()Lcom/posthog/PostHogDataMode; public final fun getDebug ()Z public final fun getEncryption ()Lcom/posthog/PostHogEncryption; public final fun getFlushAt ()I public final fun getFlushIntervalSeconds ()I public final fun getHost ()Ljava/lang/String; + public final fun getIntegrations ()Ljava/util/List; public final fun getLogger ()Lcom/posthog/PostHogLogger; public final fun getMaxBatchSize ()I public final fun getMaxQueueSize ()I + public final fun setContext (Lcom/posthog/PostHogContext;)V public final fun setDataMode (Lcom/posthog/PostHogDataMode;)V public final fun setDebug (Z)V public final fun setEncryption (Lcom/posthog/PostHogEncryption;)V @@ -65,6 +68,11 @@ public final class com/posthog/PostHogConfig { public final fun setMaxQueueSize (I)V } +public abstract interface class com/posthog/PostHogContext { + public abstract fun getDynamicContext ()Ljava/util/Map; + public abstract fun getStaticContext ()Ljava/util/Map; +} + public final class com/posthog/PostHogDataMode : java/lang/Enum { public static final field ANY Lcom/posthog/PostHogDataMode; public static final field WIFI Lcom/posthog/PostHogDataMode; @@ -94,7 +102,24 @@ public final class com/posthog/PostHogEvent { public fun toString ()Ljava/lang/String; } +public abstract interface class com/posthog/PostHogIntegration { + public abstract fun install ()V + public abstract fun uninstall ()V +} + +public final class com/posthog/PostHogIntegration$DefaultImpls { + public static fun uninstall (Lcom/posthog/PostHogIntegration;)V +} + public abstract interface class com/posthog/PostHogLogger { public abstract fun log (Ljava/lang/String;)V } +public abstract interface class com/posthog/PostHogPreferences { +} + +public final class com/posthog/PostHogPrintLogger : com/posthog/PostHogLogger { + public fun (Lcom/posthog/PostHogConfig;)V + public fun log (Ljava/lang/String;)V +} + 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 b4fc99fb..2a67f2f6 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt @@ -18,6 +18,7 @@ public class PostHog { private var featureFlags: PostHogFeatureFlags? = null private var api: PostHogApi? = null private var queue: PostHogQueue? = null + private var context: PostHogContext? = null // TODO: flushTimer, reachability, flagCallReported @@ -41,6 +42,10 @@ public class PostHog { this.featureFlags = featureFlags enabled = true + config.integrations.forEach { + it.install() + } + queue.start() loadFeatureFlagsRequest() } @@ -49,6 +54,11 @@ public class PostHog { public fun close() { synchronized(lock) { enabled = false + + config?.integrations?.forEach { + it.uninstall() + } + queue?.stop() } } @@ -79,6 +89,14 @@ public class PostHog { // distinctId is always present but it has to be nullable because the SDK may be disabled // TODO: missing static, dynamic context + context?.getStaticContext()?.let { + props.putAll(it) + } + + context?.getDynamicContext()?.let { + props.putAll(it) + } + distinctId?.let { props["distinct_id"] = it } @@ -264,5 +282,7 @@ public class PostHog { } // TODO: add other methods + + // DISCUSS: Middleware, what does it stand for? } } 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 c4c281f7..c5029071 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt @@ -1,7 +1,5 @@ package com.posthog -import com.posthog.internal.PostHogPrintLogger - public class PostHogConfig( // apiKey and host are immutable due to offline caching public val apiKey: String, @@ -15,8 +13,10 @@ public class PostHogConfig( public var dataMode: PostHogDataMode = PostHogDataMode.ANY, public var encryption: PostHogEncryption = PostHogEncryption.PostHogEncryptionNone(), + public val integrations: MutableList = mutableListOf(), ) { public var logger: PostHogLogger = PostHogPrintLogger(this) + public var context: PostHogContext? = null // TODO: read the repo name and version internal var userAgent: String = "posthog-android/3.0.0" diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt new file mode 100644 index 00000000..2b5f778c --- /dev/null +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogContext.kt @@ -0,0 +1,7 @@ +package com.posthog + +public interface PostHogContext { + public fun getStaticContext(): Map? + + public fun getDynamicContext(): Map? +} diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogIntegration.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogIntegration.kt new file mode 100644 index 00000000..b9c7981a --- /dev/null +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogIntegration.kt @@ -0,0 +1,8 @@ +package com.posthog + +public interface PostHogIntegration { + public fun install() + + public fun uninstall() { + } +} diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogPreferences.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogPreferences.kt new file mode 100644 index 00000000..0c2bfc2a --- /dev/null +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogPreferences.kt @@ -0,0 +1,4 @@ +package com.posthog + +// Properties +public interface PostHogPreferences diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogPrintLogger.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogPrintLogger.kt new file mode 100644 index 00000000..d2a95dbc --- /dev/null +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogPrintLogger.kt @@ -0,0 +1,10 @@ +package com.posthog + +public class PostHogPrintLogger(private val config: PostHogConfig) : PostHogLogger { + override fun log(message: String) { + if (!config.debug) { + return + } + println(message) + } +} diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogApi.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogApi.kt index e51761f8..d1001a2b 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogApi.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogApi.kt @@ -13,6 +13,7 @@ import java.io.OutputStream import java.util.Date internal class PostHogApi(private val config: PostHogConfig) { + // TODO: DEFAULT_READ_TIMEOUT_MILLIS, DEFAULT_CONNECT_TIMEOUT_MILLIS private val client = OkHttpClient.Builder() .addInterceptor(GzipRequestInterceptor(config)) .build() @@ -46,6 +47,7 @@ internal class PostHogApi(private val config: PostHogConfig) { // "sent_at": "2023-09-13T12:05:30.326Z", // } // """.trimIndent() + // TODO: MAX_PAYLOAD_SIZE, MAX_BATCH_SIZE val request = makeRequest("${config.host}/batch") { val writer = it.bufferedWriter() batch.sentAt = Date() diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogFeatureFlags.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogFeatureFlags.kt index 170c9bb2..19b16c18 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogFeatureFlags.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogFeatureFlags.kt @@ -4,6 +4,8 @@ import com.posthog.PostHogConfig import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicBoolean +// TODO: ENABLED_FEATURE_FLAGS_KEY + internal class PostHogFeatureFlags(private val config: PostHogConfig, private val api: PostHogApi) { private val executor = Executors.newSingleThreadScheduledExecutor(PostHogThreadFactory("PostHogDecideThread")) diff --git a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogPrintLogger.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogPrintLogger.kt deleted file mode 100644 index eaafc8dc..00000000 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogPrintLogger.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.posthog.internal - -import com.posthog.PostHogConfig -import com.posthog.PostHogLogger - -internal class PostHogPrintLogger(private val config: PostHogConfig) : PostHogLogger { - override fun log(message: String) { - if (!config.debug) { - return - } - println(message) - } -}