Gradle plugin (7.x Beta)
This document describes the Bugsee Android SDK 7.x (beta). In 6.x, no Gradle plugin was required — the SDK worked purely as a runtime library. In 7.x, the com.bugsee:bugsee-android-gradle-plugin is mandatory even when you only depend on the core bugsee-android artifact. The plugin is what unlocks:
- APM — DB, file-I/O, and network operation instrumentation that feeds
db.*/file.*/http.clientspans. - Main-thread misuse detection — pre-call checks around guarded I/O / network / DB /
SharedPreferencesoperations. - Network-client auto-install — OkHttp, Ktor 2/3, and Cronet extensions pulled in automatically based on your dependency graph.
- Feedback auto-install — extension modules wired by dependency detection.
- Compose secure-content transforms — Kotlin compiler plugin that injects
Modifier.bugseeSecure()into passwordTextFieldcall sites and tags Compose IR for input/screenshot correlation.
Without the plugin, several of the features above stop working entirely or require manual wiring.
You can find the plugin in the Maven repository.
Install
Apply the plugin to your application module. Bytecode instrumentation is only applied to modules with com.android.application — library modules are not instrumented.
Using the plugins block (recommended)
plugins {
id("com.android.application")
id("com.bugsee.android.gradle") version "<plugin-version>"
}
plugins {
id 'com.android.application'
id 'com.bugsee.android.gradle' version '<plugin-version>'
}
Using the legacy buildscript classpath
buildscript {
dependencies {
classpath("com.bugsee:bugsee-android-gradle-plugin:<plugin-version>")
}
}
plugins {
id("com.android.application")
id("com.bugsee.android.gradle")
}
buildscript {
dependencies {
classpath 'com.bugsee:bugsee-android-gradle-plugin:<plugin-version>'
}
}
plugins {
id 'com.android.application'
id 'com.bugsee.android.gradle'
}
Bytecode instrumentations
Each instrumentation runs against every class in the application variant via AGP's transformClassesWith pipeline. Each is gated on the presence of a specific dependency, and each can be toggled individually via the bugsee { instrumentation { … } } block.
| Key | Gating dependency | What it injects | SDK feature unlocked |
|---|---|---|---|
log | bugsee-android | Rewrites every android.util.Log.* static call to BugseeLogAdapter.*, which forwards the entry to the capture pipeline and then delegates to the original Log method. | Logcat capture without requiring embedders to switch logging APIs. |
thread | bugsee-android | Injects BugseeThreadAdapter.registerThread() as the first instruction of every run() method in classes that implement Runnable or extend Thread. | JVM ↔ native thread ID map used by NDK crash reporting and thread tracing. |
operationDispatch | bugsee-android | Injects BugseeOperationDispatcher.onXxxOperationStart/End() around guarded I/O, network, DB, and SharedPreferences operations. | Feeds the APM DatabasePerformanceProvider, FileIOPerformanceProvider, and NetworkPerformanceProvider — emits db.* / file.* / http.client spans without runtime reflection. |
mainThreadMisuse | bugsee-android | Injects lightweight pre-call checks before the same set of guarded operations as operationDispatch. The checks bridge to BugseeMainThreadGuardAdapter, which reports the violation when the current thread is the main thread. | Powers Options.DetectAndReportMainThreadMisuse. |
http_engine | bugsee-android | Wraps every android.net.http.HttpEngine.Builder.build() call site with BugseeHttpEngineAdapter.wrapHttpEngine(...). | Captures traffic from the Android 14+ platform HttpEngine (Cronet-derived) without requiring embedders to wrap engine builders by hand. |
okhttp | bugsee-android-okhttp | Injects BugseeOkHttpInterceptor into every OkHttpClient.Builder.build() call site (frame computation: COPY_FRAMES). | Makes the OkHttp extension fully transparent — embedders never call any wiring API. |
composeInput | bugsee-android and androidx.compose.ui:ui | Instruments AndroidComposeView.dispatchTouchEvent(MotionEvent) to call BugseeComposeInputAdapter.onComposeTouch(view, event) at the start of the method. | Captures touch events inside Jetpack Compose UI. AndroidComposeView overrides dispatchTouchEvent without calling super, so neither overlay views nor OnTouchListener see Compose touches. |
The plugin does not bytecode-instrument Cronet (org.chromium.net.CronetEngine). Cronet has no interceptor pipeline and the Builder.build() call site sits inside the Cronet artifact, so the only mechanism that works is wrapping the engine. The plugin auto-pulls bugsee-android-cronet when it detects a Cronet dependency, but the embedder still has to call BugseeCronet.instrument(engine) once per engine instance. The same pattern applies to Ktor 2 / Ktor 3 — the plugin auto-pulls the artifact, but the embedder must install(...) the plugin in each HttpClient because Ktor's pipeline is opt-in per client.
Disabling an instrumentation key only disables the build-time transformation; the corresponding runtime feature still functions but loses whatever the bytecode hook gave it (e.g. disabling log means Bugsee.log(...) calls still work, but android.util.Log calls from your app are no longer captured).
Kotlin compiler plugin (com.bugsee.compose.compiler)
Loaded automatically whenever any Compose dependency is detected. It exposes two independent subfeatures, each gated by its own option:
| Subfeature | Option | Behavior |
|---|---|---|
| Compose tag injection | instrumentation.compose | Injects element tags into Compose IR so the SDK can correlate captured input/screenshots with composables. |
| Secure modifier auto-injection | instrumentation.composeSecure | Walks the Compose IR for password TextField call sites and automatically inserts Modifier.bugseeSecure(). Embedders get redaction of password fields without touching their UI code. |
Both subfeatures stay on by default and can be disabled independently in the bugsee { instrumentation { … } } block.
Auto-install of extension modules
During withDependencies evaluation of the implementation configuration, the plugin scans the host project's declared dependencies and adds the matching Bugsee extension artifact at the same version as the plugin itself, unless the embedder has already declared it.
| Detected dependency | Auto-added Bugsee module |
|---|---|
androidx.compose.* | com.bugsee:bugsee-android-compose |
com.squareup.okhttp3:* | com.bugsee:bugsee-android-okhttp |
io.ktor:* (2.x) | com.bugsee:bugsee-android-ktor-2 |
io.ktor:* (3.x) | com.bugsee:bugsee-android-ktor-3 |
org.chromium.net:* | com.bugsee:bugsee-android-cronet |
If you already declared the matching Bugsee artifact yourself, the plugin leaves your declaration alone. Each auto-install rule can be disabled via the corresponding DSL property — for example instrumentation.ktor.set(false) suppresses Ktor auto-install, and instrumentation.cronet.set(false) suppresses Cronet auto-install.
Auto-install is also suppressed when the plugin is applied to a project that is itself a Bugsee SDK module (avoiding circular dependencies on :library, :okhttp, etc.).
Auto-install happens only when the Bugsee Gradle plugin is applied. In Maven builds, or in Gradle builds where you have chosen not to apply the plugin, every extension module must be added manually to your dependencies { } / pom.xml — nothing is pulled in for you, even when the third-party dependency (OkHttp, Ktor, Cronet, Compose) is present. See Extensions — Without the Bugsee Gradle plugin for the full manual declaration set.
Build-time tasks
The plugin registers per-variant tasks:
| Task | Trigger | Purpose |
|---|---|---|
createBugsee<Variant>ManifestConfig | Wired into SingleArtifact.MERGED_MANIFEST transform. | Injects a per-build BUILD_UUID into the merged AndroidManifest.xml so the SDK can correlate uploaded reports / mappings with the exact build. |
uploadBugsee<Variant>Mapping | Finalizes assemble<Variant> and bundle<Variant>. | Uploads the ProGuard / R8 mapping file for symbolication of obfuscated stack traces. |
uploadBugsee<Variant>Native | Finalizes assemble<Variant> / bundle<Variant> when bugsee { ndk(true) }. | Uploads NDK native debug symbols (after extract<Variant>NativeDebugMetadata) so native crashes can be symbolicated. |
uploadBugsee<Variant>Bundle | Finalizes bundle<Variant> when bugsee { sizeAnalysis { enabled.set(true) } }. | Uploads the AAB for size analysis and comparison. |
uploadBugsee<Variant>Apk | Finalizes assemble<Variant> when bugsee { sizeAnalysis { enabled.set(true) } }. | Uploads the APK for size analysis and comparison. |
Configuring the plugin
plugins {
id("com.android.application")
id("com.bugsee.android.gradle")
}
bugsee {
appToken("…") // or: appToken { variantName -> resolveToken(variantName) }
endpoint.set("https://api.bugsee.com") // default
debug.set(false) // default
ndk(true) // upload NDK symbols
sizeAnalysis { // opt-in
enabled.set(true)
buildConfiguration.set("release") // defaults to variant name
}
instrumentation {
enabled.set(true) // global switch (default: true)
log.set(true) // android.util.Log redirection
thread.set(true) // Thread/Runnable registration
operationDispatch.set(true) // I/O, network, DB operation tracking
mainThreadMisuse.set(true) // main-thread misuse detection
httpEngine.set(true) // HttpEngine (Cronet-derived) instrumentation
okhttp.set(true) // OkHttp interceptor injection
composeInput.set(true) // Compose touch input capture
compose.set(true) // Compose tag injection (compiler plugin)
composeSecure.set(true) // password TextField auto-redaction (compiler plugin)
ktor.set(true) // Ktor extension auto-install
cronet.set(true) // Cronet extension auto-install
}
}
plugins {
id 'com.android.application'
id 'com.bugsee.android.gradle'
}
bugsee {
appToken '…'
endpoint.set 'https://api.bugsee.com'
debug.set false
ndk true
sizeAnalysis {
enabled.set true
buildConfiguration.set 'release'
}
instrumentation {
enabled.set true
log.set true
thread.set true
operationDispatch.set true
mainThreadMisuse.set true
httpEngine.set true
okhttp.set true
composeInput.set true
compose.set true
composeSecure.set true
ktor.set true
cronet.set true
}
}
Bytecode instrumentation is only applied to application modules (i.e. modules with com.android.application). Library modules are not instrumented.
Requirements and compatibility
The Gradle plugin and the SDK runtime library are versioned independently but released as a matched pair. There is no cross-line compatibility — the plugin expects the exact runtime-library shape shipped alongside it.
| Plugin line | SDK line | Status | Min AGP | Min Gradle |
|---|---|---|---|---|
| 3.x | 6.x | Stable | — | — |
| 4.x | 7.x | Beta | 8.6.0 | 8.7+ |
- Use plugin 4.x only with SDK 7.x, and plugin 3.x only with SDK 6.x. Mixing lines will fail at build or runtime.
- Plugin 4.x introduces new instrumentation hooks and auto-install rules keyed on the
bugsee-android-*artifact names introduced in SDK 7.x; it cannot target the single-AAR 6.x layout. - Plugin 3.x has no knowledge of the 7.x module split, APM operation dispatch, Compose transforms, or the new manifest-metadata auto-launch, so SDK 7.x will not function correctly under it.
- Both lines are currently in beta and are expected to graduate to GA together. Pin the plugin to a specific beta version rather than a floating range while the APIs are still stabilizing.