Android RUM SDK
Install and configure the Last9 Android RUM SDK. Kotlin API, CDN-hosted Maven AAR, automatic instrumentation for sessions, views, OkHttp, errors, ANRs, and resource sampling.
Real User Monitoring for Android apps. Automatic instrumentation for sessions, views, network requests, errors, ANR detection, and resource metrics via OpenTelemetry.
Prerequisites
- Android minSdk 21 (Android 5.0+)
- Kotlin 1.8+ or Java 8+
- An
Applicationsubclass - A Last9 RUM client token and OTLP endpoint
CDN artifacts
| Artifact | URL |
|---|---|
| Maven repo root | https://cdn.last9.io/rum-sdk/android/maven/ |
| POM | https://cdn.last9.io/rum-sdk/android/maven/io/last9/rum-android/0.3.1/rum-android-0.3.1.pom |
| AAR | https://cdn.last9.io/rum-sdk/android/maven/io/last9/rum-android/0.3.1/rum-android-0.3.1.aar |
Maven coordinates: io.last9:rum-android:0.3.1. Staging builds use the -alpha suffix.
Installation
-
Add the CDN Maven repository
dependencyResolutionManagement {repositories {google()mavenCentral()maven { url = uri("https://cdn.last9.io/rum-sdk/android/maven/") }}}dependencyResolutionManagement {repositories {google()mavenCentral()maven { url = uri("https://cdn.last9.io/rum-sdk/android/maven/") }}} -
Add the dependency
In your app’s
build.gradle.kts:dependencies {implementation("io.last9:rum-android:0.3.1")} -
Initialize the SDK
In your
Applicationsubclass:import android.app.Applicationimport io.last9.rum.L9Rumimport io.last9.rum.L9RumConfigclass MyApplication : Application() {override fun onCreate() {super.onCreate()L9Rum.initialize(this,L9RumConfig(baseUrl = "https://otlp-ext-aps1.last9.io/v1/otlp/organizations/<org>",origin = "https://app.last9.io",clientToken = "your-client-token",serviceName = "my-android-app",serviceVersion = "1.0.0",deploymentEnvironment = "production",))}} -
Register the Application class
In
AndroidManifest.xml:<application android:name=".MyApplication" ... >
Configuration
L9RumConfig( // --- Required ---------------------------------------------------------
// OTLP collector endpoint baseUrl = "https://otlp-ext-aps1.last9.io/v1/otlp/organizations/<org>",
// Authentication token from Last9 clientToken = "your-client-token",
// Application identifier (maps to service.name) serviceName = "my-android-app",
// App version string (maps to service.version) serviceVersion = "1.0.0",
// Environment name deploymentEnvironment = "production",
// --- Optional ---------------------------------------------------------
// Origin sent as X-LAST9-ORIGIN header. // Required for client_monitoring tokens. origin = "https://app.last9.io",
// Specific build identifier (maps to app.build_id) appBuildId = "1.0.0-build-42",
// Unique per-install ID (NOT a hardware ID). Persists across launches. appInstallationId = null,
// Session sampling rate: 0-100 (percentage). 100 = sample everything. sampleRate = 100,
// Print debug logs to logcat debugLogs = false,
// Automatically trace HTTP requests via OkHttp interceptor networkInstrumentation = true,
// Automatically capture unhandled exceptions errorInstrumentation = true,
// Max spans per export batch maxExportBatchSize = 100,
// Export timeout in milliseconds exportTimeoutMs = 30_000L,
// Enable ANR (Application Not Responding) detection anrDetectionEnabled = true,
// ANR threshold in milliseconds anrThresholdMs = 5_000L,
// Periodically sample memory and CPU resourceMonitoringEnabled = true,
// Interval between resource samples (ms) resourceSamplingIntervalMs = 30_000L,
// When true, each HTTP request gets its own traceId // instead of sharing the current view's traceId isolateTracePerRequest = false,
// Custom resource attributes added to every span resourceAttributes = mapOf( "app.platform" to "android", ),
// W3C Baggage propagation on outgoing requests baggage = L9BaggageConfig( enabled = false, allowedKeys = listOf("session.id", "user.id"), maxTotalBytes = 8192, trackedUrlPatterns = emptyList(), warnAtPercentage = 80, ),)API reference
Identify a user
L9Rum.identify("user-123", mapOf( "email" to "user@example.com", "plan" to "premium",))Clear user on sign-out
L9Rum.clearUser()Capture errors
try { // risky operation} catch (e: Exception) { L9Rum.captureError(e, mapOf("screen" to "checkout"))}Unhandled exceptions are captured automatically when errorInstrumentation = true.
Track views
Activities are tracked automatically via ActivityLifecycleCallbacks. Use the manual API for fragments or Compose destinations:
L9Rum.startView("ProductDetailsScreen")L9Rum.setViewName("Product #42")Custom events
L9Rum.addEvent("purchase_completed", mapOf( "product_id" to "12345", "amount" to 29.99,))Global span attributes
// Inject attributes into every spanL9Rum.spanAttributes(mapOf( "experiment" to "checkout_v2", "feature_flag" to "new_cart",))
// ClearL9Rum.spanAttributes(null)Network interceptor (manual OkHttp setup)
When networkInstrumentation = true, HTTP calls through the SDK’s default client are traced automatically. For a custom OkHttpClient, add the interceptor manually:
val client = OkHttpClient.Builder() .apply { L9Rum.networkInterceptor(context)?.let { addInterceptor(it) } } .build()Session ID
val sessionId: String? = L9Rum.getSessionId()Flush pending data
L9Rum.flush()Call flush() before the app exits or in response to critical lifecycle events where losing the last batch matters.
Next steps
Once data is flowing, explore it in Discover > Applications — performance, errors, and sessions.
Troubleshooting
Please get in touch with us on Discord or Email if you have any questions.