Skip to main content

Gradle plugin — Configuration

Configuring the plugin

app/build.gradle.kts
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
feedback.set(false) // default
optimizeExtensionsLoading.set(true) // default — merges Bugsee extension ContentProviders into the SDK's single BugseeInitProvider to shave cold-start overhead
sdkAutoLoad.set(true) // default — auto-pull com.bugsee:bugsee-android when an extension is declared but the core isn't

ndk { // native crash / NDK symbol upload
enabled.set(true) // turn on NDK support
forceDebugSymbolsUpload.set(false) // re-upload symbols even when the build UUID hasn't changed
}

buildInfo { // default ON, Release-only
// enabled.set(true) // default
// allBuildTypes.set(false) // default — only release variants register

sizeAnalysis { // opt-in size analysis (server-side AAB/APK upload)
enabled.set(true)
buildConfiguration.set("release") // defaults to variant name
chunkedUpload.set(false) // opt-in deduplicated chunk-upload protocol; on subsequent builds only changed chunks are re-uploaded (typically 70–90% faster on CI)
}

sizeCheck { // opt-in size regression gates
enabled.set(true)
warningPercent.set(5.0) // warn at +5% vs the prior build
failPercent.set(10.0) // fail the task at +10%
// warningBytes.set(500_000L)
// failBytes.set(2_000_000L)
}

dependencies {
// enabled defaults to true
}
timings {
// enabled defaults to true
}
}

instrumentation {
// enabled defaults to true (via Gradle-property/manifest fallback chain)
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
startupTier.set(StartupTier.STANDARD) // cold-start tracing tier
}
}
app/build.gradle
plugins {
id 'com.android.application'
id 'com.bugsee.android.gradle'
}

bugsee {
appToken '…'
endpoint.set 'https://api.bugsee.com'
debug.set false
feedback.set false
optimizeExtensionsLoading.set true // default — merges extension ContentProviders into BugseeInitProvider
sdkAutoLoad.set true // default — auto-pull com.bugsee:bugsee-android when an extension is declared but the core isn't

ndk {
enabled.set true
forceDebugSymbolsUpload.set false
}

buildInfo {
// enabled.set true // default
// allBuildTypes.set false // default

sizeAnalysis {
enabled.set true
buildConfiguration.set 'release'
chunkedUpload.set false
}

sizeCheck {
enabled.set true
warningPercent.set 5.0
failPercent.set 10.0
}

dependencies {
// enabled defaults to true
}
timings {
// enabled defaults to true
}
}

instrumentation {
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
startupTier.set StartupTier.STANDARD
}
}
note

Bytecode instrumentation is only applied to application modules (i.e. modules with com.android.application). Library modules are not instrumented.

The instrumentation toggles map directly onto the bytecode and compiler-plugin transforms documented in Instrumentation. The buildInfo / sizeAnalysis / sizeCheck blocks drive the build & upload tasks. The sdkAutoLoad / optimizeExtensionsLoading flags govern auto-load & extensions.

Configuring via bugsee.properties

Every plugin option is also settable through a bugsee.properties file at the root project directory, using keys prefixed plugin.. The same file already hosts the app_token= key used by the plugin's token resolver — the new plugin.* namespace coexists with it.

This is the recommended surface for CI-specific configuration: it lets each CI runner ship a different config without touching the build script.

Precedence

DSL .set(…) > bugsee.properties plugin.X > built-in default

A DSL .set(…) call in the bugsee { … } block always wins. The properties file then fills in any keys the DSL didn't touch, and anything still unset falls through to the plugin's built-in defaults. The two layers are additive — DSL can override a single key from properties without invalidating the rest.

The plugin reads the file via providers.fileContents(...) so editing bugsee.properties invalidates Gradle's configuration cache and triggers a re-load on the next build.

File location and shape

<rootProject>/bugsee.properties — at the top-level directory of your Gradle build (the parent of settings.gradle.kts), not inside each :app module.

<rootProject>/bugsee.properties
# App token used by the plugin's token resolver (unprefixed — not a plugin.* key)
app_token=YOUR_APP_TOKEN_HERE

# Plugin options — every DSL field has a matching `plugin.<dotted-path>` key
plugin.debug=true
plugin.ndk.enabled=true
plugin.buildInfo.sizeAnalysis.enabled=true
plugin.buildInfo.sizeCheck.warningPercent=10.0
plugin.buildInfo.sizeCheck.failPercent=25.0
plugin.instrumentation.startupTier=DETAILED

Key reference

Each key path mirrors the DSL field name (camelCase, dotted-path).

KeyTypeDefault
plugin.endpointStringhttps://api.bugsee.com
plugin.debugBooleanfalse
plugin.feedbackBooleanfalse
plugin.optimizeExtensionsLoadingBooleantrue
plugin.sdkAutoLoadBooleantrue
plugin.ndk.enabledBooleanfalse
plugin.ndk.forceDebugSymbolsUploadBooleanfalse
plugin.buildInfo.enabledBooleantrue
plugin.buildInfo.allBuildTypesBooleanfalse
plugin.buildInfo.sizeAnalysis.enabledBooleanfalse
plugin.buildInfo.sizeAnalysis.buildConfigurationStringunset — falls back to the Gradle variant name
plugin.buildInfo.sizeAnalysis.chunkedUploadBooleanfalse
plugin.buildInfo.sizeCheck.enabledBooleanunset — gate disabled
plugin.buildInfo.sizeCheck.warningPercentDoubleunset — threshold disabled
plugin.buildInfo.sizeCheck.failPercentDoubleunset — threshold disabled
plugin.buildInfo.sizeCheck.warningBytesLong (bytes)unset — threshold disabled
plugin.buildInfo.sizeCheck.failBytesLong (bytes)unset — threshold disabled
plugin.buildInfo.dependencies.enabledBooleantrue
plugin.buildInfo.dependencies.scopeStringruntime
plugin.buildInfo.dependencies.includeSelectedReasonBooleanfalse
plugin.buildInfo.dependencies.maxCountInt5000
plugin.buildInfo.timings.enabledBooleantrue
plugin.instrumentation.enabledBooleantrue
plugin.instrumentation.okhttpBooleantrue
plugin.instrumentation.httpEngineBooleantrue
plugin.instrumentation.logBooleantrue
plugin.instrumentation.threadBooleantrue
plugin.instrumentation.mainThreadMisuseBooleantrue
plugin.instrumentation.operationDispatchBooleantrue
plugin.instrumentation.composeBooleantrue
plugin.instrumentation.composeSecureBooleantrue
plugin.instrumentation.composeInputBooleantrue
plugin.instrumentation.ktorBooleantrue
plugin.instrumentation.cronetBooleantrue
plugin.instrumentation.startupTierEnum (OFF, MINIMAL, STANDARD, DETAILED, FULL)STANDARD
App token uses an unprefixed key

The app token is set via the unprefixed app_token=… key, not plugin.appToken=…. The DSL provides richer token-resolution forms (closure, provider, per-variant resolver) that have no properties-file equivalent — app_token= covers only the literal default-token case.

Type coercion

Property typeAccepted forms
Booleantrue / false, yes / no, on / off, 1 / 0 (case-insensitive)
Int / LongStandard integer literal
DoubleStandard decimal literal
StringTrimmed; empty / whitespace-only is rejected with a warn (default holds)
EnumCase-insensitive match against the enum's constant names

Malformed values emit a warn naming the key + bad value, then fall back to the built-in default — the plugin never crashes the build on a typo in bugsee.properties.

Diagnostics

EventLog levelWhy
File absent(silent)Most consumers don't use the file.
File present, no plugin.* keys(silent)Coexisting with app_token= is the common shape.
File malformedwarnUser error — surface always.
Value malformedwarnUser error; the key + bad value are named.
Empty/whitespace string valuewarnLikely a half-edited line; default holds.
Unknown plugin.* keyinfoForward-compat — run with --info to surface typos.
Successful applywarn, only if plugin.debug=trueEchoes each applied key when verbose mode is on.

To debug what was actually applied, run with --info:

./gradlew assembleRelease --info | grep Bugsee

Worked example — DSL + properties together

<rootProject>/bugsee.properties
app_token=YOUR_APP_TOKEN_HERE

plugin.debug=true
plugin.ndk.enabled=true
plugin.buildInfo.sizeAnalysis.enabled=true
plugin.buildInfo.sizeCheck.warningPercent=10.0
plugin.buildInfo.sizeCheck.failPercent=25.0
plugin.instrumentation.startupTier=DETAILED
app/build.gradle.kts
bugsee {
// (1) Overrides plugin.endpoint from bugsee.properties (DSL > properties).
endpoint.set("https://api.bugsee-internal.example.com")

// (2) Sets a key that bugsee.properties did NOT touch — additive.
feedback.set(true)
}

Effective configuration for the example above:

KeyEffective valueFrom
endpointhttps://api.bugsee-internal.example.comDSL (overrides properties)
feedbacktrueDSL (additive — no properties value)
debugtruebugsee.properties
ndk.enabledtruebugsee.properties
ndk.forceDebugSymbolsUploadfalsebuilt-in default
buildInfo.sizeAnalysis.enabledtruebugsee.properties
buildInfo.sizeCheck.warningPercent10.0bugsee.properties
instrumentation.startupTierDETAILEDbugsee.properties

CI gotcha — instrumentation chain bypass

Boolean instrumentation flags (and startupTier) have a deeper resolution chain than other options because they pre-date the properties-file feature:

DSL .set(…) > plugin.instrumentation.X (bugsee.properties) > -Pbugsee.instrumentation.X (legacy Gradle property) > manifest <meta-data com.bugsee.android.instrumentation.X /> > default

Setting an instrumentation flag in bugsee.properties makes the underlying DSL property "present" (isPresent == true), and the plugin's resolver short-circuits at the highest layer — so plugin.instrumentation.X bypasses the legacy -Pbugsee.instrumentation.X Gradle-property and the manifest meta-data fallback for that key. The user's DSL .set(…) still wins over both sources.

If your CI relies on -Pbugsee.instrumentation.X overrides, either:

  • Don't put the same key in bugsee.properties, or

  • Read the -P flag explicitly in your DSL so it flows through the highest-priority layer:

    app/build.gradle.kts
    bugsee {
    instrumentation {
    okhttp.set(findProperty("bugsee.instrumentation.okhttp") as? Boolean ?: true)
    }
    }

This pattern keeps the CLI override authoritative and matches the idiom recommended by other major Android tooling plugins.

Found an issue, typo, or wrong statement on this page? Report it now →