Skip to content

Commit

Permalink
feat: automatic screen tracking (customerio#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shahroz16 committed Dec 15, 2021
1 parent 5da4399 commit 8f95ebb
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 6 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
tools:targetApi="m">
<activity
android:name="io.customer.example.MainActivity"
android:label="Home"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
53 changes: 49 additions & 4 deletions sdk/src/main/java/io/customer/sdk/CustomerIO.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package io.customer.sdk

import android.content.Context
import android.app.Activity
import android.app.Application
import android.content.pm.PackageManager
import io.customer.base.comunication.Action
import io.customer.base.data.ErrorResult
import io.customer.base.error.ErrorDetail
import io.customer.base.utils.ActionUtils
import io.customer.sdk.api.CustomerIOApi
import io.customer.sdk.data.communication.CustomerIOUrlHandler
import io.customer.sdk.data.model.Region
Expand Down Expand Up @@ -41,10 +46,13 @@ class CustomerIO internal constructor(
private val siteId: String,
private val apiKey: String,
private var region: Region = Region.US,
private val appContext: Context
private val appContext: Application
) {
private var timeout = 6000L
private var urlHandler: CustomerIOUrlHandler? = null
private var shouldAutoRecordScreenViews: Boolean = false

private lateinit var activityLifecycleCallback: CustomerIOActivityLifecycleCallbacks

fun setRegion(region: Region): Builder {
this.region = region
Expand All @@ -56,6 +64,11 @@ class CustomerIO internal constructor(
return this
}

fun autoTrackScreenViews(shouldRecordScreenViews: Boolean): Builder {
this.shouldAutoRecordScreenViews = shouldRecordScreenViews
return this
}

/**
* Override url/deep link handling
*
Expand All @@ -81,7 +94,8 @@ class CustomerIO internal constructor(
apiKey = apiKey,
region = region,
timeout = timeout,
urlHandler = urlHandler
urlHandler = urlHandler,
autoTrackScreenViews = shouldAutoRecordScreenViews
)

val customerIoComponent =
Expand All @@ -90,8 +104,12 @@ class CustomerIO internal constructor(
val client = CustomerIO(
config = config,
store = customerIoComponent.buildStore(),
api = customerIoComponent.buildApi()
api = customerIoComponent.buildApi(),
)

activityLifecycleCallback = CustomerIOActivityLifecycleCallbacks(client)
appContext.registerActivityLifecycleCallbacks(activityLifecycleCallback)

instance = client
return client
}
Expand Down Expand Up @@ -141,6 +159,18 @@ class CustomerIO internal constructor(
attributes: Map<String, Any> = emptyMap()
) = api.screen(name, attributes)

/**
* Track activity screen, `label` added for this activity in `manifest` will be utilized for tracking
* @param activity Instance of the activity you want to track.
* @param attributes Optional event body in Map format used as JSON object
* @return Action<Unit> which can be accessed via `execute` or `enqueue`
*/
fun screen(
activity: Activity,
attributes: Map<String, Any> = emptyMap()
) = recordScreenViews(activity, attributes)

/**
* Stop identifying the currently persisted customer. All future calls to the SDK will no longer
* be associated with the previously identified customer.
Expand Down Expand Up @@ -178,4 +208,19 @@ class CustomerIO internal constructor(
event = event,
deviceToken = deviceToken
)

private fun recordScreenViews(activity: Activity, attributes: Map<String, Any>): Action<Unit> {
val packageManager = activity.packageManager
return try {
val info = packageManager.getActivityInfo(
activity.componentName, PackageManager.GET_META_DATA
)
val activityLabel = info.loadLabel(packageManager)
screen(activityLabel.toString(), attributes)
} catch (e: PackageManager.NameNotFoundException) {
ActionUtils.getErrorAction(ErrorResult(error = ErrorDetail(message = "Activity Not Found: $e")))
} catch (e: Exception) {
ActionUtils.getErrorAction(ErrorResult(error = ErrorDetail(message = "Unable to track, $activity")))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.customer.sdk

import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle

class CustomerIOActivityLifecycleCallbacks internal constructor(
private val customerIO: CustomerIO
) : ActivityLifecycleCallbacks {

override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
}

override fun onActivityStarted(activity: Activity) {
if (customerIO.config.autoTrackScreenViews) {
customerIO.screen(activity).enqueue()
}
}

override fun onActivityResumed(activity: Activity) {
}

override fun onActivityPaused(activity: Activity) {
}

override fun onActivityStopped(activity: Activity) {
}

override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {
}

override fun onActivityDestroyed(activity: Activity) {
}
}
3 changes: 2 additions & 1 deletion sdk/src/main/java/io/customer/sdk/CustomerIOConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ class CustomerIOConfig(
val apiKey: String,
val region: Region,
val timeout: Long,
val urlHandler: CustomerIOUrlHandler?
val urlHandler: CustomerIOUrlHandler?,
val autoTrackScreenViews: Boolean
)
1 change: 1 addition & 0 deletions sdk/src/test/java/io/customer/sdk/CustomerIOTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal class CustomerIOTest {
customerIO.config.timeout `should be equal to` MockCustomerIOBuilder.timeout.toLong()
customerIO.config.region `should be equal to` MockCustomerIOBuilder.region
customerIO.config.urlHandler `should be equal to` MockCustomerIOBuilder.urlHandler
customerIO.config.autoTrackScreenViews `should be equal to` MockCustomerIOBuilder.shouldAutoRecordScreenViews
}

@Test
Expand Down
4 changes: 3 additions & 1 deletion sdk/src/test/java/io/customer/sdk/MockCustomerIOBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal class MockCustomerIOBuilder {
val region = Region.US
const val timeout = 6000
val urlHandler = null
const val shouldAutoRecordScreenViews = false
}

fun build(): CustomerIO {
Expand All @@ -25,7 +26,8 @@ internal class MockCustomerIOBuilder {
siteId = "mock-site",
region = Region.US,
timeout = 6000,
urlHandler = null
urlHandler = urlHandler,
autoTrackScreenViews = shouldAutoRecordScreenViews
)

api = mock()
Expand Down

0 comments on commit 8f95ebb

Please sign in to comment.