Ignore Gradle Build Failure and continue build script? - android

Managing Android's dependencies with Gradle is done in a weird way. They have to be downloaded differently into a local repo. This is a pain when setting up CI build as there are multiple nodes this could run on. As such I'm using the sdk-manager-plugin to have the Android dependencies downloaded at build time. There seems to be an old bug that I'm experiencing with the sdk-manager-plugin though in that it will download the dependencies at build time, but they won't be available on that command.
The next time the command is run everything works fine (as everything is already downloaded), but I need to find a way to ignore the build failure of the first gradle command so that everything is downloaded and good to go for the second. I realize this is hacky, but I'm done messing with this.
Ideally something like this would work:
./gradlew clean --ignoreBuildFailures
./gradlew distributeCIBuild
The closest thing I could find in the Gradle documentation is --quite but that doesn't look like it'd work.
Any creative solutions welcome.

The flag to use is --continue.
From the documentation:
Continues task execution after a task failure.

add this in the build.gradle file :
tasks.withType(JavaCompile) {
options.failOnError(false)
}

You can use ignoreExitValue
task ktlint(type: JavaExec, group: "verification") {
description = "Check Kotlin code style."
ignoreExitValue = true
}

Related

maven-metadata.xml keeps getting requested when building

AGP 4.2.2
gradle-6.7.1
arcticfox 2020.3.1
Everytime I build my android project I see this maven-metadata.xml and it just seems to slow the build and it just seems to hang there. Which can take 10 minutes for each build.
Is there a way to avoid this?
Gradle: Download maven-metadata.xml...
When I run one the command line I see this:
This is my gradle.properties
org.gradle.jvmargs=-Xmx8g -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=256m -XX:+UseCompressedOops -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configureondemand=true
kotlin.coroutines=enable
kotlin.code.style=official
kapt.use.worker.api=true
kapt.incremental.apt=true
android.enableD8.desugaring=true
android.useAndroidX=true
android.enableJetifier=true
I am using some maven repositories as specified here in build.gradle(app):
maven { url "https://www.jitpack.io" }
maven { url 'http://......./repo/maven2' }
maven { url "https://....../repositories/snapshots" }
maven { url 'https://....../maven/release' }
maven { url "http://......./bintray.com/maven" }
maven { url "https://....../objectbox/objectbox" }
Gradle usually needs to download a maven-metadata.xml file, if
you use a dynamic/changing version for one of your dependencies, and
the time to live (TTL) in the dependency cache is over.
For (1) you should look for versions like 1.2.3-SNAPSHOT or 1.2.+ on your declared dependencies (or at ./gradlew dependencies for simplicity). If you have any such versions, do you really need them? Using fixed versions like 1.2.3 should be faster.
For (2), have you maybe changed the default TTL threshold or do you maybe always build with --refresh-dependencies? If not, then the slowness should at least not occur more often than once a day.
If the above doesn’t help, then maybe try running your build with --info or --info --refresh-dependencies and carefully watch the log output. That should show which dependency and/or which repository is the culprit (i.e., the one on which the logging is stuck for the longest time). If you find such a culprit, then you could look into things like
replacing the dependency (or the repository),
improving the speed of the repository server or the network, or
pruning old snapshot versions from the problematic maven-metadata.xml file (if you control the repository).
If all this still doesn’t turn up actionable items, then maybe it could be worth looking for bigger maven-metadata.xml files in your Gradle dependency cache. Maybe the repeated download of such big files is the issue and one of the approaches from the previous list could help. Here’s an idea for how to find the ten biggest maven-metadata.xml files (with a Unix shell command):
find ~/.gradle/caches/modules-2/resources-* \
-name maven-metadata.xml \
-printf '%s\t%p\n' \
| sort -k1 \
| tail
The question is kind of insufficient to tell, because no build.gradle had been provided. But I'd assume, that the reason is any -SNAPSHOT dependency, which is not being cached. Building against a local copy of that dependency should result in not downloading the maven-metadata.xml over and over again; or use mavenLocal(). Building against a stable version should also result in caching.
Other answers give very good context on why this happens. Especially when using -SNAPSHOT dependencies, if you have no other way, I have a trick for you that might help a lot.
It is to use offline mode 🎉
When running via CLI, do
./gradlew someTask --ofline
When running via IDE, enable offline mode.
The cause of slow downloads for maven-metadata.xml files is that one of your proxy repositories has a very slow remote.
This problem will be compounded if either of the "metadata max age" and "not found cache ttl" settings is set too low. Thus it will check the circle too fast and download it everytime from scratch. Turn it up to 12 hours. Default should be 30min (1800sec) what is a too short period of time.
For setting the max age you can simple follow along this site.
Another good article to manage Http Cache Headers.
Chriki answer directed me in the right direction to find a simple solution. After you have downloaded all dependencies (in my case, I am using -SNAPSHOT library, which wants to be updated on every run), you can set Gradle in offline mode. This will prevent Gradle to download new metadata, etc.
In Android Studio you have a dedicated button to toggle online mode (see image
Android studio settings).

Real time rules with ktlint

I am trying to use ktlint on my android project.
Currently I am using these gradle plugins:
org.jlleitschuh.gradle.ktlint
org.jlleitschuh.gradle.ktlint-idea
I can check the code using a manual gradle task, where the warnings will be displayed by the terminal.
Is it possible to achive something like eslint in javascript? Example:
Perhaps the following advice does not directly solve your requirement. But, what about making the auto format process part of the build process? I mean, your code will be auto formatted and then checked according to the ktlint rules and you only will be worried about to run the build command (i.e. ./gradlew clean build) before committing your code. This is how I have done that:
First of all, I am using Gradle 6.3 and I have implemented the version 9.1.2 of org.jlleitschuh.gradle.ktlint plugin.
Once the plugin has been imported to the project, some tasks are added as the plugin's documentation describes:
This plugin adds two maintasks to every source set: ktlint[source set name]SourceSetCheck and ktlint[source set name]SourceSetFormat
Usually the added tasks are:
ktlintMainSourceSetCheck and ktlintMainSourceSetFormat for src/kotlin/main source set
ktlintTestSourceSetCheck and ktlintTestSourceSetFormat for src/kotlin/test source set
In order to make ktlintMainSourceSetFormat and ktlintTestSourceSetFormat part of the build process, you should add the following gradle action inside subprojects { } section:
For kotlin-based gradle scripts (build.gradle.kts):
afterEvaluate {
tasks["ktlintMainSourceSetCheck"].dependsOn(tasks["ktlintMainSourceSetFormat"])
tasks["ktlintTestSourceSetCheck"].dependsOn(tasks["ktlintTestSourceSetFormat"])
}
For groovy-based gradle scripts (build.gradle):
afterEvaluate {
tasks.getByName('ktlintMainSourceSetCheck').dependsOn(tasks.getByName('ktlintMainSourceSetFormat'))
tasks.getByName('ktlintTestSourceSetCheck').dependsOn(tasks.getByName('ktlintTestSourceSetFormat'))
}
This makes the "format" tasks mentioned above run before the "check" tasks after the build process of the current sub project has succeeded. These "check" tasks are the ones that display formatting errors in the console whenever the build is run, but making them children of the "format" tasks will force the build process to format the code before checking it so that no formatting errors will show up in the console.
Additionally, you can also apply code checks and formats to build script files (build.gradle(.kts)) by adding the following code inside allprojects { } section:
afterEvaluate {
tasks["ktlintKotlinScriptCheck"].dependsOn(tasks["ktlintKotlinScriptFormat"])
}
For Git support:
If you want to add the auto formatting feature at pre-commit stage, you can use these tasks: addKtlintCheckGitPreCommitHook and addKtlintFormatGitPreCommitHook as explained here
For IntelliJ IDEA support:
If you want to apply the ktlint rules to your current project, just execute the following gradle command once you have imported the org.jlleitschuh.gradle.ktlint-idea plugin: ./gradlew ktlintApplyToIdea and this will replace the codeStyles file inside .idea/ folder as described here
Finally, here is an example of a build.gradle.kts where all the mentioned above is applied.
You will not get an error message like in eslint but using following method you won't need to deal with ktlint styling issues manually. Is not it much better than manually fixing things up?
Install ktlint commandline tools as described here.
Set IntelliJ IDEA's code styles to align with ktlint's code styles as described here.
So when you make a commit using IntelliJ IDEA's commit window (CTRL + K or Command + K) and you have reformat code before commit enabled then your commit will be made with correct code styles.
Try to install plugin Ktlint ​(unofficial)​ and follow setup instructions.
Go to Preferences > Tools > ktlint and make sure Enabled ktlint checkbox is selected.
In case of android project also select Android mode check box.

java.lang.IllegalStateException: Dex archives: setting .DEX extension only for .CLASS files

I build the project at gitlab ci
./gradlew assembleDebug --stacktrace
and sometimes it throws an error:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> com.android.build.api.transform.TransformException: java.lang.IllegalStateException: Dex archives: setting .DEX extension only for .CLASS files
At my local pc it works correctly.
kotlin version is 1.2
multidex is enabled
What is the reason of this error?
./gradlew clean fixed the same error for me.
For Cordova developers,
If you get this build error in your project, as said Pierrick Martellière in the comments of this answer, in you project folder use :
cordova clean
It makes a cleaning and a build immediately
It seems I found the solution.
At the build moment gradle was showing warnings for me:
Configuration 'compile' in project ':app' is deprecated. Use 'implementation' instead.
app: 'androidProcessor' dependencies won't be recognized as kapt annotation processors. Please change the configuration name to 'kapt' for these artifacts: 'com.arello-mobile:moxy-compiler:1.5.3' and apply the kapt plugin: "apply plugin: 'kotlin-kapt'".
I made a misspelling and forgot to remove unnecessary annotationProcessor for library:
annotationProcessor "com.arello-mobile:moxy-compiler:$moxyVersion"
kapt "com.arello-mobile:moxy-compiler:$moxyVersion"
So I removed first line.
After that I applied kapt plugin apply plugin: 'kotlin-kapt' and fixed some build errors in code after it.
After all I realized that I forgot to replace compile to implementation in some places. It is weird but without it build didn't work.
This changes fix my error build.
Simple Solution
For Ionic and Cordove Projects
cordova clean
Above answer is mostly right but in my case, i get this exception when i crate same name java and kotlin file then deletes one of them.
Solutions are: just Build -> Clean Project my project and it works. And my project also enabled multiDex.
defaultConfig {
...
// Enabling multidex support.
multiDexEnabled true
}
As mentioned above by #mixel cleaning gets the job done. But as an option not to do it manually just add the gradle 'clean' task into app run configuration so it will be done all the time before launch. Of cource, it can slow down the whole process a bit.
I was able to get the problem to go away by closing and restarting Android Studio. Perhaps even a Rebuild Project would have done it as well (did not try that though).
Configuring for multidexing did not solve this issue for me.
However I did come up with a resolution...of sorts. Basically it involved creating a pull request for a second branch on the same commit as the build that was failing. The build for this pull request succeeded, and then Bitbucket thought that the original pull request was ok and allowed us to merge, even though we had made no changes on that branch. There is some unexplained weirdness there but the technique worked.
Here's how I did it:
Assume that the branch that is failing is called bad-branch.
I created a new branch called bad-branch-copy on the commit that was common between bad-branch and develop. Then I merged bad-branch into bad-branch-copy. The end result of this was a fast forward such that bad-branch-copy ended up on the same commit as bad-branch. I was expecting a separate commit so this result surprised me, but I was grasping at straws anyway so I kept going.
I then pushed bad-branch-copy to GitHub and created a pull request from bad-branch-copy to develop. This triggered a build on bad-branch-copy -> develop, which was successful.
At that point, buddybuild showed a successful build on bad-branch-copy -> develop and still showed a failure on bad-branch -> develop. However, Bitbucket showed a successful build on the pull request for bad-branch. Yes, that's right: buddybuild showed a failure but Bitbucket said it was ok.
We were then able to merge the bad-branch pull request and all was well with the world. Please don't ask me why, I will not answer. :)
I think the same thing could be accomplished with
git checkout bad-build
git checkout -b bad-build-copy
git push origin bad-build-copy
followed by creating a pull request for bad-build-copy.
Currently using Android Studio 3.3.2 I just disabled the instant run and it worked.
What resolved the issue for me was manually adding all the conflicting files manually. For example in my gradle file I had:
implementation 'com.android.support:support-compat:27.1.1'
it was underlined with red. I hovered over the line and android studio said there was a conflict with another file using a lower version. The error was similar to
come.android.support:support-annotations:26.0.1 conflicts/mix versions with 27.1.1.
It gave me the names of the files and I manually added them with the corresponding version so they would all match
compile 'com.android.support:support-annotations:27.1.1'
compile 'com.android.support:support-compat:27.1.1'
compile 'com.android.support:support-core-ui:27.1.1'
compile 'com.android.support:animated-vector-drawable:27.1.1'
compile 'com.android.support:appcompat-v7:27.1.1'
compile 'com.android.support:design:27.1.1'
None of the current solutions worked for me and it was fixed by simply disabling Instant Run.
please find here the solution of this problem,
defaultConfig {
...
minSdkVersion 14
targetSdkVersion 21
...
// Enabling multidex support.
multiDexEnabled true
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}

How to Build AAR and Sample Application

I'm running into a collection of gradle problems in setting up a multi-module project. I'm trying to produce an AAR that contains an SDK for our customers use. I'm also trying to produce a sample application that uses that AAR both as a development platform internally and as an example for our customers of how to use the platform.
settings.gradle:
include :sdk
include :SampleApplication
build.gradle:
...
// copy the AAR produced by the SDK into the SampleApplication
task import_aar(type: Copy) {
dependsOn ":sdk:build"
from(new File(project(':sdk').getBuildDir(), 'outputs/aar')) {
include '*-release.aar'
rename '(.*)-release.aar', '$1-v1.0.0.aar'
}
into new File(project(':SampleApplication').projectDir, 'aars')
}
...
SampleApplication/build.gradle:
...
repositories {
...
flatDir {
dirs 'aars'
}
}
...
dependencies {
...
// This causes gradle to fail if the AAR hasn't been copied yet
compile 'com.moxiesoft.netagent:moxieMobileSDK:+#aar'
compile project(':moxieMobileSDK')
...
}
So the biggest problem that I'm having right now is getting the import_aar task to run before the compileDebug/ReleaseSources tasks. I've tried adding explicit dependencies to the compile tasks, but I'm apparently not finding the right way to do it.
I've tried putting this in SampleApplication/settings.gradle:
tasks['compileReleaseSources'].dependsOn(':import_aar')
but gradle fails because there's no compileReleaseSources task, even though gradle :SampleApplication:tasks shows one.
I also tried putting similar stuff in settings.gradle, but it also failed with an error that the task compileReleaseSources didn't exist.
I did have limited success by putting this in my SampleApplication/settings.gradle:
tasks['build'].dependsOn(':import_aar')
But that only has the correct affect if I use "gradle build", which doesn't happen if I'm debugging or running from Android Studio.
I was finally able to get this to work by putting the dependsOn on the preBuild task, but I'm still not particularly happy with the solution, because:
It requires me to have the aar in place before gradle runs, which
means I wind up putting the .aar into git, which isn't a
particularly good idea.
I'd rather not have the AAR generation leaking into the
SampleApplication/build.gradle file, since that's intended for
customer usage.
Is there a better way of handling the problem in general?
I also had problem adding a dependency to compileReleaseSources task and described here a solution that worked for me. In short, the dependency need to be added in tasks.whenTaskAdded closure.

Android studio - How to use an executable jar file from gradle

So I have a custom_rules.xml file Im trying to rebuild in gradle. so far I have no problem figuring everything else out but the last part Im trying to accomplish is running a special apk signing tool for widevine drm on the unsigned apk that I generate with my gradle build process. Ive been looking online and in the gradle documentation all day but I have yet to find how to run an executable jar file from gradle. I know I have to create a task but thats about it. Any help would be much appreciated.
PS. Ive read a lot of the gradle documentation so please spare me any read the docs responses
EDIT:
this is what my task looks like at the moment and it compiles but Im not sure its actually doing anything
task (runApkSigTool , dependsOn: 'android', type: JavaExec) {
classpath files('apksigtool.jar')
main 'com.widevine.tools.android.apksigtool.ApkSigTool'
args[0] = apkLocation
args[1] = 'private_key.der'
args[2] = 'my.crt'
}
Im not sure if I have to use it like a method in the android section of my build.gradle file or what.
You could probably use the JavaExec task. Something like this:
task signApk(type: JavaExec) {
classpath files('path/to/executable.jar')
main 'com.foo.MainClass'
args ['-foo', 'bar']
}

Categories

Resources