Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure activity name is used when activity label is not defined #153

Merged
merged 9 commits into from
Aug 8, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Next

- fix: ensure activity name is used when activity label is not defined ([#153](https://github.com/PostHog/posthog-android/pull/153))
- recording: mask views with `contentDescription` setting and mask `WebView` if any masking is enabled ([#149](https://github.com/PostHog/posthog-android/pull/149))

## 3.4.2 - 2024-06-28
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ internal class PostHogActivityLifecycleCallbackIntegration(

override fun onActivityStarted(activity: Activity) {
if (config.captureScreenViews) {
val activityLabel = activity.activityLabel(config)
if (!activityLabel.isNullOrEmpty()) {
PostHog.screen(activityLabel)
val screenName = activity.activityLabelOrName(config)

if (!screenName.isNullOrEmpty()) {
PostHog.screen(screenName)
}
}
}


override fun onActivityResumed(activity: Activity) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,19 @@ internal fun Context.telephonyManager(): TelephonyManager? {
}

@Suppress("DEPRECATION")
internal fun Activity.activityLabel(config: PostHogAndroidConfig): String? {
internal fun Activity.activityLabelOrName(config: PostHogAndroidConfig): String? {
return try {
val info = packageManager.getActivityInfo(componentName, GET_META_DATA)
info.loadLabel(packageManager).toString()
val activityInfo = packageManager.getActivityInfo(componentName, GET_META_DATA)
val activityLabel = activityInfo.loadLabel(packageManager).toString()
val applicationLabel = applicationInfo.loadLabel(packageManager).toString()

if (activityLabel.isNotEmpty() && activityLabel != applicationLabel) {
activityLabel
} else {
activityInfo.name.substringAfterLast('.')
}
} catch (e: Throwable) {
config.logger.log("Error getting the Activity's label: $e.")
config.logger.log("Error getting the Activity's label or name: $e.")
null
}
}
Expand Down
15 changes: 14 additions & 1 deletion posthog-android/src/test/java/com/posthog/android/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,32 @@ public fun mockActivityUri(uri: String): Activity {
public fun mockScreenTitle(
throws: Boolean,
title: String,
activityName: String,
applicationLabel: String
): Activity {
val activity = mock<Activity>()
val pm = mock<PackageManager>()
val ac = mock<ActivityInfo>()
val ac = mock<ActivityInfo>().apply {
name = activityName
}
val appInfo = mock<ApplicationInfo>()

whenever(ac.loadLabel(any())).thenReturn(title)
whenever(appInfo.loadLabel(any())).thenReturn(applicationLabel)

if (throws) {
whenever(pm.getActivityInfo(any(), any<Int>())).thenThrow(PackageManager.NameNotFoundException())
} else {
whenever(pm.getActivityInfo(any(), any<Int>())).thenReturn(ac)
}

whenever(pm.getApplicationInfo(any(), any<Int>())).thenReturn(appInfo)

val component = mock<ComponentName>()
whenever(activity.componentName).thenReturn(component)
whenever(activity.packageManager).thenReturn(pm)
whenever(activity.applicationInfo).thenReturn(appInfo) // Ensure applicationInfo is not null

return activity
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {
captureScreenViews: Boolean = true,
throws: Boolean = false,
title: String = "Title",
activityName: String = "com.example.MyActivity",
applicationLabel: String = "AppLabel",
): PostHogFake {
val sut = getSut(captureScreenViews = captureScreenViews)
val activity = mockScreenTitle(throws, title)
val activity = mockScreenTitle(throws, title, activityName, applicationLabel)

val fake = createPostHogFake()

Expand All @@ -125,6 +127,17 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {
assertEquals("Title", fake.screenTitle)
}

@Test
fun `onActivityStarted returns activityInfo name if labels are the same`() {
val fake = executeCaptureScreenViewsTest(
captureScreenViews = true,
title = "AppLabel",
activityName = "com.example.MyActivity",
applicationLabel = "AppLabel"
)
assertEquals("MyActivity", fake.screenTitle)
}

@Test
fun `onActivityStarted does not capture captureScreenViews if disabled`() {
val fake = executeCaptureScreenViewsTest(false)
Expand All @@ -140,9 +153,9 @@ internal class PostHogActivityLifecycleCallbackIntegrationTest {
}

@Test
fun `onActivityStarted does not capture if title is empty`() {
fun `onActivityStarted returns activity name if activity label are the empty`() {
val fake = executeCaptureScreenViewsTest(title = "")

assertNull(fake.screenTitle)
assertEquals("MyActivity", fake.screenTitle)
}
}
Loading