Safeguard
Developer Tools•

How do you lock Android SDK versions with Gradle lockfiles?

Turn on Gradle dependency locking, generate gradle.lockfile with write-locks, commit it, and update chosen modules on purpose. Steps and caveats inside.

Safeguard Security Team
3 min read

Enable Gradle dependency locking, run the write-locks task to create gradle.lockfile, commit that file, and update individual modules only when you decide to. Locked versions become strict constraints, so builds stop drifting even if a library uses a dynamic version.

What dependency locking does

Gradle's documentation says locking saves the resolved versions of dependencies to a lock file so later builds reuse them. The file is called gradle.lockfile and sits in each project directory. Buildscript dependencies use a separate buildscript-gradle.lockfile. Each line holds group, artifact and version, plus the configurations that include it. Gradle says the file is expected to be part of source control.

Android's own guidance says you should not use dynamic version numbers such as a plus sign in a version, because it can cause unexpected updates and hard to resolve differences. Locking is one defence if you inherit builds that already use them. Removing the dynamic versions is the better fix, as covered in why to avoid dynamic versions in mobile releases.

Steps

  1. Turn locking on for all configurations in your build script:
dependencyLocking {
    lockAllConfigurations()
}
  1. Generate the lock state:
./gradlew dependencies --write-locks
  1. Commit every gradle.lockfile that appears.
  2. Build as usual. Gradle checks that resolution matches the lock state.
  3. To move one library, update only that module:
./gradlew dependencies --update-locks org.slf4j:slf4j-api
  1. Review the lockfile diff in the pull request like any code change.

How it behaves

Gradle adds the locked versions as strict constraints. For transitive dependencies this pins the version. For direct dependencies, the declared version acts as a requirement, so if you declare a version higher than the locked one, resolution fails until you update the lock state. That failure is useful: it tells you the lock and the build file disagree.

Gradle also will not write lock state if the build fails, so a broken build cannot silently rewrite your pins.

Caveats

  • Locking should not be used with changing versions such as snapshots, because their content can change while the coordinates stay the same.
  • A lock file records versions, not trust. Pair it with dependency verification, covered in our post on checksums and signatures.
  • Version catalogs and locking solve different problems. Android recommends version catalogs for managing versions in one place. Locking records what actually resolved, including transitive libraries a catalog does not list.

Connect it to approval

Treat a lockfile change as an SDK change. If the diff adds a new group and artifact, that is a new dependency and needs a request. If it only bumps a patch version of an approved SDK, a lighter review fits. The SDK risk tiers help decide which.

Safeguard reads Gradle manifests and lock files during SBOM and dependency scanning, so the resolved set you commit is also the set that gets checked. A free scan is at gold.safeguard.sh/scan.

Quick check

Does a lockfile replace a version catalog?

No. A catalog centralises the versions you declare. A lockfile records every version that resolved, including transitive ones.

What happens if I declare a higher version than the lock?

Resolution fails until you update the lock state, which makes the mismatch visible.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.