Question
Fix registerResGeneratingTask Deprecated Warning in Android Gradle
Question
After upgrading to Android Studio and Android Gradle Plugin 3.0.0, the build displays this warning:
registerResGeneratingTask is deprecated; use registerGeneratedFolders(FileCollection)
What does this warning mean, and how should generated resource folders be registered with the newer Gradle API?
Short Answer
This warning means that a Gradle build script or a third-party Gradle plugin is using an older Android Gradle Plugin API for generated resources. You will learn how to find the code that produces the warning, replace the deprecated registration call with a generated-folder registration, and update dependencies when the call comes from an external plugin.
Concept
Android builds can create files during the build, such as generated source code, images, XML resources, or configuration files. Gradle and the Android Gradle Plugin (AGP) need to know where those generated files are located so they can include them in later build steps.
Older AGP integrations could register a task as a resource-generating task using registerResGeneratingTask(...). In AGP 3.0, that API was deprecated in favor of registerGeneratedFolders(FileCollection).
The newer API focuses on the important result: the generated folders. A FileCollection can also describe which task builds those folders, allowing Gradle to preserve task ordering and incremental-build information.
This matters because generated files must be available before Android packages resources or compiles source code. If a generated folder is not registered correctly, the build may fail to find a resource or may run tasks in the wrong order.
If the warning is emitted by a third-party plugin rather than your own build logic, the correct fix is usually to update that plugin. You generally cannot fix a deprecated API call inside a dependency from your app module alone.
Mental Model
Think of an Android build as a factory assembly line.
- A generation task is a machine that creates new boxes of files.
- A generated folder is the storage shelf where those boxes are placed.
- AGP needs the shelf location so the next machine can use the boxes.
The old API said, “This machine generates Android resources.” The newer API says, “Here are the shelves containing generated output.” Gradle can still know which machine fills a shelf when the file collection is marked as being built by that task.
Syntax and Examples
In legacy Groovy Gradle build logic, replace a deprecated registration like this:
// Deprecated in Android Gradle Plugin 3.0
variant.registerResGeneratingTask(generateTask, generatedResDir)
with a FileCollection representing the generated directory:
variant.registerGeneratedFolders(
files(generatedResDir).builtBy(generateTask)
)
files(generatedResDir) creates a Gradle FileCollection. The .builtBy(generateTask) part tells Gradle that generateTask must run before anything consumes that folder.
A complete simplified example:
android.applicationVariants.all { variant ->
def generatedResDir = file("$buildDir/generated/custom-res/${variant.name}")
def generateTask = tasks.create("generate${variant.name.capitalize()}Resources") {
outputs.dir(generatedResDir)
doLast {
def valuesDir = new File(generatedResDir, "values")
valuesDir.mkdirs()
new File(valuesDir, "generated.xml").text = '''
<resources>
<string name="generated_message">Hello</string>
</resources>
'''.stripIndent()
}
}
variant.registerGeneratedFolders(
files(generatedResDir).builtBy(generateTask)
)
}
The generated directory contains Android resource files, and AGP is informed that it should treat the folder as generated build output.
Step by Step Execution
Consider this build logic:
android.applicationVariants.all { variant ->
def outputDir = file("$buildDir/generated/custom/${variant.name}")
def generateTask = tasks.create("generate${variant.name.capitalize()}File") {
outputs.dir(outputDir)
doLast {
outputDir.mkdirs()
new File(outputDir, "message.txt").text = "Created for ${variant.name}"
}
}
variant.registerGeneratedFolders(files(outputDir).builtBy(generateTask))
}
When Gradle builds the debug variant:
variant.nameisdebug.outputDirbecomesbuild/generated/custom/debug.- Gradle creates a task named
generateDebugFile. - The task declares that it writes to
outputDirusingoutputs.dir(outputDir). registerGeneratedFolders(...)gives AGP a file collection containing that directory..builtBy(generateTask)records that the folder is produced bygenerateDebugFile.- Before a consumer needs the generated folder, Gradle can run
generateDebugFilefirst.
For Android resources, the task should write a valid Android resource directory structure, such as values/generated.xml or drawable/generated_icon.xml.
Real World Use Cases
Generated folders are common in Android build automation:
- Build configuration resources: Generate XML or JSON files containing environment-specific values.
- API clients and models: Generate Java or Kotlin source files from an API specification.
- Localization: Convert a translation source file into Android
values/strings.xmlresources. - Asset pipelines: Transform SVG, image, or design assets into generated Android resources.
- Feature flags: Generate a resource or source file based on build variant, flavor, or CI configuration.
- Code-generation plugins: Plugins such as annotation processors or schema tools produce files that must be included in compilation or packaging.
Real Codebase Usage
In a production project, avoid placing large custom task definitions directly in an app module when possible. Put reusable generation logic in a convention plugin or a dedicated Gradle plugin.
Useful patterns include:
- Declare outputs: Use
outputs.dir(...)oroutputs.file(...)so Gradle can determine whether work is up to date. - Connect producer and consumer: Use
files(outputDir).builtBy(task)so task dependencies are inferred instead of manually forcing task order. - Use variant-aware paths: Include the variant name in output paths so
debugandreleaseoutput never overwrite each other. - Validate inputs early: Fail with a clear message when a required template, API specification, or configuration value is missing.
- Update external plugins: If a warning names a plugin task or appears after applying a dependency, check that plugin's release notes and use a version compatible with the AGP version in the project.
For current AGP versions, prefer the supported Android Components APIs and Gradle's lazy task APIs when writing new build plugins. The registerGeneratedFolders migration is mainly relevant to build logic written for the AGP 3.0-era variant API.
Common Mistakes
Replacing the method but losing the task dependency
This may register the directory, but it does not explicitly tell Gradle what produces it:
variant.registerGeneratedFolders(files(generatedResDir))
Prefer:
variant.registerGeneratedFolders(files(generatedResDir).builtBy(generateTask))
Registering the wrong directory
If a resource generator writes to build/generated/res/debug/values/generated.xml, register the resource root:
build/generated/res/debug
Do not register only the values child unless the API specifically expects that child. Android resource directories need their expected structure below the registered root.
Sharing one output folder across variants
This can cause debug and release builds to overwrite each other:
file("$buildDir/generated/resources")
Use a variant-specific folder instead:
file("$buildDir/generated/resources/${variant.name}")
Editing dependency code blindly
If an external plugin produces the warning, changing your app's build.gradle may not affect it. Upgrade or replace the plugin, or use a compatible AGP version until the plugin is updated.
Assuming deprecation is immediately fatal
A deprecation warning usually allows the build to continue, but it signals that a future plugin version may remove the old API. Fix your own build logic before upgrading further.
Comparisons
| Approach | What it describes | Status for the AGP 3.0 migration |
|---|---|---|
registerResGeneratingTask(task, dir) | A task and a generated resource directory | Deprecated |
registerGeneratedFolders(files(dir).builtBy(task)) | Generated folders and their producing task | Replacement API in this migration |
Manual dependsOn only | Task ordering, but not necessarily generated-folder integration | Usually incomplete |
| No registration | Neither generated output nor its relationship to the Android build | Generated files may not be consumed |
A FileCollection is more flexible than a single File: it can represent one folder, several folders, task outputs, and build dependencies.
Cheat Sheet
// Old, deprecated AGP 3.0-era API
variant.registerResGeneratingTask(generateTask, generatedDir)
// Replacement
variant.registerGeneratedFolders(
files(generatedDir).builtBy(generateTask)
)
generatedDirshould be the root directory containing generated output.- Use a different output directory for each build variant.
- Declare task output with
outputs.dir(generatedDir). - Use
.builtBy(task)to preserve the producer relationship. - If a third-party plugin causes the warning, update that plugin rather than changing unrelated app code.
- For newly written plugins targeting modern AGP, check the current Android Components API instead of copying legacy variant API examples.
FAQ
What causes the registerResGeneratingTask is deprecated warning?
A Gradle script or plugin is calling an old Android Gradle Plugin API. It is often custom build logic or an outdated third-party plugin.
Does this warning stop the Android build?
Usually no. A deprecation warning means the API still works for now, but may be removed in a later version.
How do I find which code causes the warning?
Run Gradle with additional warning information, for example:
./gradlew assembleDebug --warning-mode all
Then inspect the reported script, task, or plugin name.
Should I replace registerResGeneratingTask with registerGeneratedFolders directly?
Yes, when you own the legacy build logic and the AGP version exposes that replacement API. Pass a FileCollection, commonly files(directory).builtBy(task).
Why use builtBy(generateTask)?
It tells Gradle that the generated directory is produced by that task, allowing Gradle to schedule the task before consumers use the directory.
What if the warning comes from a library or Gradle plugin?
Update the plugin to a version compatible with your Android Gradle Plugin. If no update exists, use a compatible plugin/AGP combination or migrate away from the outdated plugin.
Is registerGeneratedFolders the preferred API for every modern Android project?
Not necessarily. It was the replacement for this legacy AGP migration. New build plugins should use the APIs recommended by the AGP version they target.
Mini Project
Description
Create a small Gradle task that generates an Android string resource for each application variant and registers its output as a generated folder. This models a build that creates environment-specific resources automatically.
Goal
Generate a generated_message string resource for every variant and make it available to the Android build.
Requirements
Requirement list is provided below.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.