=====Compatibilité=====
* Java
^Java^Minimum Gradle^
|8|2.0|
|9|4.3|
|10|4.7|
|11|5.0|
|12|5.4|
|13|6.0|
|14|6.3|
|15|6.7|
|16|7.0|
|17|7.3|
|18|7.5|
|19|7.6|
|20|8.3|
[[https://docs.gradle.org/current/userguide/compatibility.html|Compatibility Matrix]] {{ :prog:gradle:compatibility_matrix_18_08_2023_14_26_14_.html |Archive du 2023 le 18/08/2023}}
=====Options en ligne de commande=====
Pour améliorer la vitesse de compilation, essayer d'activer les options ''%%--parallel --daemon --configuration-cache --build-cache%%''
=====build.gradle=====
====Android====
===Debug / Release===
* Pour du ''Debug'' :
shrinkResources false
minifyEnabled false
debuggable true
jniDebuggable true
ndk {
debugSymbolLevel 'FULL'
}
packagingOptions {
doNotStrip '**/*.so'
}
* Pour du ''Release'' :
''minifyEnabled'' se met à ''false'' pour les librairies sinon le fichier ''classes.jar'' sera vide et il ne sera pas possible de utiliser la librairie externe sous Android Studio.
''shrinkResources'' se met à ''false'' pour une librairie.
''shrinkResources'' se met à ''false'' si ''minifyEnabled'' est déjà à ''false''.
''minifyEnabled'' se met à ''false'' si on souhaite utilise ''jni'', y compris dans l'application principale en Android avec JNI qui utilise une librairie avec NDK.
shrinkResources true
minifyEnabled true
debuggable false
jniDebuggable false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
Attention, il existe les fichiers ''proguard-android-optimize.txt'' et ''proguard-android.txt''. Les deux sont destinés au release. Le fichier ''optimize'' ajoute des optimisations qui peuvent être incompatibles avec certains programmes. [[https://developer.android.com/studio/build/shrink-code|Shrink, obfuscate, and optimize your app]], {{ :prog:gradle:shrink_obfuscate_and_optimize_your_app_android_developers_22_09_2022_14_09_51_.html |Archive du 19/09/2022 le 22/09/2022}}
* Non compatible
Le champ ''testBuildType'' est commun entre ''debug'' et ''release''. Il faut donc trouver un moyen de savoir si on veut en ''release'' ou ''debug''.
android {
testBuildType 'debug'
gradle.startParameter.taskNames.each{value ->
if (value.indexOf('ebug') != -1)
testBuildType 'debug'
else if (value.indexOf('elease') != -1)
testBuildType 'release'
}
...
===API===
Voir [[lang:android:retro_compatibility#choix_des_versions_des_api|Choix des versions des api]].
===NDK===
* CMake
Il n'est pas possible de voir les logs de CMake pour la configuration et la compilation. Il faut aller voir directement les fichiers :
build/intermediates/cxx/*/*/logs/*/configure_stdout.txt
build/intermediates/cxx/*/*/logs/*/configure_stderr.txt
build/intermediates/cxx/*/*/logs/*/build_stdout_project.txt
build/intermediates/cxx/*/*/logs/*/build_stderr_project.txt
====Java====
* Ajouter des options de compilation
android {
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
...
====Task====
* Ajout d'une tâche
Cette tâche exécute un script ''generate_assets.py'' qui génère des fichiers ''draw1.xml'' à ''draw10.xml''.
Renseigner ''inputs'' et ''outputs'' va servir uniquement à relancer la task si l'un de ces fichiers est modifié. [[https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:task_outcomes|Authoring Tasks]] ou [[https://github.com/gradle/gradle/blob/master/subprojects/docs/src/docs/userguide/authoring-builds/more_about_tasks.adoc|Authoring Tasks Github]] {{ :prog:gradle:authoring_tasks_08_06_2023_14_44_01_.html |Archive du 24/05/2023 le 08/06/2023}}
task generateAssets(type: Exec) {
int startDelay = 100;
int endDelay = 10000;
int stepDelay = 100;
inputs.files("${project.projectDir}/../tools/generate_assets.py")
for (int i = 1; i <= 10; i = i + 1) {
outputs.files file("${project.projectDir}/src/main/res/drawable/draw" + i.toString() + ".xml")
}
workingDir "${project.projectDir}/../tools"
commandLine 'python', 'generate_assets.py'
}
Code ne fonctionnant pas avec configuration cache :
outputs.upToDateWhen {
def result = exec {
workingDir '../tools'
commandLine 'python', 'generate_assets.py', '100', '10000', '100', 'dry-run'
ignoreExitValue = true
}
return result.exitValue == 0
}
Code ne fonctionnant pas car la modification des fichiers n'est pas détectée :
outputs.files fileTree("${project.buildDir}/many").matching { include '*.txt' }
Ajout d'une dépendance entre deux tâches :
tasks.whenTaskAdded { task ->
if (task.name.startsWith('compile')) {
task.dependsOn generateAssets
}
}
====Ligne de commandes====
Les paramètres des lignes de commande sont accessibles depuis un fichier ''build.gradle''.
* ''project.gradle.startParameter.logLevel.name() == 'DEBUG%%'%%'' permet de savoir si l'option ''%%--%%debug'' a été appliquée.
====Debug====
Afficher des messages dans la console pour afficher la valeur des variables.
project.logger.lifecycle('my message visible by default')
====plugins====
===pmd===
* Quand tout va bien
Il suffit de rajouter en plus d'un plugin ''java'' ou un de ses dérivés (''java-library'', ''com.android.library'', ''com.android.application'') :
plugins {
id 'pmd'
}
et une configuration :
pmd {
consoleOutput = true
toolVersion = "6.55.0"
ignoreFailures = true
threads = 2
ruleSets = [
"category/java/bestpractices.xml",
"category/java/codestyle.xml",
"category/java/design.xml",
"category/java/documentation.xml",
"category/java/errorprone.xml",
"category/java/multithreading.xml",
"category/java/performance.xml",
"category/java/security.xml"]
}
Pour vérifier qu'il y a bien la bonne tâche d'ajoutée, il faut exécuter ''gradlew tasks'' et voir un ou plusieurs tâches
lib:pmdMain - Run PMD analysis for main classes
lib:pmdTest - Run PMD analysis for test classes
* Tâches manquantes
Dans le cas d'un projet Android avec du ndk, je n'ai pas réussi à faire fonctionner ''pmd'' de façon native. Il faut alors forcer la création de la tâche.
android {
tasks.register("pmd", Pmd) {
consoleOutput = true
ignoreFailures = true
ruleSets = [
"category/java/bestpractices.xml",
"category/java/codestyle.xml",
"category/java/design.xml",
"category/java/documentation.xml",
"category/java/errorprone.xml",
"category/java/multithreading.xml",
"category/java/performance.xml",
"category/java/security.xml"]
source 'src'
include '**/*.java'
exclude '**/build/**'
threads = 2
reports {
xml.enabled = false
html.enabled = true
html {
destination = file("$project.buildDir/reports/pmd/pmd.html")
}
}
}
}
pmd {
toolVersion = "6.55.0"
}
[[https://raw.githubusercontent.com/nextcloud/android/38d337846f563f20ce6a854dbb9cada6ca0769b0/app/build.gradle|build.gradle nextcloud/android]] {{ :prog:gradle:build.gradle.txt |Archive du 17/04/2023 le 17/04/2023}}
* Désactiver des règles spécifiques
Il faut passer par un fichier de config spécifique.
My custom rules
Et mettre dans ''build.gradle'' :
ruleSetFiles = files('config/pmd/rules.xml')
[[https://docs.pmd-code.org/latest/pmd_userdocs_making_rulesets.html#bulk-adding-rules|Making rulesets]] {{ :prog:pmd:making_rulesets_pmd_source_code_analyzer_12_05_2023_09_40_55_.html |Archive du 25/11/2022 le 12/05/2023}}
* Ignorer certaines erreurs
Ajouter sur la ligne indiquée par pmd le commentaire ''%%//%% NOPMD''
[[https://pmd.github.io/pmd/pmd_userdocs_suppressing_warnings.html|Suppressing warnings]] {{ :prog:pmd:suppressing_warnings_pmd_source_code_analyzer_16_05_2023_08_54_54_.html |Archive du 27/04/2023 le 16/05/2023}}
===checkstyle===
* Quand tout va bien
Il suffit de rajouter en plus d'un plugin ''java'' ou un de ses dérivés (''java-library'', ''com.android.library'', ''com.android.application'') :
plugins {
id 'checkstyle'
}
et une configuration :
checkstyle {
toolVersion '10.9.3'
configFile file("config/checkstyle/checkstyle.xml")
}
Pour vérifier qu'il y a bien la bonne tâche d'ajoutée, il faut exécuter ''gradlew tasks'' et voir un ou plusieurs tâches
lib:checkstyleMain - Run Checkstyle analysis for main classes
lib:checkstyleTest - Run Checkstyle analysis for test classes
* Tâches manquantes
Dans le cas d'un projet Android avec du ndk, je n'ai pas réussi à faire fonctionner ''checkstyle'' de façon native. Il faut alors forcer la création de la tâche.
android {
tasks.register('checkstyleMain', Checkstyle) {
configFile = file('config/checkstyle/checkstyle.xml')
source 'src'
include '**/*.java'
exclude '**/build/**'
classpath = files()
}
}
checkstyle {
toolVersion '10.9.3'
}
Le fichier ''checkstyle'' peut se récupérer directement dans le code de l'application (penser à bien configurer ''toolVersion'') : [[https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml|google_checks.xml]]
[[https://raw.githubusercontent.com/nextcloud/android/38d337846f563f20ce6a854dbb9cada6ca0769b0/app/build.gradle|build.gradle nextcloud/android]] {{ :prog:gradle:build.gradle.txt |Archive du 17/04/2023 le 17/04/2023}}
===javadoc===
* Quand tout va bien
javadoc {
source = sourceSets.main.allJava
classpath = configurations.compile
}
* Tâches manquantes
Pour un projet Android et/ou avec du code généré, il peut être nécessaire d'utiliser le code généré par la compilation Java.
android {
tasks.register("javadoc${variant.name.capitalize()}", Javadoc) {
source = variant.sourceSets.collect { it.java.sourceFiles }.inject { m, i -> m + i }
doFirst {
classpath = project.files(variant.javaCompileProvider.get().classpath.files,
project.android.getBootClasspath(),
"${project.buildDir}/intermediates/javac/${variant.name}",
"${project.buildDir}/generated/data_binding_base_class_source_out/${variant.name}/out")
}
options.addBooleanOption('Xdoclint:all', true)
dependsOn "assemble${variant.name.capitalize()}"
// To enable error on warning
// options.addStringOption('Xwerror', '-quiet')
}
}
====Messages d'erreur====
* kotlin
Execution failed for task ':app:checkDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
> Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.internal.jdk7.JDK7PlatformImplementations found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.internal.jdk7.JDK7PlatformImplementations$ReflectSdkVersion found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.internal.jdk8.JDK8PlatformImplementations found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.internal.jdk8.JDK8PlatformImplementations$ReflectSdkVersion found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.io.path.ExperimentalPathApi found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.io.path.PathRelativizer found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.io.path.PathsKt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.io.path.PathsKt__PathReadWriteKt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.io.path.PathsKt__PathUtilsKt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.jdk7.AutoCloseableKt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk7-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21)
Duplicate class kotlin.jvm.jdk8.JvmRepeatableKt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.random.jdk8.PlatformThreadLocalRandom found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.streams.jdk8.StreamsKt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$1 found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$2 found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$3 found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.streams.jdk8.StreamsKt$asSequence$$inlined$Sequence$4 found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.text.jdk8.RegexExtensionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Duplicate class kotlin.time.jdk8.DurationConversionsJDK8Kt found in modules jetified-kotlin-stdlib-1.8.10 (org.jetbrains.kotlin:kotlin-stdlib:1.8.10) and jetified-kotlin-stdlib-jdk8-1.6.21 (org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21)
Go to the documentation to learn how to Fix dependency resolution errors.
Il manque le plugin kotlin. Même si vous n'utilisez pas de kotlin, les dépendances le peuvent.
plugins {
id 'org.jetbrains.kotlin.android' version '1.8.10'
}
[[https://stackoverflow.com/questions/75263047/duplicate-class-in-kotlin-android|Duplicate class in Kotlin Android]] {{ :prog:gradle:java_-_duplicate_class_in_kotlin_android_-_stack_overflow_22_06_2023_10_49_54_.html |Archive du 27/01/2023 le 22/06/2023}}
=====Erreurs=====
====Certificats====
* ''Unable to find valid certification path to requested target''
* ''Connection refused: connect''
C'est évidemment un problème de certificat à cause d'un serveur faisant du ''DPI'' (''Deep Packet Inspection'').
Il faut l'installer dans la machine virtuelle Java. Faire également la même chose pour [[ide:android_studio:preferences#dpi|Android Studio]].
Regarder le contenu de la variable ''JAVA_HOME'' (''C:\jdk-11.0.15+10'' par exemple).
Aller dans le dossier ''C:\jdk-11.0.15+10\lib\security'' en ligne de commande.
Et lancer la commande ''../../bin/keytool -importcert -file /path/to/your/certificate/my-root-ca-cert.cer -keystore cacerts -storepass changeit -noprompt''
Avec ''changeit'' le mot de passe par défaut et ''my-root-ca-cert.cer'' le certificat du serveur ''DPI''.
Il est nécessaire de redémarrer la session car l'application ''gradle'' tourne peut-être en arrière plan.
[[https://stackoverflow.com/questions/26697118/android-studio-unable-to-find-valid-certification-path-to-requested-target|Android Studio - Unable to find valid certification path to requested target]] {{ :prog:gradle:gradle_-_android_studio_-_unable_to_find_valid_certification_path_to_requested_target_-_stack_overflow_21_02_2023_16_43_22_.html |Archive du 02/11/2014 le 21/02/2023}}