Gradle & Code Quality

Where Android Build Dependencies Belong in Multi-Module Apps

Android build dependencies belong in the module and configuration that use them. Plugin dependencies, application libraries and test libraries are different inputs; placing them all in a root build script makes the project harder to reason about.

By , FounderUpdated 3 min read

Separate plugin resolution from library resolution

A plugin changes how the build works. A library provides code or resources to a module. Settings-level plugin management and dependency repository configuration also have different roles.

The Android dependency guide explains supported declarations. Do not paste an old buildscript classpath example into an unrelated modern plugins block and assume the syntax or resolution path is equivalent.

Place declarations by ownership

Input Typical owner
Android application plugin version Root plugin declaration or version catalog, then module application
App runtime library App module dependency block
Shared library dependency The library module that uses it
Unit-test framework Relevant module's test configuration
Repository policy Settings or supported centralized repository configuration

Exact structure can vary, especially with convention plugins and included builds. Consistency with the project's established model is more important than forcing one tutorial layout.

Keep the release graph intentional

Use implementation, api and test scopes according to the code boundary. Gradle dependency resolution can bring in transitive dependencies, so the declaration list is not the complete release inventory.

Do not duplicate the same coordinate in several scopes to make an import resolve without understanding which source set needs it.

Diagnose unresolved dependencies precisely

Check coordinate spelling, repository availability, version existence and credentials. An artifact available through a plugin repository is not necessarily available through the library repositories configured for the module.

Avoid adding untrusted repositories globally as a quick fix. Prefer the publisher's documented distribution source and review repository scope.

Validate the built module

Run the affected module's build and dependency report. APKLint's Gradle Dependency Checker can review declarations and common mistakes, but it does not resolve your private repositories or entire multi-module graph. Use the tool as a configuration review alongside actual Gradle output, not as a substitute for it.

Place a dependency in a three-module application

Consider an illustrative project containing :app, :feature:orders and :core:network. The orders screen calls a repository exposed by the network module. Put the project dependency in the module that uses it: the orders module depends on network, while the application depends on the feature it assembles. The HTTP library belongs in network if only network's implementation uses its types. Declaring that library in the root project will not automatically make it available to every Android source set.

// feature/orders/build.gradle.kts
dependencies {
    implementation(project(":core:network"))
}
// app/build.gradle.kts
dependencies {
    implementation(project(":feature:orders"))
}

These project paths must already be included by the settings configuration. The snippets assume the corresponding Android plugins have been applied and the project supplies its existing SDK configuration. They deliberately introduce no external version number: the example demonstrates ownership, not a recommended library release. The Gradle dependency declaration reference distinguishes project dependencies from repository coordinates and local files.

Separate an import failure from a repository failure

If an orders source file cannot import a network type, first check that the module dependency exists and the type is public in the intended source set. If Gradle instead reports that an external artifact cannot be found, inspect the requested coordinate and repository configuration. Those failures occur at different boundaries. Moving imports or adding another project dependency will not fix a repository that cannot provide the requested artifact.

For a private repository, verify the job's approved credential reference and whether repository content filters allow the relevant group. Log the repository identity and coordinate without printing credentials. A developer's successful cached build does not establish that a fresh CI worker can resolve the same artifact.

After the correction, build the orders module and the application variant that packages it. Inspect the runtime graph for that variant and exercise the orders request using synthetic data. If a unit-test helper was mistakenly added to production dependencies, move it to the test configuration and verify both the test task and production compilation. This demonstrates the intended separation while retaining a reproducible explanation for the build change.

Sources and further reading

  1. Android Developers: Add build dependencies
  2. Gradle: Declaring dependencies

Reference review: 29 September 2026. Examples illustrate the workflow; check your installed versions, release artifact and account-specific Console requirements before applying them. This guide is not a claim that APKLint executed your project or verified your private account.

APKLint

Android inspection tools and practical release guides. About APKLint · Report a correction