Skip to content

Commit

Permalink
fix: do not allow default integrations multiple times (#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Jan 30, 2025
1 parent 9d0337b commit 958ee59
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 6 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
## Next

- fix: do not allow default integrations multiple times ([#219](https://github.com/PostHog/posthog-android/pull/219))

## 3.11.0 - 2025-01-27

- chore: Session Replay - GA
- fix: session replay and auto capture works with 'with' method ([#217](https://github.com/PostHog/posthog-flutter/pull/217))
- fix: sending cached events null check ([#218](https://github.com/PostHog/posthog-flutter/pull/218))
- fix: session replay and auto capture works with 'with' method ([#217](https://github.com/PostHog/posthog-android/pull/217))
- fix: sending cached events null check ([#218](https://github.com/PostHog/posthog-android/pull/218))

## 3.10.0 - 2025-01-07

- chore: change screenshots debouncing approach to throttling ([#214](https://github.com/PostHog/posthog-flutter/pull/214))
- chore: change screenshots debouncing approach to throttling ([#214](https://github.com/PostHog/posthog-android/pull/214))
- Added `throttleDelayMs` config and deprecated `debouncerDelayMs` config.
- chore: change screenshot image type from JPEG to WEBP ([#211](https://github.com/PostHog/posthog-android/pull/211))

Expand Down
13 changes: 12 additions & 1 deletion posthog-android/lint-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

<issue
id="GradleDependency"
message="A newer version of androidx.compose.ui:ui than 1.0.0 is available: 1.7.6"
message="A newer version of androidx.compose.ui:ui than 1.0.0 is available: 1.7.7"
errorLine1=" compileOnly(&quot;androidx.compose.ui:ui:${PosthogBuildConfig.Dependencies.ANDROIDX_COMPOSE}&quot;)"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
Expand All @@ -45,4 +45,15 @@
column="17"/>
</issue>

<issue
id="GradleDependency"
message="A newer version of org.jetbrains.kotlin:kotlin-test-junit than 1.8.22 is available: 1.9.20"
errorLine1=" testImplementation(&quot;org.jetbrains.kotlin:kotlin-test-junit:${PosthogBuildConfig.Kotlin.KOTLIN}&quot;)"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="build.gradle.kts"
line="108"
column="24"/>
</issue>

</issues>
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ public class PostHogAndroid private constructor() {

/**
* Setup the SDK and returns an instance that you can hold and pass it around
*
* All default PostHogIntegration's will only be installed for the very 1st instance,
* either that be created with the [setup] or [with] method otherwise they would race each other
* and cause issues, so the 1st instance of the SDK that is created on the hosting app
* will hold all installed integrations, the order of the setup matters.
*
* @param T the type of the Config
* @property context the Context
* @property config the Config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ internal class PostHogActivityLifecycleCallbackIntegration(
) : ActivityLifecycleCallbacks, PostHogIntegration {
private var postHog: PostHogInterface? = null

private companion object {
@Volatile
private var integrationInstalled = false
}

override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?,
Expand Down Expand Up @@ -79,12 +84,18 @@ internal class PostHogActivityLifecycleCallbackIntegration(
}

override fun install(postHog: PostHogInterface) {
if (integrationInstalled) {
return
}
integrationInstalled = true

this.postHog = postHog
application.registerActivityLifecycleCallbacks(this)
}

override fun uninstall() {
this.postHog = null
integrationInstalled = false
application.unregisterActivityLifecycleCallbacks(this)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ internal class PostHogAppInstallIntegration(
private val context: Context,
private val config: PostHogAndroidConfig,
) : PostHogIntegration {
private companion object {
@Volatile
private var integrationInstalled = false
}

override fun install(postHog: PostHogInterface) {
if (integrationInstalled) {
return
}
integrationInstalled = true

getPackageInfo(context, config)?.let { packageInfo ->
config.cachePreferences?.let { preferences ->
val versionName = packageInfo.versionName
Expand Down Expand Up @@ -56,4 +66,8 @@ internal class PostHogAppInstallIntegration(
}
}
}

override fun uninstall() {
integrationInstalled = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ internal class PostHogLifecycleObserverIntegration(
@JvmStatic
@Volatile
private var fromBackground = false

@Volatile
private var integrationInstalled = false
}

override fun onStart(owner: LifecycleOwner) {
Expand Down Expand Up @@ -109,6 +112,11 @@ internal class PostHogLifecycleObserverIntegration(
}

override fun install(postHog: PostHogInterface) {
if (integrationInstalled) {
return
}
integrationInstalled = true

try {
this.postHog = postHog
if (isMainThread(mainHandler)) {
Expand All @@ -129,6 +137,7 @@ internal class PostHogLifecycleObserverIntegration(

override fun uninstall() {
try {
integrationInstalled = false
this.postHog = null
if (isMainThread(mainHandler)) {
remove()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,10 @@ public class PostHogReplayIntegration(
}

override fun install(postHog: PostHogInterface) {
if (!isSupported()) {
if (integrationInstalled || !isSupported()) {
return
}
integrationInstalled = true
this.postHog = postHog

// workaround for react native that is started after the window is added
Expand All @@ -334,6 +335,7 @@ public class PostHogReplayIntegration(

override fun uninstall() {
try {
integrationInstalled = false
this.postHog = null
Curtains.onRootViewsChangedListeners -= onRootViewsChangedListener

Expand Down Expand Up @@ -1272,5 +1274,8 @@ public class PostHogReplayIntegration(
const val PH_NO_CAPTURE_LABEL: String = "ph-no-capture"
const val ANDROID_COMPOSE_VIEW_CLASS_NAME: String = "androidx.compose.ui.platform.AndroidComposeView"
const val ANDROID_COMPOSE_VIEW: String = "AndroidComposeView"

@Volatile
private var integrationInstalled = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ internal class PostHogLogCatIntegration(private val config: PostHogAndroidConfig

private var postHog: PostHogInterface? = null

private companion object {
@Volatile
private var integrationInstalled = false
}

override fun install(postHog: PostHogInterface) {
if (!config.sessionReplayConfig.captureLogcat || !isSupported()) {
if (integrationInstalled || !config.sessionReplayConfig.captureLogcat || !isSupported()) {
return
}
integrationInstalled = true
this.postHog = postHog
val cmd = mutableListOf("logcat", "-v", "threadtime", "*:E")
val sdf = SimpleDateFormat("MM-dd HH:mm:ss.mmm", Locale.ROOT)
Expand Down Expand Up @@ -90,6 +96,7 @@ internal class PostHogLogCatIntegration(private val config: PostHogAndroidConfig
}

override fun uninstall() {
integrationInstalled = false
this.postHog = null
logcatInProgress = false
logcatThread?.interruptSafely()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {
sut.install(fake)

verify(application).registerActivityLifecycleCallbacks(any())

sut.uninstall()
}

@Test
Expand All @@ -70,6 +72,8 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {

sut.install(fake)
sut.onActivityCreated(activity, null)
sut.uninstall()

return fake
}

Expand All @@ -84,6 +88,8 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {

sut.install(fake)
sut.onActivityCreated(activity, null)
sut.uninstall()

return fake
}

Expand Down Expand Up @@ -164,6 +170,8 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {

sut.install(fake)
sut.onActivityStarted(activity)
sut.uninstall()

return fake
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ internal class PostHogAppInstallIntegrationTest {
assertEquals("Application Installed", fake.event)
assertEquals("1.0.0", fake.properties?.get("version"))
assertEquals(1L, fake.properties?.get("build"))

sut.uninstall()
}

@Test
Expand All @@ -58,13 +60,16 @@ internal class PostHogAppInstallIntegrationTest {

context.mockPackageInfo("2.0.0", 2)

sut.uninstall()
sut.install(fake)

assertEquals("Application Updated", fake.event)
assertEquals("1.0.0", fake.properties?.get("previous_version"))
assertEquals(1L, fake.properties?.get("previous_build"))
assertEquals("2.0.0", fake.properties?.get("version"))
assertEquals(2L, fake.properties?.get("build"))

sut.uninstall()
}

@Test
Expand All @@ -79,9 +84,12 @@ internal class PostHogAppInstallIntegrationTest {

assertEquals(1, fake.captures)

sut.uninstall()
sut.install(fake)

// sanity check
assertEquals(1, fake.captures)

sut.uninstall()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ internal class PostHogLifecycleObserverIntegrationTest {
sut.install(fake)

assertEquals(1, fakeLifecycle.observers)

sut.uninstall()
}

@Test
Expand Down Expand Up @@ -69,6 +71,8 @@ internal class PostHogLifecycleObserverIntegrationTest {
assertEquals("1.0.0", fake.properties?.get("version"))
assertEquals(1L, fake.properties?.get("build"))
assertEquals(false, fake.properties?.get("from_background"))

sut.uninstall()
}

@Test
Expand All @@ -84,6 +88,8 @@ internal class PostHogLifecycleObserverIntegrationTest {

assertEquals("Application Opened", fake.event)
assertEquals(true, fake.properties?.get("from_background"))

sut.uninstall()
}

@Test
Expand All @@ -97,5 +103,7 @@ internal class PostHogLifecycleObserverIntegrationTest {
sut.onStop(ProcessLifecycleOwner.get())

assertEquals("Application Backgrounded", fake.event)

sut.uninstall()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ internal class PostHogSendCachedEventsIntegration(
private val startDate: Date,
private val executor: ExecutorService,
) : PostHogIntegration {
private companion object {
@Volatile
private var integrationInstalled = false
}

override fun install(postHog: PostHogInterface) {
if (integrationInstalled) {
return
}
integrationInstalled = true

executor.executeSafely {
if (config.networkStatus?.isConnected() == false) {
config.logger.log("Network isn't connected.")
Expand Down Expand Up @@ -216,4 +226,8 @@ internal class PostHogSendCachedEventsIntegration(
}
}
}

override fun uninstall() {
integrationInstalled = false
}
}
Loading

0 comments on commit 958ee59

Please sign in to comment.