diff --git a/.gitignore b/.gitignore index eb3925bb..9b8c9409 100644 --- a/.gitignore +++ b/.gitignore @@ -152,4 +152,7 @@ build/ gradle-app.setting # Jacoco -/posthog/jacoco.exec \ No newline at end of file +/posthog/jacoco.exec + +# eclipse +.project/ diff --git a/.project b/.project deleted file mode 100644 index a0ebd26e..00000000 --- a/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - posthog-android - Project posthog-android created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - 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 new file mode 100644 index 00000000..cec2c8ea --- /dev/null +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogActivityLifecycleCallback.kt @@ -0,0 +1,6 @@ +package com.posthog.android.internal + +// ActivityLifecycleCallbacks, IntegrationOperation, PostHogActivityLifecycleCallbacks +internal class PostHogActivityLifecycleCallback { + // TODO: lifecycle events, deeplinks, record screen views +} \ No newline at end of file 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 new file mode 100644 index 00000000..1a5af7ac --- /dev/null +++ b/posthog-v3/posthog-android/src/main/java/com/posthog/android/internal/PostHogAdvertisingIdReader.kt @@ -0,0 +1,5 @@ +package com.posthog.android.internal + +// GetAdvertisingIdTask +class PostHogAdvertisingIdReader { +} \ No newline at end of file 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 c4c2965d..5cfdd24a 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt @@ -79,6 +79,7 @@ public class PostHog { properties?.let { props.putAll(it) } + // TODO: message_id=messageId // distinctId is always present but it has to be nullable because the SDK may be disabled // TODO: missing static, dynamic context @@ -136,6 +137,7 @@ public class PostHog { // TODO: reset feature flags, set anonymousId and distinctId // val oldDistinctId = this.distinctId + // TODO: userProperties val props = mutableMapOf() props["distinct_id"] = distinctId @@ -156,6 +158,7 @@ public class PostHog { if (!isEnabled()) { return } + // TODO: groupProperties, event $groupidentify } public fun reloadFeatureFlagsRequest() { @@ -265,5 +268,6 @@ public class PostHog { } // TODO: add other methods + // TODO: is Stats a feature or just used by tests in posthog-android } } 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 50cd1593..162710ce 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt @@ -14,6 +14,7 @@ public class PostHogConfig( public var flushIntervalSeconds: Int = 30, public var dataMode: PostHogDataMode = PostHogDataMode.ANY, + public var encryption: PostHogEncryption = PostHogEncryption.PostHogEncryptionNone() ) { internal var logger: PostHogLogger? = null diff --git a/posthog-v3/posthog/src/main/java/com/posthog/PostHogEncryption.kt b/posthog-v3/posthog/src/main/java/com/posthog/PostHogEncryption.kt new file mode 100644 index 00000000..dca6fe09 --- /dev/null +++ b/posthog-v3/posthog/src/main/java/com/posthog/PostHogEncryption.kt @@ -0,0 +1,21 @@ +package com.posthog + +import java.io.InputStream +import java.io.OutputStream + +public abstract class PostHogEncryption { + public abstract fun decrypt(inputStream: InputStream): InputStream + + public abstract fun encrypt(outputStream: OutputStream): OutputStream + + internal class PostHogEncryptionNone : PostHogEncryption() { + override fun decrypt(inputStream: InputStream): InputStream { + return inputStream + } + + override fun encrypt(outputStream: OutputStream): OutputStream { + return outputStream + } + + } +} 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 eaa6fe8e..e51761f8 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 @@ -21,10 +21,13 @@ internal class PostHogApi(private val config: PostHogConfig) { private val mediaType = "application/json; charset=utf-8".toMediaType() private val gson = GsonBuilder().apply { registerTypeAdapter(Date::class.java, GsonDateTypeAdapter(config)) + .setLenient() }.create() private val gsonBatchBodyType = object : TypeToken() {}.type private val gsonDecideBodyType = object : TypeToken>() {}.type + // TODO: do we care about max queue size? apparently theres a 500kb hardlimit on the server + fun batch(events: List) { val batch = PostHogBatchEvent(config.apiKey, events) // """ @@ -39,11 +42,15 @@ internal class PostHogApi(private val config: PostHogConfig) { // "timestamp": "2023-09-13T12:05:30.326Z" // } // ], -// "timestamp": "2023-09-13T12:05:30.326Z" +// "timestamp": "2023-09-13T12:05:30.326Z", +// "sent_at": "2023-09-13T12:05:30.326Z", // } // """.trimIndent() val request = makeRequest("${config.host}/batch") { - gson.toJson(batch, gsonBatchBodyType, it.bufferedWriter()) + val writer = it.bufferedWriter() + batch.sentAt = Date() + gson.toJson(batch, gsonBatchBodyType, writer) + writer.flush() } client.newCall(request).execute().use { @@ -89,6 +96,7 @@ internal class PostHogApi(private val config: PostHogConfig) { } client.newCall(request).execute().use { + // TODO: do we handle 429 differently? if (!it.isSuccessful) throw PostHogApiError(it.code, it.message, body = it.body) it.body?.let { body -> 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 85187205..26a73ecd 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 @@ -9,4 +9,6 @@ internal data class PostHogBatchEvent( 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/PostHogStorage.kt b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt index 2a8d4f1c..bd209d6f 100644 --- a/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt +++ b/posthog-v3/posthog/src/main/java/com/posthog/internal/PostHogStorage.kt @@ -4,6 +4,11 @@ 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 + // 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()