Skip to content

Commit

Permalink
add more integrations
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto committed Sep 21, 2023
1 parent e7d6cc1 commit a83e4f0
Show file tree
Hide file tree
Showing 17 changed files with 186 additions and 57 deletions.
5 changes: 5 additions & 0 deletions posthog-v3/posthog-android/api/posthog-android.api
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ 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/PostHogAndroidNetworkStatus : com/posthog/internal/PostHogNetworkStatus {
public fun <init> (Landroid/content/Context;)V
public fun isConnected ()Z
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.posthog.PostHogPrintLogger
import com.posthog.android.internal.PostHogActivityLifecycleCallback
import com.posthog.android.internal.PostHogAndroidContext
import com.posthog.android.internal.PostHogAndroidLogger
import com.posthog.android.internal.PostHogAndroidNetworkStatus
import com.posthog.android.internal.PostHogAppInstallIntegration
import com.posthog.android.internal.PostHogSharedPreferences
import com.posthog.android.internal.appContext
import java.io.File
Expand Down Expand Up @@ -37,11 +39,14 @@ public class PostHogAndroid private constructor() {
val path = File(context.cacheDir, "posthog-disk-queue")
config.legacyStoragePrefix = config.legacyStoragePrefix ?: legacyPath.absolutePath
config.storagePrefix = config.storagePrefix ?: path.absolutePath
config.preferences = config.preferences ?: PostHogSharedPreferences(context, config)
val preferences = config.preferences ?: PostHogSharedPreferences(context, config)
config.preferences = preferences
config.networkStatus = config.networkStatus ?: PostHogAndroidNetworkStatus(context)

if (context is Application) {
config.integrations.add(PostHogActivityLifecycleCallback(context))
}
config.integrations.add(PostHogAppInstallIntegration(context, config))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.posthog.android.internal

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.os.Build
import com.posthog.PostHogConfig
import com.posthog.PostHogContext
Expand All @@ -16,8 +19,7 @@ internal class PostHogAndroidContext(private val context: Context, private val c
staticContext["\$screen_height"] = displayMetrics.heightPixels
staticContext["\$screen_width"] = displayMetrics.widthPixels

val packageInfo = getPackageInfo(context, config)
packageInfo?.let {
getPackageInfo(context, config)?.let {
// TODO: check if we should use getApplicationInfo instead
it.applicationInfo?.loadLabel(context.packageManager)?.let { name ->
staticContext["\$app_name"] = name
Expand All @@ -35,11 +37,9 @@ internal class PostHogAndroidContext(private val context: Context, private val c
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["\$lib"] = config.sdkName
staticContext["\$lib_version"] = config.sdkVersion

staticContext
}
Expand All @@ -48,6 +48,7 @@ internal class PostHogAndroidContext(private val context: Context, private val c
return cacheStaticContext
}

@SuppressLint("MissingPermission")
override fun getDynamicContext(): Map<String, Any> {
val dynamicContext = mutableMapOf<String, Any>()
dynamicContext["\$locale"] = "${Locale.getDefault().language}-${Locale.getDefault().country}"
Expand All @@ -56,7 +57,24 @@ internal class PostHogAndroidContext(private val context: Context, private val c
}
dynamicContext["\$timezone"] = TimeZone.getDefault().id

// TODO: "$network_bluetooth", "$network_carrier","$network_cellular","$network_wifi"
context.connectivityManager()?.let { connectivityManager ->
// TODO: stop using getNetworkInfo
if (context.hasPermission(Manifest.permission.ACCESS_NETWORK_STATE)) {
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)?.let {
dynamicContext["\$network_wifi"] = it.isConnected
}
}
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_BLUETOOTH)?.let {
dynamicContext["\$network_bluetooth"] = it.isConnected
}
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)?.let {
dynamicContext["\$network_cellular"] = it.isConnected
}
}

context.telephonyManager()?.let {
dynamicContext["\$network_carrier"] = it.networkOperatorName
}

return dynamicContext
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.posthog.android.internal

import android.content.Context
import com.posthog.internal.PostHogNetworkStatus

public class PostHogAndroidNetworkStatus(private val context: Context) : PostHogNetworkStatus {
override fun isConnected(): Boolean {
return context.isConnected()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.posthog.android.internal

import android.content.Context
import com.posthog.PostHog
import com.posthog.PostHogConfig
import com.posthog.PostHogIntegration

internal class PostHogAppInstallIntegration(private val context: Context, private val config: PostHogConfig) : PostHogIntegration {
override fun install() {
getPackageInfo(context, config)?.let { packageInfo ->
config.preferences?.let { preferences ->
val versionName = packageInfo.versionName
val versionCode = packageInfo.versionCodeCompat()

val previousVersion = preferences.getValue("version") as? String
var previousBuild = preferences.getValue("build")

val event: String
val props = mutableMapOf<String, Any>()
if (previousBuild == null) {
event = "Application Installed"
} else {
event = "Application Updated"
previousVersion?.let {
props["previous_version"] = it
}
// to keep compatibility
if (previousBuild is Int) {
previousBuild = previousBuild.toLong()
}
props["previous_build"] = previousBuild
}
props["version"] = versionName
props["build"] = versionCode

preferences.setValue("version", versionName)
preferences.setValue("build", versionCode)

PostHog.capture(event, properties = props)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.posthog.android.internal

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.os.Build
import android.os.Process
import android.telephony.TelephonyManager
import android.util.DisplayMetrics
import com.posthog.PostHogConfig

Expand Down Expand Up @@ -36,21 +41,34 @@ internal fun PackageInfo.versionCodeCompat(): Long {
}
}

internal fun hasPermission(context: Context): Boolean {
return false
internal fun Context.displayMetrics(): DisplayMetrics {
return resources.displayMetrics
}
internal fun hasFeature(context: Context): Boolean {
return false

internal fun Context.appContext(): Context {
return applicationContext ?: this
}

internal fun isConnected(context: Context): Boolean {
return false
internal fun Context.hasPermission(permission: String): Boolean {
return checkPermission(permission, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED
}

internal fun Context.displayMetrics(): DisplayMetrics {
return resources.displayMetrics
@SuppressLint("MissingPermission")
internal fun Context.isConnected(): Boolean {
val connectivityManager = connectivityManager() ?: return true

if (!hasPermission(Manifest.permission.ACCESS_NETWORK_STATE)) {
return true
}
// TODO: stop using activeNetworkInfo
val networkInfo = connectivityManager.activeNetworkInfo ?: return false
return networkInfo.isConnected
}

internal fun Context.appContext(): Context {
return applicationContext ?: this
internal fun Context.connectivityManager(): ConnectivityManager? {
return getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
}

internal fun Context.telephonyManager(): TelephonyManager? {
return getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
}
13 changes: 9 additions & 4 deletions posthog-v3/posthog/api/posthog.api
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public final class com/posthog/PostHogConfig {
public final fun getContext ()Lcom/posthog/PostHogContext;
public final fun getDataMode ()Lcom/posthog/PostHogDataMode;
public final fun getDebug ()Z
public final fun getEnable ()Z
public final fun getEncryption ()Lcom/posthog/PostHogEncryption;
public final fun getFlushAt ()I
public final fun getFlushIntervalSeconds ()I
Expand All @@ -64,6 +63,8 @@ public final class com/posthog/PostHogConfig {
public final fun getLogger ()Lcom/posthog/PostHogLogger;
public final fun getMaxBatchSize ()I
public final fun getMaxQueueSize ()I
public final fun getNetworkStatus ()Lcom/posthog/internal/PostHogNetworkStatus;
public final fun getOptOut ()Z
public final fun getPreferences ()Lcom/posthog/PostHogPreferences;
public final fun getPreloadFeatureFlags ()Z
public final fun getSdkName ()Ljava/lang/String;
Expand All @@ -73,14 +74,15 @@ public final class com/posthog/PostHogConfig {
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 setEnable (Z)V
public final fun setEncryption (Lcom/posthog/PostHogEncryption;)V
public final fun setFlushAt (I)V
public final fun setFlushIntervalSeconds (I)V
public final fun setLegacyStoragePrefix (Ljava/lang/String;)V
public final fun setLogger (Lcom/posthog/PostHogLogger;)V
public final fun setMaxBatchSize (I)V
public final fun setMaxQueueSize (I)V
public final fun setNetworkStatus (Lcom/posthog/internal/PostHogNetworkStatus;)V
public final fun setOptOut (Z)V
public final fun setPreferences (Lcom/posthog/PostHogPreferences;)V
public final fun setPreloadFeatureFlags (Z)V
public final fun setSdkName (Ljava/lang/String;)V
Expand All @@ -101,8 +103,7 @@ public final class com/posthog/PostHogDataMode : java/lang/Enum {
public static fun values ()[Lcom/posthog/PostHogDataMode;
}

public abstract class com/posthog/PostHogEncryption {
public fun <init> ()V
public abstract interface class com/posthog/PostHogEncryption {
public abstract fun decrypt (Ljava/io/InputStream;)Ljava/io/InputStream;
public abstract fun encrypt (Ljava/io/OutputStream;)Ljava/io/OutputStream;
}
Expand Down Expand Up @@ -158,3 +159,7 @@ public final class com/posthog/PostHogPrintLogger : com/posthog/PostHogLogger {
public fun log (Ljava/lang/String;)V
}

public abstract interface class com/posthog/internal/PostHogNetworkStatus {
public abstract fun isConnected ()Z
}

33 changes: 17 additions & 16 deletions posthog-v3/posthog/src/main/java/com/posthog/PostHog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ public class PostHog private constructor() {
val queue = PostHogQueue(config, api, serializer)
val featureFlags = PostHogFeatureFlags(config, api)

val enable = config.preferences?.getValue("opt-out", defaultValue = config.enable) as? Boolean
enable?.let {
config.enable = enable
val optOut = config.preferences?.getValue("opt-out", defaultValue = false) as? Boolean
optOut?.let {
config.optOut = optOut
}

val sendCachedEventsIntegration = SendCachedEventsIntegration(config, api, serializer)
Expand Down Expand Up @@ -76,12 +76,12 @@ public class PostHog private constructor() {
}
}

public val anonymousId: String?
public val anonymousId: String
get() {
if (!isEnabled()) {
return null
return ""
}
return sessionManager?.anonymousId
return sessionManager?.anonymousId ?: ""
}

public val distinctId: String
Expand Down Expand Up @@ -131,7 +131,7 @@ public class PostHog private constructor() {
if (!isEnabled()) {
return
}
if (config?.enable == false) {
if (config?.optOut == true) {
config?.logger?.log("PostHog is in OptOut state.")
return
}
Expand All @@ -145,17 +145,17 @@ public class PostHog private constructor() {
return
}

config?.enable = true
config?.preferences?.setValue("opt-out", true)
config?.optOut = false
config?.preferences?.setValue("opt-out", false)
}

public fun optOut() {
if (!isEnabled()) {
return
}

config?.enable = false
config?.preferences?.setValue("opt-out", false)
config?.optOut = true
config?.preferences?.setValue("opt-out", true)
}

// public fun register(key: String, value: Any) {
Expand Down Expand Up @@ -202,9 +202,7 @@ public class PostHog private constructor() {
val oldDistinctId = this.distinctId

val props = mutableMapOf<String, Any>()
anonymousId?.let {
props["\$anon_distinct_id"] = it
}
props["\$anon_distinct_id"] = anonymousId
props["distinct_id"] = distinctId

properties?.let {
Expand Down Expand Up @@ -241,8 +239,11 @@ public class PostHog private constructor() {
}

private fun loadFeatureFlagsRequest() {
val map = mapOf<String, Any>()
featureFlags?.loadFeatureFlags(buildProperties(distinctId, map, null, null))
val props = mutableMapOf<String, Any>()
props["\$anon_distinct_id"] = anonymousId
props["distinct_id"] = distinctId

featureFlags?.loadFeatureFlags(buildProperties(distinctId, props, null, null))
}

public fun isFeatureEnabled(key: String, defaultValue: Boolean = false): Boolean {
Expand Down
9 changes: 6 additions & 3 deletions posthog-v3/posthog/src/main/java/com/posthog/PostHogConfig.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.posthog

// TODO: bootstrap
import com.posthog.internal.PostHogNetworkStatus

public class PostHogConfig(
// apiKey and host are immutable due to offline caching
public val apiKey: String,
public val host: String = "https://app.posthog.com",
public var debug: Boolean = false,
public var enable: Boolean = true,
public var optOut: Boolean = false,
public var sendFeatureFlagEvent: Boolean = true,
public var preloadFeatureFlags: Boolean = true,
// min. allowed is 1
Expand All @@ -18,7 +18,7 @@ public class PostHogConfig(
public var flushIntervalSeconds: Int = 30,

public var dataMode: PostHogDataMode = PostHogDataMode.ANY,
public var encryption: PostHogEncryption = PostHogEncryption.PostHogEncryptionNone(),
public var encryption: PostHogEncryption? = null,
public val integrations: MutableList<PostHogIntegration> = mutableListOf(),
) {
@PostHogInternal
Expand All @@ -45,4 +45,7 @@ public class PostHogConfig(

@PostHogInternal
public var preferences: PostHogPreferences? = null

@PostHogInternal
public var networkStatus: PostHogNetworkStatus? = null
}
Loading

0 comments on commit a83e4f0

Please sign in to comment.