Gradle android: Where should I put my custom task? - android

I want to add a custom task to my Gradle build file.
Should this go inside the android configuration closure or not?
I tried both and they seem to work fine and I couldn't find any explicit mention in the docs.

the task definition should usually not go into the android blog and on root level as zeventh suggests. though it sometimes useful to do this in the android block. especially when you create these tasks dynamically.
In the following example I create one task for each build variant:
android{
applicationVariants.all{ variant ->
def variantTask = task("${variant.name}CustomTask", type:CustomTask){
...
}
check.dependsOn variantTask
}
}

You should just put the task at the root level of the file, outside the android closure.
task yourTask << {
println "Hello world"
}

Related

How to add gradle's task parameter in Android Studio?

We are going to debug our Android app by adding some properties in app.properties and pre-process it in the Kotlin codes.
We wrote build.gradle like:
task dailytest {
doLast {
File testProperty = new File('assets/app.properties')
testProperty.append("\ndaily_test=true")
testProperty.append("\nfps_sample_interval_ms=")
testProperty.append(fps_sample_interval_ms)
testProperty.append("\ndrop_stack_sample_interval_ms=")
testProperty.append(drop_stack_sample_interval_ms)
testProperty.append("\nmin_drop_count_to_log=")
testProperty.append(min_drop_count_to_log)
}
}
And we compile it in command line using:
./gradlew dailytest -Pfps_sample_interval_ms="100" -Pdrop_stack_sample_interval_ms="100" -Pmin_drop_count_to_log="1" :connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.myapp.sub.MainActivityTest#test_click_shelf
I was wondering if maybe we could run this test case in Android Studio by adding some confirmations?
We did try to add ::dailytest in the Before launch part, but we couldn't manage to find a way to add the custom parameters.
You can have an afterEvaluate block in your build.gradle to run your task when you build your app, something like this:
afterEvaluate {
lint.dependsOn dailytest
}

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)

Why can't I use gradle task connectedDebugAndroidTest in my build script?

I can refer to connectedCheck task (which came from android plugin) from my build script:
connectedCheck.finalizedBy AndroidShowTestResults
But trying to use connectedDebugAndroidTest (which came from android plugin too)
connectedDebugAndroidTest.finalizedBy AndroidShowTestResults
gives me
Error:(48, 0) Could not find property 'connectedDebugAndroidTest' on project ':app'.
And if I try
task connectedDebugAndroidTest << {print '123'}
it curses me with
Error:Cannot add task ':app:connectedDebugAndroidTest' as a task with that name already exists.
I don't undestand why I cannot refer to connectedDebugAndroidTest?
Available gradle tasks are shown below:
The android plugin defers the addition of several tasks especially those that have buildType or flavor names in them till a very late stage of the configuration phase. Which in turn means if you try to refer to these yet-to-be-added-tasks by name, you're likely to see a "does not exist" type error messages. If you want to add dependencies around deferred-created tasks, you should wait until configuration is complete:
gradle.projectsEvaluated {
connectedDebugAndroidTest.finalizedBy AndroidShowTestResults
}
Alternatively, you can add a listener to task-graph events, so you can do stuff as soon as a certain task is added to task-graph:
tasks.whenTaskAdded { task ->
if (task.name == 'connectedDebugAndroidTest') {
task.finalizedBy AndroidShowTestResults
}
}
Try
task connectedTest(dependsOn: ["connectedDebugAndroidTest"]){
}
connectedTest.finalizedBy "AndroidShowTestResults"
I think you should try to open test and rebuild.

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 {}

Gradle: How to run custom task after an Android Library is built?

I have an Android Library, it's generating a debug.aar and a release.aar, I need to copy the release.aar to another folder as a reference to other part of the project.
What I've done now is in this Android Library build.gradle I defined a task:
task copyAARToCommonLibs(type: Copy) {
from('../build/outputs/aar') {
include '*-release.arr'
}
into '../SomeSampleApps/libs'
}
I'm trying to run this task after the arr is generated, which I assume is assembleRelease stage, so I tried do this in this build.gradle
assembleRelease.doLast{
copyAARToCommonLibs
}
I build the overall project using
gradle build
But this task is running at the very beginning of the whole process.
I also tried this:
applicationVariants.all { variant ->
variant.assemble.doLast {
copyAARToCommonLibs
}
}
inside android{} property(I guess that's what it's called?)
Running gradle build, got this error: Could not find property 'applicationVariants'
I then came across this snippet:
tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn copyAARToCommonLibs }
But it seems this makes the task to run after compiling, I don't know exactly how to modify this to run after assemble.
Could someone please correct me where I did wrong and how can I get this copy task work after the .arr file is generated?
It seems that finalizedBy might be helpful.
assembleRelease.finalizedBy(copyAARToCommonLibs)
Mind the fact that in the following way you won't define a dependency:
assembleRelease.doLast {
copyAARToCommonLibs
}
actually.. it does exactly nothing. You need to execute the task:
assembleRelease.doLast {
copyAARToCommonLibs.execute()
}
but running task in the following way is discouraged and very bad practice.
You can also try:
assembleRelease.doLast {
copy {
from('../build/outputs/aar') {
include '*-release.aar'
}
into '../AscendonSDKSamples/libs'
}
}
I went with finalizedBy() but had to include it within an afterEvaluate...
afterEvaluate {
if (gradle.startParameter.taskNames.contains(":app:assembleFatReleaseInternal")) {
play.enabled = true
play.commit = true
play.track = "internal"
play.releaseStatus = "completed"
play.releaseName = versionName
generateFatReleaseInternalBuildConfig.dependsOn set_build_date
assembleFatReleaseInternal.finalizedBy(uploadCrashlyticsSymbolFileFatReleaseInternal)
uploadCrashlyticsSymbolFileFatReleaseInternal.finalizedBy(publishFatReleaseInternal)
}
}
This worked well for automating the upload of native symbols to Fabric / Crashlytics and other things such as automated play store publishing.
Because android studio add task by dynamic,so assembleRelease will not be recognized.
Just add hook after task added event happens.
tasks.whenTaskAdded {
theTask ->
if (theTask.name.contains('externalNativeBuild')) {
theTask.doLast{
println "[*] begin to copy file."
}
}
// println theTask.name
}

Categories

Resources