Skip to content
Last9
Book demo

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 Application subclass
  • A Last9 RUM client token and OTLP endpoint

CDN artifacts

ArtifactURL
Maven repo roothttps://cdn.last9.io/rum-sdk/android/maven/
POMhttps://cdn.last9.io/rum-sdk/android/maven/io/last9/rum-android/0.3.1/rum-android-0.3.1.pom
AARhttps://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

  1. Add the CDN Maven repository

    dependencyResolutionManagement {
    repositories {
    google()
    mavenCentral()
    maven { url = uri("https://cdn.last9.io/rum-sdk/android/maven/") }
    }
    }
  2. Add the dependency

    In your app’s build.gradle.kts:

    dependencies {
    implementation("io.last9:rum-android:0.3.1")
    }
  3. Initialize the SDK

    In your Application subclass:

    import android.app.Application
    import io.last9.rum.L9Rum
    import io.last9.rum.L9RumConfig
    class 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",
    )
    )
    }
    }
  4. 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 span
L9Rum.spanAttributes(mapOf(
"experiment" to "checkout_v2",
"feature_flag" to "new_cart",
))
// Clear
L9Rum.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.