gradle custom task order on Android - android

I have 2 gradle tasks that i want to run after assembleRelease task.
task copyRequiredFilesToVersionControl(type:Copy) {
...
}
task ('versionControl') << {
...
}
If I configure order for these tasks as below tasks get never called...
copyRequiredFilesToVersionControl.dependsOn(assembleRelease)
versionControl.dependsOn(copyRequiredFilesToVersionControl)
If i change order like;
assembleRelease.dependsOn(copyRequiredFilesToVersionControl)
versionControl.dependsOn(copyRequiredFilesToVersionControl)
Tasks are run at the beginning of document. So there is no file to copy and add to version control.
What is the best approach?

I have found method that called doLast. So i fixed my problem with it.
assembleRelease {
doLast {
tasks.versionControl.execute()
}
}

The best approach that I've found to date, has been to use the Ordering Tasks feature in Gradle : see http://www.gradle.org/docs/current/userguide/more_about_tasks.html for more documentation, currently section 15.5.
Basically, you have two rules available : MUST run after and SHOULD run after. I like the rule quite a bit, I use this to create zip archives of projects automatically. NOTE : you must still make use of the "dependsOn" to get proper execution if tasks that you need to have run in a particular order.

Related

Generated code stays in build folder after Android Studio Build

I am using a gradle task to generate some code for my API and store this code into the build folder. When I am building my application the process deletes the build folder.
Is there a way to call my code generation task between the folder deletion and the start of the compilation?
I am not a Gradle expert, so their might be better answers!
In your build.gradle you can create custom tasks and make them depend on other tasks:
// this is your new task
task generateCode() {
description 'Generates some code...'
doLast {
println("generateCode")
// do your code generation here
}
}
// put the name of the task you wanna depend on, like: compileSources
project.task("compileSources").dependsOn generateCode
When you call this task ./gradlew compileSources you should see that the custom task generateCode gets executed first.
After allot of trying , i found the solution .
In the build.gradle i had to add the preBuild.finalizedBy(generateCode)

Android Gradle - Check which task is being executed

In my gradle file I want to know which task triggered the code block. e.g. If I run
gradle assembleVanillaDebug
from the terminal, I want to know in my gradle file that assembleVanillaDebug task is being executed. This will also help me in figuring out I am running debug build type task or release build type task.
Can we know which task is being executed?
In the end,
gradle.startParameter.taskNames
proved to be my friend. gradle.startParameter.getTaskNames() would return you the list of all tasks being executed in current build.
e.g. For gradle clean assembleVanillaDebug, it will return you a list of tasks clean and assembleVanillaDebug.
Seeing this is still the first hit on google when you search for listing tasks, I thought I'd share the better way I found of getting all tasks that are being scheduled:
// Doc: Returns the tasks which are included in the execution plan.
// The tasks are returned in the order that they will be executed.
gradle.taskGraph.allTasks
As opposed to gradle.startParameter which is meant for finding out how gradle has been started, this gives you a list of actual task objects that gradle queues for execution.
Edit:
Make sure the graph is resolved before using it. It should be available when running a task action, for example in a doFirst {}, or try running your code in the whenReady{} closure like so:
project.gradle.taskGraph.whenReady {
println(project.gradle.taskGraph.allTasks)
}

How to make conditional build task on android build gradle

In android, we would like to make one app build with different application id depends on the pre-installed app package.
So it contains flavor in the build gradle with different applicationId set.
But we don't want all these flavors been build, we just want to only build the one based on pre-installed app package name to save sometime on build server.
If used
task prepareA(dependsOn:['assembleADebug']){}
task prepareB(dependsOn:['assembleBDebug']){}
task prepareTest(dependsOn:['prepareA', 'prepareB']) {}
Then when called prepareTest, both prepareA and prepareB would be executed with both assembleADebug and assembleBDebug executed.
I only want to build either prepareA or prepareB be executed based on one condition check (if ...).
The answer I found after some hours invesigation, it is that we can use afterEvaluate method, which would execute before dependsOn is running.
Remove the predefined dependsOn the the prepareA and prepareB.
Then
afterEvaluate {
if (isPackageInstalled(packageName)) {
tasks.findByName("prepareTest").dependsOn("prepareA")
} else {
tasks.findByName("prepareTest").dependsOn("prepareB")
}
}

Could not find property 'uninstallDebug' on project

In my project I want to run my custom task "MyTask" to run before uninstall happens. Code for the same is
uninstallDebug.dependsOn "MyTask"
When I run this, it fails with an error
Could not find property 'uninstallDebug' on project
whereas, I see a gradle task listed in the Gradle window with that name.
What may be going wrong?
project.afterEvaluate { p ->
p.tasks.uninstallDebug.doFirst {
println 'before uninstall'
}
}
gradle.taskGraph.whenReady {
// if your MyTask is in the same project
uninstallDebug.dependsOn "MyTask"
// if it is else where
uninstallDebug.dependsOn project("someProject").project("subProject).tasks["MyTask"]
}
uninstallDebug along with several other tasks, especially those that have flavor or buildType name in their name are created and added to the gradle taskGraph quite late in the configuration step by the android plugin. What that means, as you have discovered is that you may not be able to refer to them by name early in the config step since they do not exist yet.
The way around this as the other answers point out is to wait until the tasks in question are added to the taskgraph. You can use your line uninstallDebug.dependsOn "MyTask" in either gradle.taskgraph.whenRead{} or project.afterEvaluate {}

Want to run a custom gradle task only when running Unit test

How to set up gradle to run a particular custom copy task, only when running unit tests?
EDIT
I want to run these tasks when i press build, i. e only in the flavor of the build with unit test execution included.
I've finally found the solution, with the help of this documentation which presents all the tasks that run during build, test, release etc. in a very concise manner. So by making tasks clean, preBuild depend on my copyTask I can ensure that the copy task is run every time the project is cleaned or built.
But since I don't want to run this during building or cleaning process but want to run it when I only run tests, I identified a task that compiles release unit test sources called the compileReleaseUnitTestSources but just mentioning it in build.gradle as
compileReleaseUnitTestSources.dependsOn(myCopyTask)
doesn't actually work, because gradle will give an error saying it cannot find the task compileReleaseUnitTestSources as for some reason that task is not available yet. Instead by enclosing it in a afterEvaluate block we can ensure that this block is executed after all tasks are evaluated, that way we have access to that task now, So finally I added this to my build.gradle
afterEvaluate {
compileReleaseUnitTestSources.dependsOn(copyResDirectoryToClasses)
}
All the answers here mention to use the dependsOn keyword to attach my task to another task that is run during general build/test execution, but none of them mentioned how to go around the problem where gradle is not able to find the tasks even though you know for sure that these tasks were available and run during build/test execution.
you have to set up a "customCopyTask" and make the "test-task" which does the unittests depend on the "customCopyTask" like this
task customCopyTask(type: Copy) {
from sourceSets.test.resources
into sourceSets.test.output.classesDir
}
test.dependsOn customCopyTask
You can make some task finalizing another, in that case this task will run only if another one was called, right after it. This could be done as:
task runUnitTest << {
println 'running tests'
}
task copyTestResults << {
println 'copying results'
}
//make copyTestResults finalize runUnitTest
runUnitTest.finalizedBy copyTestResults
You can read about it in the official user guide.
Additionally, if your unit test could be up-to-date and you don't want to run you copy task in that case, you can check the test task status and skip copy-task, as:
task copyTestResults {
doFirst {
//chtck anothe task status and skip this one if it didn't actually work
if (!tasks.getByName("runUnitTest").getState().didWork) {
throw new StopExecutionException();
}
}
doLast{
println 'copying results'
}
}
Or, if you just need to run copy-task before unit tests, make the test task depending on copy-task by setting it's dependsOn property, read about it with a number og examples here

Categories

Resources