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: ShopAppinto 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:
- Emits
Screen Entered: CheckoutModalSheetinto the activity trail when entering composition. - Emits
Screen Exited: CheckoutModalSheetupon disposal. - 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.