Skip to main content
Version: 2.1.x

Compose Multiplatform UI & Screen Telemetry

The tech.appxiom:appxiom-kmp-compose module instruments Compose Multiplatform applications across Android and iOS. It provides automated app launch telemetry, navigation route transitions, semantic touch breadcrumbs, and composable memory leak detection.


Dependency Setup​

In your shared module's build.gradle.kts (e.g. composeApp/build.gradle.kts):

val appxiomVersion = "2.1.0"

kotlin {
sourceSets {
commonMain.dependencies {
api("tech.appxiom:appxiom-kmp-core:$appxiomVersion")
// Compose Multiplatform telemetry (always implementation, NEVER export)
implementation("tech.appxiom:appxiom-kmp-compose:$appxiomVersion")
}
}
}

1. Root Application Wrapper (AxApp)​

Wrap your top-level composable hierarchy inside AxApp. This establishes initial app launch telemetry and root container bounds across Android and iOS:

package com.example.app

import androidx.compose.runtime.Composable
import tech.appxiom.kmp.compose.AxApp

@Composable
fun App() {
AxApp(appName = "ShopApp") {
AppNavigation()
}
}
  • App Launch Marker: Automatically records App Launch: ShopApp into the activity trail.
  • Root Touch Observation: Automatically captures raw touch coordinates across platform view trees.

2. Navigation Compose Integration (NavHost)​

When using androidx.navigation:navigation-compose, call AxCompose.TrackLifecycleAndScreens(navController) at your navigation root. It automatically listens to back-stack changes and logs screen entry/exit transitions:

package com.example.app.ui

import androidx.compose.runtime.Composable
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import tech.appxiom.kmp.compose.AxCompose

@Composable
fun AppNavigation() {
val navController = rememberNavController()

// Automatically records route transitions as screen breadcrumbs
AxCompose.TrackLifecycleAndScreens(navController)

NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") {
HomeScreen(onNavigateToCheckout = { navController.navigate("checkout") })
}
composable("checkout") {
CheckoutScreen()
}
}
}

3. Discrete Screen Tracking with AxScreen​

For modal sheets, dialogs, or composables rendered outside of a NavHost, wrap the content in AxScreen:

package com.example.app.ui

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import tech.appxiom.kmp.compose.AxScreen

@Composable
fun CheckoutModalSheet() {
AxScreen(screenName = "CheckoutModalSheet") {
Text("Complete Your Payment")
}
}

AxScreen automatically:

  1. Emits Screen Entered: CheckoutModalSheet into the activity trail when entering composition.
  2. Emits Screen Exited: CheckoutModalSheet upon disposal.
  3. Associates hangs, frame drops, and uncaught exceptions with the active screen.

4. Semantic Click Tracking: Modifier.axTrackClick​

Why Modifier.axTrackClick is Essential​

When an application is wrapped with AxApp, raw touch coordinates are automatically captured:

Tapped at (800, 1294) : UI

However, raw coordinate taps lack semantic context. In crash reports, support engineers cannot tell whether the user tapped "Submit Order", "Cancel", "Delete Account", or an empty container.

To provide clear, actionable telemetry, add Modifier.axTrackClick across all clickable and interactive elements in your UI:

Instrumentation Examples​

Standard & Outlined Buttons​

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import tech.appxiom.kmp.compose.axTrackClick

Button(
onClick = { onSubmit() },
modifier = Modifier.axTrackClick("SubmitOrderButton")
) {
Text("Submit Order")
}

Icon Buttons & Floating Action Buttons​

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.ui.Modifier
import tech.appxiom.kmp.compose.axTrackClick

IconButton(
onClick = { onNavigateBack() },
modifier = Modifier.axTrackClick("BackNavButton")
) {
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
}

Custom Clickable Cards & Containers​

import androidx.compose.foundation.clickable
import androidx.compose.material3.Card
import androidx.compose.ui.Modifier
import tech.appxiom.kmp.compose.axTrackClick

Card(
modifier = Modifier
.fillMaxWidth()
.axTrackClick("ProductCard_${product.id}")
.clickable { onProductSelected(product) }
) {
Text(product.name)
}

Tabs & Navigation Items​

import androidx.compose.material3.Tab
import androidx.compose.ui.Modifier
import tech.appxiom.kmp.compose.axTrackClick

Tab(
selected = isSelected,
onClick = { onTabSelect() },
modifier = Modifier.axTrackClick("Tab_${tab.title}")
) {
Text(tab.title)
}

5. Composable Memory Leak Detection (AxWatchLeakOnDispose)​

To monitor a ViewModel, presenter, or remembered state object for memory leaks when a Composable leaves composition, use AxWatchLeakOnDispose:

import androidx.compose.runtime.Composable
import tech.appxiom.kmp.compose.AxWatchLeakOnDispose

@Composable
fun OrderDetailsScreen(viewModel: OrderDetailsViewModel) {
// Automatically registers viewModel for leak verification when this screen leaves composition:
AxWatchLeakOnDispose(target = viewModel, tag = "OrderDetailsViewModel")

// UI content...
}

Next Steps​

Learn how to monitor network traffic in Network Telemetry.