Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
prog:gradle [2023/01/06 10:08] – Ajout de "Options en ligne de commande" root | prog:gradle [2023/08/18 14:32] (Version actuelle) – Ajout de la compilatibilité Java / Gradle root |
---|
| =====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===== | =====Options en ligne de commande===== |
| |
===Debug / Release=== | ===Debug / Release=== |
| |
Pour du ''Debug'' : | * Pour du ''Debug'' : |
| |
<code groovy> | <code groovy> |
</code> | </code> |
| |
Pour du ''Release'' : | * 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. | ''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. |
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}} | 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''. |
| |
| <code groovy> |
| android { |
| testBuildType 'debug' |
| gradle.startParameter.taskNames.each{value -> |
| if (value.indexOf('ebug') != -1) |
| testBuildType 'debug' |
| else if (value.indexOf('elease') != -1) |
| testBuildType 'release' |
| } |
| |
| ... |
| </code> |
===API=== | ===API=== |
| |
Voir [[lang:android:retro_compatibility#choix_des_versions_des_api|Choix des versions des 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 : |
| |
| <code> |
| 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 |
| </code> |
====Java==== | ====Java==== |
| |
</code> | </code> |
| |
====Mise à jour==== | ====Task==== |
| |
* ''com.android.tools.build'' et de la version de Gradle | * Ajout d'une tâche |
| |
Bien mettre à jour la classe ''com.android.tools.build'' du ''build.gradle'' en même temps que le champ ''distributionUrl'' de Gradle dans le fichier ''gradle-wrapper.properties''. | Cette tâche exécute un script ''generate_assets.py'' qui génère des fichiers ''draw1.xml'' à ''draw10.xml''. |
| |
Voir la page [[https://developer.android.com/studio/releases/gradle-plugin|Gradle Plugin]] pour la compatibilité entre la version de gradle et son plugin. | 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}} |
| |
Voir la page [[https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google|Maven]] pour la dernière version disponible de la classe ''com.android.tools.build:gradle''. | <code groovy> |
| task generateAssets(type: Exec) { |
| int startDelay = 100; |
| int endDelay = 10000; |
| int stepDelay = 100; |
| |
Il est aussi possible de lancer la commande suivante deux fois : | 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> |
| |
<code bash> | Code ne fonctionnant pas avec configuration cache : |
./gradle wrapper --gradle-version --7.5.1 | |
| <code groovy> |
| outputs.upToDateWhen { |
| def result = exec { |
| workingDir '../tools' |
| commandLine 'python', 'generate_assets.py', '100', '10000', '100', 'dry-run' |
| ignoreExitValue = true |
| } |
| return result.exitValue == 0 |
| } |
</code> | </code> |
| |
| Code ne fonctionnant pas car la modification des fichiers n'est pas détectée : |
| |
| <code groovy> |
| outputs.files fileTree("${project.buildDir}/many").matching { include '*.txt' } |
| </code> |
| |
| Ajout d'une dépendance entre deux tâches : |
| |
| <code groovy> |
| tasks.whenTaskAdded { task -> |
| if (task.name.startsWith('compile')) { |
| task.dependsOn generateAssets |
| } |
| } |
| </code> |
====Ligne de commandes==== | ====Ligne de commandes==== |
| |
| |
* ''project.gradle.startParameter.logLevel.name() == 'DEBUG%%'%%'' permet de savoir si l'option ''%%--%%debug'' a été appliquée. | * ''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. |
| |
| <code groovy> |
| project.logger.lifecycle('my message visible by default') |
| </code> |
| |
| ====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'') : |
| |
| <code groovy> |
| plugins { |
| id 'pmd' |
| } |
| </code> |
| |
| et une configuration : |
| |
| <code groovy> |
| 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"] |
| } |
| </code> |
| |
| 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 |
| |
| <code> |
| lib:pmdMain - Run PMD analysis for main classes |
| lib:pmdTest - Run PMD analysis for test classes |
| </code> |
| |
| * 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. |
| |
| <code groovy> |
| 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" |
| } |
| </code> |
| |
| [[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. |
| |
| <file xml rules.xml> |
| <?xml version="1.0"?> |
| |
| <ruleset name="Custom Rules" |
| xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd"> |
| |
| <description> |
| My custom rules |
| </description> |
| |
| <rule ref="category/java/bestpractices.xml"> |
| </rule> |
| <rule ref="category/java/codestyle.xml"> |
| </rule> |
| <rule ref="category/java/design.xml"> |
| </rule> |
| <rule ref="category/java/documentation.xml"> |
| <exclude name="CommentRequired"/> |
| </rule> |
| <rule ref="category/java/errorprone.xml"> |
| </rule> |
| <rule ref="category/java/multithreading.xml"> |
| </rule> |
| <rule ref="category/java/performance.xml"> |
| </rule> |
| <rule ref="category/java/security.xml"> |
| </rule> |
| </ruleset> |
| </file> |
| |
| Et mettre dans ''build.gradle'' : |
| |
| <code> |
| ruleSetFiles = files('config/pmd/rules.xml') |
| </code> |
| |
| [[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'') : |
| |
| <code groovy> |
| plugins { |
| id 'checkstyle' |
| } |
| </code> |
| |
| et une configuration : |
| |
| <code groovy> |
| checkstyle { |
| toolVersion '10.9.3' |
| configFile file("config/checkstyle/checkstyle.xml") |
| } |
| |
| </code> |
| |
| 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 |
| |
| <code> |
| lib:checkstyleMain - Run Checkstyle analysis for main classes |
| lib:checkstyleTest - Run Checkstyle analysis for test classes |
| </code> |
| |
| * 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. |
| |
| <code groovy> |
| android { |
| tasks.register('checkstyleMain', Checkstyle) { |
| configFile = file('config/checkstyle/checkstyle.xml') |
| source 'src' |
| include '**/*.java' |
| exclude '**/build/**' |
| classpath = files() |
| } |
| |
| } |
| |
| checkstyle { |
| toolVersion '10.9.3' |
| } |
| </code> |
| |
| 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 |
| |
| <code groovy> |
| javadoc { |
| source = sourceSets.main.allJava |
| classpath = configurations.compile |
| } |
| </code> |
| |
| * 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. |
| |
| <code groovy> |
| 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') |
| } |
| } |
| </code> |
| |
| ====Messages d'erreur==== |
| |
| * kotlin |
| |
| <code> |
| 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 <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>. |
| |
| </code> |
| |
| Il manque le plugin kotlin. Même si vous n'utilisez pas de kotlin, les dépendances le peuvent. |
| |
| <code groovy> |
| plugins { |
| id 'org.jetbrains.kotlin.android' version '1.8.10' |
| } |
| </code> |
| |
| [[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}} |