How to cache dependency of a detached gradle configuration on CI? - android

I'm trying to generate a full cache of dependencies for all project/scripts configurations before assemble step. I'd like to use --offline gradle flag for all jobs except the caching one.
So android plugin provides androidDependencies task which resolves all resolvable dependencies of a project
Previously we used a custom task which does the same:
task resolveDependencies {
description "Resolves all projects dependencies from the repository."
group "Build Server"
doLast {
rootProject.allprojects { project ->
project.buildscript.configurations.forEach { configuration ->
if (configuration.canBeResolved) {
try {
configuration.resolve()
} catch (ignored) {
}
}
}
project.configurations.forEach { configuration ->
if (configuration.canBeResolved) {
try {
configuration.resolve()
} catch (ignored) {
}
}
}
}
}
}
Unluckily some gradle scripts which are activated during assemble step use detachedConfigurations. These configurations are not visible and solved neither with androidDependencies task nor with the custom one
For example, android gradle build plugin throws the error during assemble step:
Execution failed for task ':app:mergeDebugResources'.
> A failure occurred while executing com.android.build.gradle.internal.res.Aapt2CompileRunnable
> Could not isolate value com.android.build.gradle.internal.res.Aapt2CompileRunnable$Params_Decorated#3d617643 of type Aapt2CompileRunnable.Params
> Could not resolve all files for configuration ':app:detachedConfiguration1'.
> Could not resolve com.android.tools.build:aapt2:7.1.3-7984345.
Required by:
project :app
> No cached version of com.android.tools.build:aapt2:7.1.3-7984345 available for offline mode.
Is it possible to solve all detached configurations before the assemble task?
For now the only solution i see is to cache dependencies as well after the assemble task and forget about using --offline
Please also check related topic on circleCi forum

Related

Android - Starting custom gradle task after build

Using Gradle 7.0.2 with the new Android Gradle Plugin I try to start a copy task which copies a file in the build folder.
The script looks something like this
androidComponents {
onVariants(selector().withBuildType("debug"), {
def copyTestTask = tasks.register("copyTest", Copy) {
from(file('../../local/test.txt'))
into(buildDir)
logger.lifecycle("DEST: $buildDir")
}
// build.dependsOn copyTestTask
// tasks.getByPath(':app:processDebugResources') {
// it.dependsOn(copyTestTask)
// }
})
}
The comments are my first tries to add to copy task in my assembleDebug/assembleRelease build. They do not call my copy task.
My questions:
What is the correct way to set the dependency to my task?
Which build task should depend on my copy job?

Android Build failure : Could not get unknown property 'assembleDebug' for project

I need to create Jar and copy to lib folder, which is done in following task :
task copyJarToLib(type: Copy, dependsOn: 'createJar') {
from "build/libs/lib1.jar"
from "build/libs/lib2.jar"
into "../App/libs/"
}
I have to execute this after apk generation. So, I am calling following instruction at the end of the module-app build.gradle :
assembleDebug.finalizedBy(copyJarToLib)
Issue is observed after upgrading the gradle plugin to 3.1.0 and gradle to 4.4.
Same implementation is working fine with gradle 2.3.
If you want to execute something at the end of build, you can do it as follows:
gradle.buildFinished {
copy {
from "build/libs/lib1.jar"
from "build/libs/lib2.jar"
into "../App/libs/"
}
}
If you want to execute task before apk is built the you can:
afterEvaluate {
project.tasks.findByName('preDebugBuild').dependsOn(':<module>:copyJarToLib')
}
base on Android Studio 2020.3.1, you can use follow codes
afterEvaluate {
project.tasks.findByName('preDebugBuild').dependsOn(copyJarToLib)
}

How to copy debug assets for unit tests

I have an android library gradle project. And I need to copy some files to assets folder for robolectric unit tests.
To do it I've defined a copy task:
task copyDebugAssets(type: Copy) {
from "${projectDir}/somewhere"
into "${buildDir}/intermediates/bundles/debug/assets"
}
but I can't add this task as a dependency for processDebugResources task:
processDebugResources.dependsOn copyDebugAssets
because of this error:
Could not get unknown property 'processDebugResources' for object of type com.android.build.gradle.LibraryExtension.
Now I have to manually execute this task before unit test:
./gradlew clean copyDebugAssets test
How can I solve it?
The android plugin adds several tasks dynamically. Your .dependsOn line doesn't work because at the time gradle is trying to process this line, processDebugResources task yet available. You should tell gradle to add the dependency as soon as the upstream task is available:
tasks.whenTaskAdded { task ->
if (task.name == 'processDebugResources') {
task.dependsOn copyDebugAssets
}
}
Why copy? Configure where the assets should be pulled from:
android {
// other cool stuff here
sourceSets {
androidTest {
assets.srcDirs = ['../testAssets']
}
}
}
(replacing ../testAssets with a path to where the assets should come from)
I have used this successfully with androidTest for instrumentation testing. AFAIK, it should work for test or any other source set.

Gradle extend assembleRelease

on gradle 2.1.3 I could do:
assembleRelease
{
doFirst()
{
//some code
}
}
But when I updated to gradle 2.2.0 I get an error:
Error:(12, 1) A problem occurred evaluating project ':MyProj'.
> Could not find method assembleRelease() for arguments [build_6dlppzyvvovwra7h55acb4kp$_run_closure1#543a3981] on project ':MyProj' of type org.gradle.api.Project.
Can you please help me with that?
It seems to be a common issue for version update to 2.2.0. You can find some similar questions on SO, for example here. But they all lead to a common workaround - rewrite your task this way:
tasks.whenTaskAdded { task ->
if (task.name == 'assembleRelease') {
task.doFirst {
//some code
}
}
}
Not sure, but it seems, that assembleRelease is not available at the moment you try to point it in your script since 2.2.0 version.

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.

Categories

Resources