[versions] agp = "9.1.0" kotlin = "2.4.10" # Static analysis for Kotlin, driven by tools/verify.sh. 1.23.8 is the newest release on the plugin # portal (there is no 2.x there yet). It is used through its CLI rather than its Gradle plugin: the # plugin runs the analysis inside the build's own JVM, and detekt 1.23 cannot parse JDK 25's version # string — see the task in app/build.gradle.kts. The findings that exist today are frozen in # config/detekt/baseline.xml, so the gate fails on a new one rather than on the backlog. detekt = "1.23.8" # AndroidX / Compose coreKtx = "1.18.0" lifecycle = "2.10.0" activityCompose = "1.13.0" # SAF backend: DocumentFile over a persisted tree URI. documentfile = "1.1.0" # Compose BOM 2026.06.01 -> Compose UI/foundation 1.11.4, material3 1.4.0. # Newer BOMs (2026.08.00+) ship Compose 1.12.x, which requires compileSdk 37 — # that is newer than what AGP 9.1.0 supports (36) and newer than the API level # Google Play requires for targetSdk, so we deliberately stay on 1.11.4. composeBom = "2026.06.01" # Coil 3.6.x requires compileSdk 37; 3.5.0 requires 36. coil = "3.5.0" # Kotlin libraries coroutines = "1.9.0" # Archives. Commons Compress is pure Java (zip/tar/gzip/bzip2/xz, 7z read), # so it adds no native code and therefore no NDK dependency to the build. commonsCompress = "1.27.1" # Commons Compress declares its LZMA/LZMA2 support — the `.xz` compressor and the 7z # format — against this library, as an *optional* dependency. Optional means it is NOT # pulled in transitively, so leaving it out breaks `.xz` and `.7z` at **runtime** with # NoClassDefFoundError rather than failing the build. 1.10 is the version Commons # Compress 1.27.1 itself compiles against. xz = "1.10" # Testing junit = "4.13.2" robolectric = "4.17" # Debug-only leak detection: a Compose screen that outlives its screen is invisible in tests and # obvious in a heap dump. Never shipped — `debugImplementation` below. leakcanary = "2.14" # Macrobenchmark (the `:benchmark` module). Its own versions because it is a test APK that is never # part of the app. benchmark = "1.5.0" # Baseline profiles: the Gradle plugin generates one from a device run, and profileinstaller applies it # on the device at install time. 1.5.0 is the newest stable and the one that knows AGP 9. baselineprofile = "1.5.0" profileinstaller = "1.4.0" androidxTestJunit = "1.3.0" uiautomator = "2.4.0" androidxTestRunner = "1.7.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-documentfile = { group = "androidx.documentfile", name = "documentfile", version.ref = "documentfile" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-compose-material-icons-core = { group = "androidx.compose.material", name = "material-icons-core" } androidx-compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" } kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" } # Decodes a frame out of a video, so a video row shows what is in the clip rather than a film icon. # Same version as coil-compose on purpose — a decoder is part of Coil's pipeline, not a plugin beside # it — and its POM adds nothing coil-compose does not already bring (coil-core, kotlin-stdlib, # core-ktx). No ExoPlayer and no media3, which is what makes this acceptable for a thumbnail. coil-video = { group = "io.coil-kt.coil3", name = "coil-video", version.ref = "coil" } commons-compress = { group = "org.apache.commons", name = "commons-compress", version.ref = "commonsCompress" } # Commons Compress's LZMA/LZMA2 support: the `.xz` compressor and the 7z format. xz = { group = "org.tukaani", name = "xz", version.ref = "xz" } junit = { group = "junit", name = "junit", version.ref = "junit" } robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" } # Compose rendering tests, run on the JVM through Robolectric. Versions come from the Compose BOM. androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } leakcanary-android = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakcanary" } # Macrobenchmark, for the `:benchmark` module only. androidx-benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "benchmark" } androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxTestJunit" } androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" } androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" } # Installs the baseline profile bundled in the APK on first run. androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "profileinstaller" } kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "coroutines" } # Static analysis, run by the :app:detekt task from its own configuration — never an app dependency. detekt-cli = { group = "io.gitlab.arturbosch.detekt", name = "detekt-cli", version.ref = "detekt" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } # NOTE: `org.jetbrains.kotlin.android` is intentionally absent — AGP 9.x provides # built-in Kotlin support and applying that plugin is now an error. kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } androidx-baselineprofile = { id = "androidx.baselineprofile", version.ref = "baselineprofile" }