Gradle task doesn't execute in Android Studio - android

I've tried to get a gradle task to execute for a lib module 'lib1' in an Android Studio project. It should run with command 'gradlew assembleDebug' or 'gradlew assemble' but it never runs.
task copy(type: Copy, dependsOn: ':lib1:assembleDebug') << {
println "copying"
}
I tried a simpler task with no dependency and it never seems to run either.
task hello << {
println 'hello world'
}
This runs but it's only in the configuration phase.
task hello {
println 'hello world'
}
I need to get a copy to work in the execution phase after the library module assembled. Any clues what to do?

You need to add your task to the task dependency graph somehow. Typically, by making an existing task depend on it. In this case, copy depends on assembleDebug, which simply means, if you run the copy task, assembleDebug must run first. This does not mean that running assembleDebug will cause copy to run. Add this to your build.
assemble.dependsOn copy
Now running gradlew assemble will cause the copy task to execute.
Your second task is correctly defined but again, no other task depends on it so it will only execute if you run it explicitly via gradlew hello or by adding a dependency as mentioned above.
Your third task prints a line during the configuration phase because that closure is evaluated only during that phase. It is the << operator that adds a doLast action which is run at execution time.

Related

Android run Gradle task after app install

need help with Gradle tasks. I need to run some "taskX" after an app was installed (after "installDebug" task). I've also tried to make the task like this:
task taskX(type: Exec, dependsOn: 'installDebug') {
commandLine 'sh', './myScript.sh'
}
but it didn't execute.
I actually can do this by Android Studio build configuration, but I also want to do this by Gradle wrapper.

Run custom task before ALL possible packaging tasks in gradle android project

I have a gradle project named data-android that applies the com.android.library plugin. Before the packaging phase I want a custom task of my own (named copySqlMigrations) to be executed. This task copies a bunch of assets into the project tree.
I have made many attempts, but none of them work universally.
The closest I got was adding the following to the end of my gradle file.
afterEvaluate {
assemble.dependsOn copySqlMigrations
assembleDebug.dependsOn copySqlMigrations
assembleRelease.dependsOn copySqlMigrations
}
This only works if I call e.g. gradle assembleDebug directly, but when I want to launch my APK (for which my library project is a dependency), this fails spectacularly.
Error:(56, 1) A problem occurred configuring project ':app'.
> Could not resolve all dependencies for configuration ':app:_debugApk'.
> A problem occurred configuring project ':data-android'.
> Could not get unknown property 'assembleDebug' for project ':data-android' of type org.gradle.api.Project.
How can I always call :data-android:copySqlMigrations before this project is being packaged up? I'm looking for a solution that works with all build flavors and all potential invocations (build/run/debug).
Gradle has a TaskContainer accessible via (project.)tasks. This container is also a TaskCollection containing all tasks. One can query a subset TaskCollection via the matching method and, thanks to some magic, the new TaskCollection is live. So, whenever a new task gets added to the parent TaskCollection (or the TaskContainer) and it matches the closure of the matching method, the subset TaskCollection will contain it. Together with the TaskCollection all method one can handle each task following a pattern whenever it is created.
For the problem stated in your question, I wrote and tested the following build file:
task assembleX { }
task copySqlMigrations { }
task assembleY { }
tasks.matching { task ->
task.name.startsWith('assemble')
}.all { task ->
task.dependsOn copySqlMigrations
}
task assembleZ { }
You can call each assemble* task and it will call copySqlMigrations as a dependency. Of course, you can modify the matching closure to fit your needs.

Gradle Exec task running from command line build but not from Android build

I am attempting to execute a python script from a Gradle task of type Exec. My main build task has a dependency on this task. Let's for this example call my build task assembleProjectDebug. Let's simplify the example also to this:
tasks.create(name: newFooTask, type: Exec) {
commandLine "python", "doSomething.py"
}
tasks[assembleProjectDebug].dependsOn(newFooTask)
If I run ./gradlew assembleProjectDebug from a terminal, my python script executes and all is well in the world. However if I attempt to build from Android Studio with Build -> Make Project, my python script will not execute.
I can confirm as well that my currently selected build variant is set to projectDebug, and can also confirm that when building from Android Studio, :app:assembleProjectDebug appears in the log leading me to believe that assembleProjectDebug task is or will be executed (I could be wrong there).
For the sake of brevity I have also left out where I assign an environment variable in my task which points my $PATH variable to the location of my python exec.
Is there any reason why, outside of me messing up the assignment of a proper $PATH variable for the subprocess, that a command line build will execute this task, yet a build from within Android Studio will not execute this task?
It's likely you'll need to set the workingDir on the Exec task
Eg:
tasks.create(name: newFooTask, type: Exec) {
commandLine "python", "doSomething.py"
workingDir = projectDir
}
I found a solution to my problem. Building from within Android Studio, my task dependency was not being executed as it was when building from the command line. This was due to having Configure on Demand selected in Android Preferences -> Build, Execution, Deployment -> Compiler. Android Studio applies this setting by default. You can read more about Configure on Demand here:
Configure on Demand in Gradle

Gradle - Which task creates the 'build' directory?

I'm using Android Studio 1.3.2 on Mac.
Gradle version is listed as 2.2.1, Android Plugin version 1.3.1.
I have applied the FindBugs Gradle plugin, and I've created a task that successfully runs the analysis on the directory 'build/intermediates/classes'.
To trigger this task on Gradle Sync, I've added it as a dependency to the preBuild task, like this:
preBuild.dependsOn findBugs
The problem with this dependency is that, at time of preBuild, the generated class files are either non-existent (first sync) or stale (remaining from previous sync). Basically, I want my task to run immediately after the 'build/intermediates/classes' directory is created, or when the files there are refreshed as part of the 'Sync' operation.
Looking at the tasks available, I can see the 'clean' task has the following description:
clean - Deletes the build directory.
However, none of the other tasks I see describe the directory's creation. My first thought was "Well, it's got to be the build task, right?". Unfortunately, as usual, it's not that simple (pressing gradle 'sync' button, does not trigger my task when I've added it as a dependency to the 'build' task). Is no such task available? If so, which task would best suit what I'm trying to achieve?
You can see all tasks using ./gradlew tasks
The build task is the main one. It builds everything, generates APKs and runs all checks.
I recommend you adding the following to the build.gradle file:
check.dependsOn 'findbugs'
So when you run the check task, it will execute findbugs as well.
Then also set a dependency on findBugs for the compilation task:
task findbugs(type: FindBugs, dependsOn: 'compileDebugSources') {...}
This will compile the source in case you run findbugs without previously compiling it.

How to execute an Ant target task in build.gradle?

How can I get the task associated with an Ant target to execute from within the build.gradle file?
The part in build.gradle which imports the build.xml file:
def targetSdk = android.defaultConfig.targetSdkVersion.getApiLevel()
ant.properties['android.version'] = "android-$targetSdk"
ant.properties['sdk-location'] = SDK_DIR
ant.importBuild(rootDir.absolutePath + "/bcproj/build.xml")
The ant target I want to execute is named compile-android. It successfully runs at the command line with:
./gradlew compile-android
But I'd like to include this in build.gradle so I can specify which ant target needs compiling for each buildType. In all my googling, all I could find references for is getting it to compile at the command line.
Update 1
I've tried adding the compile-android task as a dependency to another task that gets executed along with the build process. Though conceptually the two are really independent of each other. This still failed in getting compile-android to execute.
task copyShopMetadata(type: Exec, dependsOn: 'compile-android') {
workingDir rootDir
commandLine './copy_shop_metadata.sh'
}
copyShopMetadata.execute()
I've tried reversing the dependency, still doesn't work.
Task t = tasks.findByName('compile-android')
t.dependsOn(copyShopMetadata)
copyShopMetadata.execute()
Update 2
I should note that adding the dependency examples above does work when executing from the command line. However my end goal here is to be able to hit "sync project with gradle files" in Android Studio and have the the compile-android ant target compile. Perhaps this just isn't possible?
Assuming your task is not intended to be independent of all other processing, you're going to want your task to be depended on by some other task, which means that when you try to run that other task, your task will be executed first. That task might be "build" for instance, so you might do something like this:
project.build.dependsOn("compile-android")
(I'm not certain of the exact syntax for this.)
Ok, looks like the problem was a misunderstanding on my part for what the "Sync Project with Gradle" button was doing. It is not the equivalent of executing a build from the command line. It's not until I actually hit the run button in Android Studio does it perform the compile-android task. As hitting the run button is what's equivalent to the command line.

Categories

Resources