How can you implement a custom task in Gradle, and what are some use cases for it?

A custom Gradle task is a user-defined unit of build work registered in build.gradle, typically by extending the DefaultTask class or using the task/tasks.register API with an action closure. It lets teams automate project-specific steps that aren't covered by standard plugins.

Key Points: • Simple tasks can be defined inline with tasks.register('taskName') { doLast { ... } } for one-off logic. • Reusable, typed tasks extend DefaultTask and expose @Input/@Output properties so Gradle can track them for incremental builds and caching. • Task dependencies are wired with dependsOn, mustRunAfter, or finalizedBy to control execution order. • Common use cases include file management (copying, renaming, cleaning), environment setup, code generation, and custom health checks or reports. • Using tasks.register (lazy configuration) instead of task() avoids unnecessary configuration-time work, improving build performance.

Example: A team might add a custom task that copies environment-specific configuration files into build/resources before the main build runs, so local, staging, and production builds automatically pick up the right settings.

Code Example:

tasks.register('copyEnvConfig', Copy) {
    from "config/${project.findProperty('env') ?: 'dev'}"
    into "$buildDir/resources/main"
}

tasks.named('processResources') {
    dependsOn('copyEnvConfig')
}

Interview Tip: A concise interview answer is:

"I define custom tasks using tasks.register, either inline with a doLast closure for simple actions or as a DefaultTask subclass with typed inputs/outputs when I want incremental build support. I've used them for things like copying environment-specific config files or generating build metadata before packaging."