Android SDK
Install DebugBundle in Android apps with crash replay, ANR/process-exit capture, offline queueing, OkHttp, Ktor, Navigation, Compose, Timber, and probes.
The Android SDK is the Kotlin mobile SDK for native Android applications. It captures handled exceptions, fatal crashes on next launch, ANR/process-exit signals, lifecycle breadcrumbs, network request failures, logs, and diagnostic probes without throwing back into app code.
Android is a mobile client SDK, not a browser relay host. It sends mobile events to the configured ingestion endpoint and uses explicit first-party network instrumentation for trace correlation; browser relay settings such as transportMode, allowedOrigins, and CORS preflight handling belong to the Browser SDK plus a backend/server SDK relay.
This SDK is pre-release and published on Maven Central. Use the 0.1.0 package family for the current public release.
Installation
Import the BOM and the runtime module:
dependencies {
implementation(platform("com.debugbundle:debugbundle-android-bom:0.1.0"))
implementation("com.debugbundle:debugbundle-android")
}Add optional integrations as needed:
dependencies {
implementation("com.debugbundle:debugbundle-android-okhttp")
implementation("com.debugbundle:debugbundle-android-ktor-client")
implementation("com.debugbundle:debugbundle-android-navigation")
implementation("com.debugbundle:debugbundle-android-compose")
implementation("com.debugbundle:debugbundle-android-timber")
}The SDK supports Android minSdk 23 and uses Java 17 bytecode with core-library desugaring.
Initialize
Initialize once from your Application:
import android.app.Application
import com.debugbundle.android.DebugBundle
import com.debugbundle.android.DebugBundleConfig
class CheckoutApplication : Application() {
override fun onCreate() {
super.onCreate()
DebugBundle.init(
application = this,
config = DebugBundleConfig(
projectToken = "dbundle_proj_...",
service = "checkout-android",
environment = "production",
appVersion = BuildConfig.VERSION_NAME,
buildNumber = BuildConfig.VERSION_CODE.toString(),
),
)
}
}Android initialization installs runtime defaults, device context, fatal-crash replay, ApplicationExitInfo ANR/process-exit replay where available, activity screen breadcrumbs, process foreground/background breadcrumbs, and WorkManager-backed deferred flushing.
Capture
try {
checkout()
} catch (error: Throwable) {
DebugBundle.captureException(
error,
context = mapOf("cart_id" to cartId),
)
}
DebugBundle.captureLog(
message = "checkout retry",
level = DebugBundleLogLevel.Warning,
context = mapOf("attempt" to attempt),
)
DebugBundle.setContext("tenant", tenantId)
DebugBundle.flush()SDK capture calls are no-throw. If transport, queueing, redaction, or config refresh fails, the SDK swallows the failure and keeps app execution isolated.
Network Capture
OkHttp requests are instrumented only when they match an explicit propagation target:
import com.debugbundle.android.network.DebugBundleOkHttpInterceptor
import com.debugbundle.android.network.DebugBundleTracePropagationTarget
import okhttp3.OkHttpClient
val httpClient = OkHttpClient.Builder()
.addInterceptor(
DebugBundleOkHttpInterceptor(
tracePropagationTargets = listOf(
DebugBundleTracePropagationTarget.host("api.example.com"),
),
),
)
.build()Ktor client support uses the same target matcher:
import com.debugbundle.android.network.DebugBundleKtorClientPlugin
import com.debugbundle.android.network.DebugBundleTracePropagationTarget
import io.ktor.client.HttpClient
val client = HttpClient {
install(DebugBundleKtorClientPlugin) {
tracePropagationTargets = listOf(
DebugBundleTracePropagationTarget.hostSuffix("example.com"),
)
}
}Matching requests receive X-DebugBundle-Trace-Id, network breadcrumbs, and policy-driven request_event promotion for failed responses. The SDK captures allowlisted headers only and leaves request/response bodies disabled by default.
Screens And Logs
Navigation and Compose helpers record screen breadcrumbs:
navController.installDebugBundleNavigationListener()@Composable
fun CheckoutScreen() {
DebugBundleScreen("checkout")
}Timber support captures structured logs at the SDK's configured threshold:
Timber.plant(DebugBundleTimberTree())Offline Queue And Crash Replay
The Android runtime writes a bounded file-backed offline queue under app-private storage by default. Queue limits are controlled by offlineQueueMaxEvents, offlineQueueMaxBytes, and offlineQueueTtl.
Fatal crashes are captured by a chained uncaught-exception handler and replayed on the next launch. ANR/process-exit events are read from ApplicationExitInfo when the OS exposes a pending exit reason. WorkManager schedules deferred flushes so queued events can be sent without blocking the foreground path.
Probes
Always-on probes buffer redacted diagnostic data locally and attach contract-shaped inline data to exception payloads:
DebugBundle.probe(
label = "checkout.tax",
data = mapOf("amount" to amount, "country" to country),
)Inline probe data is sent as:
{
"probe_data": {
"version": 1,
"items": [
{
"label": "checkout.tax",
"data": { "amount": 42, "country": "SI" },
"timestamp": "2026-05-28T10:15:30Z",
"activation_id": null
}
]
}
}Heavy probes stay dormant until a matching remote directive or trigger token is active:
DebugBundle.probe("checkout.expensive_state", ProbeOptions(heavy = true)) {
collectExpensiveDiagnostics()
}Remote probe directives come from GET /v1/sdk/config and from piggybacked probe_directives in successful ingestion responses. When the server capture policy allows standalone_when_activated, matching probes emit standalone probe_event records with the activation ID.
OkHttp and Ktor integrations also read X-DebugBundle-Probe-Trigger from instrumented requests. The SDK validates dbundle_probe_... trigger tokens locally with the trigger_token_key from config and silently ignores invalid or expired tokens.
Privacy Defaults
Sensitive fields such as passwords, tokens, cookies, authorization headers, card fields, verification codes, and SSNs are redacted before buffering or transport. Header capture is allowlist-based, and request/response bodies remain off by default.
For app-specific identifiers, prefer explicit low-cardinality context:
DebugBundle.setContext("account_tier", "team")
DebugBundle.setContext("region", "eu")Avoid sending raw PII, access tokens, full request bodies, or unbounded collections in probe payloads.
Modules
| Module | Purpose |
|---|---|
debugbundle-android-core | Core client, facade, event envelopes, redaction, transport, capture policy, queues, and probes |
debugbundle-android | Android runtime bootstrap, lifecycle/process hooks, device context, crash/ANR replay, and WorkManager flushing |
debugbundle-android-okhttp | OkHttp trace injection, request capture, failed-response promotion, and trigger-token header extraction |
debugbundle-android-ktor-client | Ktor client trace injection, request capture, failed-response promotion, and trigger-token header extraction |
debugbundle-android-navigation | Navigation screen transition capture with previous-screen context |
debugbundle-android-compose | Compose screen recorder helpers and Navigation bridge |
debugbundle-android-timber | Timber tree for structured log capture |
debugbundle-android-testkit | Fake transports and batch inspection helpers |