Skip to content

Commit 69254e0

Browse files
[CHNL-12435] Adding new lifecycle listener function (#241)
* [CHNL-12435] Adding new lifecycle listener function * Readme recc Co-authored-by: Evan Masseau <> * brackets to link init function --------- Co-authored-by: Evan C Masseau <5167687+evan-masseau@users.noreply.github.com>
1 parent 301a122 commit 69254e0

File tree

3 files changed

+87
-8
lines changed

3 files changed

+87
-8
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@ persist data. Upon initialize, the SDK registers listeners for your application'
8484
to gracefully manage background processes.
8585

8686
`Klaviyo.initialize()` **must** be called before any other SDK methods can be invoked. We recommend initializing from
87-
the earliest point in your application code, such as the `Application.onCreate()` method.
87+
the earliest point in your application code, the `Application.onCreate()` method.
88+
89+
**Note:** If you are unable to `Application.onCreate()` (e.g. if your API key is dynamic and not yet available) you
90+
**must** call `Klaviyo.registerForLifecycleCallbacks(applicationContext)` and provide your API key via `initialize`
91+
as early as it is available.
8892

8993
```kotlin
9094
// Application subclass
@@ -99,6 +103,9 @@ class YourApplication : Application() {
99103

100104
// Initialize is required before invoking any other Klaviyo SDK functionality
101105
Klaviyo.initialize("KLAVIYO_PUBLIC_API_KEY", applicationContext)
106+
107+
// If unable to call initialize, you must at least register lifecycle listeners:
108+
Klaviyo.registerForLifecycleCallbacks(applicationContext)
102109
}
103110
}
104111
```

sdk/analytics/src/main/java/com/klaviyo/analytics/Klaviyo.kt

+18-7
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,23 @@ object Klaviyo {
4545
if (!Registry.isRegistered<ApiClient>()) Registry.register<ApiClient> { KlaviyoApiClient }
4646
}
4747

48+
/**
49+
* Use this method to register Klaviyo for lifecycle functions. This is necessary for
50+
* apps that are not able to [initialize] Klaviyo immediately on app launch, but would like to
51+
* utilize Klaviyo Forms
52+
*
53+
* @param applicationContext
54+
*/
55+
fun registerForLifecycleCallbacks(applicationContext: Context) = safeApply {
56+
val application = applicationContext.applicationContext as? Application
57+
application?.apply {
58+
unregisterActivityLifecycleCallbacks(Registry.lifecycleCallbacks)
59+
unregisterComponentCallbacks(Registry.componentCallbacks)
60+
registerActivityLifecycleCallbacks(Registry.lifecycleCallbacks)
61+
registerComponentCallbacks(Registry.componentCallbacks)
62+
} ?: throw LifecycleException()
63+
}
64+
4865
/**
4966
* Configure Klaviyo SDK with your account's public API Key and application context.
5067
* This must be called to before using any other SDK functionality
@@ -60,13 +77,7 @@ object Klaviyo {
6077
.build()
6178
)
6279

63-
val application = applicationContext.applicationContext as? Application
64-
application?.apply {
65-
unregisterActivityLifecycleCallbacks(Registry.lifecycleCallbacks)
66-
unregisterComponentCallbacks(Registry.componentCallbacks)
67-
registerActivityLifecycleCallbacks(Registry.lifecycleCallbacks)
68-
registerComponentCallbacks(Registry.componentCallbacks)
69-
} ?: throw LifecycleException()
80+
registerForLifecycleCallbacks(applicationContext)
7081

7182
Registry.get<ApiClient>().startService()
7283

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.klaviyo.analytics
2+
3+
import android.app.Application
4+
import com.klaviyo.core.Registry
5+
import com.klaviyo.core.config.Config
6+
import com.klaviyo.fixtures.BaseTest
7+
import io.mockk.every
8+
import io.mockk.mockk
9+
import io.mockk.verify
10+
import io.mockk.verifyAll
11+
import org.junit.Test
12+
13+
internal class KlaviyoRegisterForLifecycleCallbacksTest : BaseTest() {
14+
15+
private val mockBuilder = mockk<Config.Builder>().apply {
16+
every { apiKey(any()) } returns this
17+
every { applicationContext(any()) } returns this
18+
every { build() } returns mockConfig
19+
}
20+
21+
private val mockApplicationContext = mockk<Application> {
22+
every { applicationContext } returns mockk()
23+
every { unregisterActivityLifecycleCallbacks(any()) } returns Unit
24+
every { unregisterComponentCallbacks(any()) } returns Unit
25+
every { registerActivityLifecycleCallbacks(any()) } returns Unit
26+
every { registerComponentCallbacks(any()) } returns Unit
27+
}
28+
29+
private val mockApplication = mockk<Application>().apply {
30+
every { applicationContext } returns mockApplicationContext
31+
}
32+
33+
@Test
34+
fun `check that lifecycle register function does not touch api key dependent functions`() {
35+
val expectedListener = Registry.lifecycleCallbacks
36+
val expectedConfigListener = Registry.componentCallbacks
37+
38+
Klaviyo.registerForLifecycleCallbacks(mockApplication)
39+
40+
verifyAll {
41+
mockApplicationContext.unregisterActivityLifecycleCallbacks(
42+
match { it == expectedListener }
43+
)
44+
mockApplicationContext.registerActivityLifecycleCallbacks(
45+
match { it == expectedListener }
46+
)
47+
mockApplicationContext.unregisterComponentCallbacks(
48+
match { it == expectedConfigListener }
49+
)
50+
mockApplicationContext.registerComponentCallbacks(
51+
match { it == expectedConfigListener }
52+
)
53+
}
54+
55+
verify(exactly = 0) {
56+
mockBuilder.apiKey(any())
57+
mockBuilder.applicationContext(any())
58+
mockBuilder.build()
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)