Custom Tasks hooking on to all flavors of a given buildtype

Hmm…! So I’m working on an android gradle plugin and I’m trying perform a custom action that hooks off of the package and compile steps of an android gradle project. I’d like to trigger this action in response to each buildType (e.g., compileRelease, compileDebug, and packageRelease, packageDebug), but I’d also like a local reference to the current buildtype’s configuration properties.

Right now I’m solving this by making a pluginRelease task and pluginDebug task (with the only difference being that one uses android.buildTypes.release.debuggable and the other uses android.buildTypes.debug.debuggable), but this seems brittle it especially won’t work well if the user adds extra build types and flavors.

Does anyone have any suggestions as to a better, less brittle, means of implementing this?

You say you declare two specific tasks (one for each buildtype?) To declare a task for each buildtype dynamically and use its debuggable flag, you can do something like this:

android.buildTypes.all{ theBuildType ->
 task ("${theBuildType.name}MyCustomTask")<<{
    //use debuggable flag
           println theBuildType.debuggable
   }
}

is this the snippet you’re looking for?

cheers, René

Ah! Interesting. I think I can use this to solve the other part of my question to.

So the other part was how do I access from a task the “current buildtype”, e.g., android.buildTypes.release.debuggable, but if I use the closure as you’ve suggested, I have a reference to that buildType via “it”, so I can do it.debuggable!

Thanks! I’ll try this out.

Ok! This mostly worked but I ran into one problem. I’m having trouble adding a dependency to the android “compileDebug” task

I tried to get the reference to compileDebug a bunch of ways, e.g., tasks.getByPath(":${project.name}:compile${buildName}").dependsOn … project.“compile${buildName}”.dependsOn …

but received Task with path ‘:App:compileDebug’ not found in project ‘:App’. and other similar errors.

Is there a standard way to dynamically access and add dependencies to default tasks?

Thanks much!

I think one problem is that the taskname is case sensitive. try this

android.buildTypes.all{ theBuildType ->
 task ("${theBuildType.name}MyCustomTask"){
   dependsOn "compile${theBuildType.name.capitalize()}"
   //use debuggable flag
  doLast{
           println theBuildType.debuggable
    }
 }
}

Yup! I am doing that. I should say that I’m not trying to make MyCustomTask depend on compile, I’m trying to make compile depend on my custom task. That way, my custom task always occurs in builds that have applied my plugin.

So in my example above I’m trying to access “compile${theBuildType.name.capitalize()}” to make it dependOn("${theBuildType.name}MyCustomTask")

Is there a preferred way of doing this type of code-dependency insertion from a plugin? I’m surprised that I wasn’t able to dynamically access the compileDebug task to add the dependOn because before I apply my plugin, I am able to build the script and I see a task named :App:compileDebug

Ah, as a side note I tried println’ing the current tasks of a project:

[task ‘:App:assemble’, task ‘:App:assembleDebug’, task ‘:App:assembleRelease’, task ‘:App:build’, task ‘:App:buildDependents’, task ‘:App:buildNeeded’, task ‘:App:check’, task ‘:App:clean’, task ‘:App:connectedCheck’, task ‘:App:deviceCheck’, task ‘:App:uninstallAll’]

so I imagine part of my problem is I am trying to add a dependency to something that is lazily instantiated?

Is it better to make my tasks default tasks that must occur after compileDebug? Or make assemble, which exists in this case, depend on my task, but add that my task must occur after compileDebug?

So it looks like findbugs does so magic here:

https://github.com/ajoberstar/gradle-plugins/blob/master/src/main/groovy/org/ajoberstar/gradle/findbugs/FindbugsPlugin.groovy

which I’m not sure I totally understand. They call

project.plugins.withType(JavaBasePlugin) {

configureForJavaPlugin(project, convention)

}, then inside that configure method add the check.dependsOn

Is there something special I have to do to add dependencies to the android compileDebug task?

I digged a bit into the android plugin. The problem is that the tasks are created in the “project.afterEvaluate” hook. I’m currently on travel, I’ll have another look once I got a chance and provide a solution.

cheers, René

Rene, you are super helpful! As an intermediate hack I was able to configure my tasks to depend on the compileDebug during afterEvaluate. It says that in Gradle 2.0 that this will be deprecated, so in the meantime perhaps it’d be good for me to ask the android plugin folks if there is anything they can do on their end to help support these kinds of hooks.

If you know of any recommended ‘gradle way’ methods I should be doing this instead of my hacky solution, feel free to let me know, as I’d be interested in hearing about it.

what is the detailed deprecation warning? We want to provide another mechanism in the future to not force the android plugin to do the task creation in the afterevaluate hook.

One way to declare the dependency would be

tasks.whenTaskAdded{ theTask ->
      if(theTask.name.equals("compile${theBuildType.name.capitalize()}"){
          theTask.dependsOn "${theBuildType.name}MyCustomTask"
      }
}
1 Like

Thanks, worth noting, swap ‘buildTypes’ with ‘productFlavors’ to have a task per flavor too

The way to do this would be:

android {

applicationVariants.all { com.android.build.gradle.api.ApplicationVariant variant ->

someOtherTask.dependsOn variant.packageApplication

someOtherTask.dependsOn variant.javaCompile

} }

You can see ‘ApplicationVariant’ and friends here: https://android.googlesource.com/platform/tools/build/+/master/gradle/src/main/groovy/com/android/build/gradle/api/

@Christopher Jenkins: Thanks a ton for pointing this out!