Write your own custom tasks in Gradle
Learn how to customize the Gradle build process.
Problem
You want to customize the Gradle build process with your own tasks.
Solution
Add task
elements to the Gradle build files. Use the extra properties supplied with the Android plug-in to make development easier.
Discussion
The Gradle DSL supports a task
block for defining your own custom tasks. The API includes a wide range of existing tasks (like Copy
, Wrapper
, and Exec
) that you can use simply by setting properties.
For example, the Copy
task includes from
and into
properties, and the from
block can be configured to exclude specified filename patterns. To copy all the APKs into a new folder, excluding those that are either unsigned or unaligned, add the task in Example 1 to the module build.
Example 1. Copy APKs to another folder
task copyApks(type: Copy) { from("$buildDir/outputs/apk") { exclude '**/*unsigned.apk', '**/*unaligned.apk' } into '../apks' }
The buildDir
property refers to the default build directory (app/build), and the dollar sign is used to inject it into a Groovy string (with double quotes). The documentation for the Copy
task shows that the exclude
block inside from
supports an Ant-style directory name, meaning that **
matches all descendent directories.
If you don’t want to simply configure an existing Gradle task, you need to understand the distinction between the configuration and execution phases of Gradle. During the configuration phase, Gradle builds a DAG based on their dependencies. It then executes the desired task, along with its dependencies. All tasks are configured before any are executed.
Gradle prefers declarative tasks, like the Example 1 task, where you specify what you want done but not how to do it. If you need to execute commands, however, add a doLast
block to your Gradle task.
The task shown in Example 2, from not available, is repeated here.
Example 2. A custom task to print available variants
task printVariantNames() { doLast { android.applicationVariants.all { variant -> println variant.name } } }
Anything done in the task either before or after the doLast
block would be run during configuration time. The code in the doLast
block itself runs at execution time.
The Android plug-in adds an android
property, which in turn has an application
Variants
property that returns all the buildType/flavor combinations. In this case, they are all being printed to the console.
Note
The applicationVariants
property is only available for the com.android.application
plug-in. A libraryVariants
property is available in Android libraries. A testVariants
property is available in both.
To install all the debug flavors onto a single device (assuming they all have unique applicationId
values), use the task in Example 3.
Example 3. Install all the debug flavors on a single device
task installDebugFlavors() { android.applicationVariants.all { v -> if (v.name.endsWith('Debug')) { String name = v.name.capitalize() dependsOn "install$name" } } }
In this case, the dependsOn
method shows that this is part of the configuration process rather than execution. Each variant name, like friendlyDebug
, is capitalized (FriendlyDebug
) and then the corresponding installation task (installFriendly
Debug
) is added as a dependency to the installDebugFlavors
task.
The result is during the configuration process, installArrogantDebug
, installFriendlyDebug
, and installObsequiousDebug
are all added as dependencies to installDebugFlavors
. Therefore, executing installDebugFlavors
at the command line requires all three flavor installs.
Example 4. Installing all the debug flavors
./gradlew instDebFl :app:preBuild UP-TO-DATE :app:preArrogantDebugBuild UP-TO-DATE :app:checkArrogantDebugManifest // ... lots of tasks ... :app:assembleArrogantDebug UP-TO-DATE :app:installArrogantDebug Installing APK 'app-arrogant-debug.apk' on 'Nexus_5_API_23(AVD) - 6.0' Installed on 1 device. :app:checkFriendlyDebugManifest // ... lots of tasks ... :app:assembleFriendlyDebug UP-TO-DATE :app:installFriendlyDebug Installing APK 'app-friendly-debug.apk' on 'Nexus_5_API_23(AVD) - 6.0' Installed on 1 device. :app:checkObsequiousDebugManifest // ... lots of tasks ... :app:assembleObsequiousDebug UP-TO-DATE :app:installObsequiousDebug Installing APK 'app-obsequious-debug.apk' on 'Nexus_5_API_23(AVD) - 6.0' Installed on 1 device. :app:installDebugFlavors BUILD SUCCESSFUL
You can see that writing your own custom tasks requires at least some knowledge of Groovy. An extensive discussion is therefore a bit beyond the scope of this book, but there are several good Groovy resources available. Additional Groovy concepts are defined in this book as they occur.
See Also
The Gradle plug-in User Guide (see not available) shows available properties in the android
object. The documentation for the Copy
, Zip
, or other Gradle tasks is found on the Gradle website. not available and not available have background information on the Groovy programming language and basic Gradle information, respectively.