9
votes

DexArchiveMergerException uniquement à la sortie

J'ai développé une application qui utilise un client Java généré par swagger. Le client est dans un projet appelé "api", tandis que l'application est dans un projet appelé "app".

Quand je construis l'application via Build / Make Project , tout fonctionne correctement. De plus, lorsque j'essaie d'exécuter l'application sur un appareil émulé ou physique, Run / Run 'app' . L'exécution avec le débogueur fonctionne également. Même lorsque je construis le projet via Buid / Generate Signed Bundle / APK et que je choisis l'option de débogage, cela fonctionne.

Maintenant. La compilation échoue lorsque j'essaie de créer une version de version signée. Les messages suivants s'affichent:

Provoqué par: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Erreur lors de la fusion des archives dex: [...] \ app \ build \ intermediates \ transforms \ dexBuilder \ release \ 54, [. ..] \ app \ build \ intermediates \ transforms \ externalLibsDexMerger \ release \ 0, [...] \ app \ build \ intermediates \ transforms \ dexBuilder \ release \ 52.jar, [...] \ app \ build \ intermédiaires \ transforms \ dexBuilder \ release \ 53.jar


Causé par: com.android.builder.dexing.DexArchiveMergerException: Erreur lors de la fusion des archives dex: [...] \ app \ build \ intermediates \ transforms \ dexBuilder \ release \ 54, [...] \ app \ build \ intermediates \ transforms \ externalLibsDexMerger \ release \ 0, [...] \ app \ build \ intermediates \ transforms \ dexBuilder \ release \ 52.jar, [...] \ app \ build \ intermediates \ transforms \ dexBuilder \ release \ 53.jar


Causé par: com.android.tools.r8.CompilationFailedException: échec de la compilation


Causé par: com.android.tools.r8.utils.AbortException: Erreur: Type de programme déjà présent: io.swagger.client.ApiCallback

Je suis assez nouveau dans le développement avec Android Studio et Gradle. J'ai essayé des solutions sur Stack Overflow qui suggéraient déjà d'ajouter des bibliothèques, mais jusqu'à présent, aucune d'elles n'a fonctionné avec mon problème.

Pour moi, c'est particulièrement suspect que le dernier message d'erreur pointe vers io. swagger.client.ApiCallback .

Cela pourrait-il avoir quelque chose à voir avec le fait que les deux settings.gradle pour "api" et "app" ont le même contenu? Les deux ressemblent à ceci: rootProject.name = "swagger-java-client" . C'est la seule ligne du fichier, mais pour autant que je sache, le settings.gradle pour "app" a déjà ce contenu. Je ne me souviens pas de l'avoir changé, donc c'est étrange pour moi qu'il montre "swagger-java-client". Est-ce normal?

Mise à jour 1

ProGuard a été mentionné dans les commentaires comme pouvant être un problème. C'est le seul événement que j'ai pu trouver, en le référençant. Dans ma build.gradle pour le projet "app", il y a cette partie:

buildscript {
    repositories {
        maven { url 'https://maven.fabric.io/public' }
    }

    dependencies {
        classpath 'io.fabric.tools:gradle:1.+'
    }
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "projectName"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "0.1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation fileTree(dir: '../api/build/libs', include: ['*.jar'])
    implementation 'com.google.code.gson:gson:2.8.2'
    implementation 'com.squareup.okhttp:okhttp:2.7.5'
    api project(path: ':api')
    implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
    implementation 'org.jetbrains:annotations-java5:15.0'
}

Cependant, sa suppression n'a rien changé.

Mise à jour 2

Lorsque vous recherchez "io.swagger" AS ne trouve que ceci:

 une seule correspondance trouvée p >

Lors de la recherche de "io.swagger.client.ApiCallback" AS ne trouve que ceci:

une seule correspondance trouvée

Mise à jour 3

Comme suggéré, j'ai essayé d'ajouter

apply plugin: 'idea'
apply plugin: 'eclipse'

group = 'io.swagger'
version = '1.0.0'

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.0'
        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
    }
}

repositories {
    jcenter()
}


if(hasProperty('target') && target == 'android') {

    apply plugin: 'com.android.library'
    apply plugin: 'com.github.dcendents.android-maven'

    android {
        compileSdkVersion 25
        buildToolsVersion '25.0.2'
        defaultConfig {
            minSdkVersion 14
            targetSdkVersion 25
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7
        }

        // Rename the aar correctly
        libraryVariants.all { variant ->
            variant.outputs.each { output ->
                def outputFile = output.outputFile
                if (outputFile != null && outputFile.name.endsWith('.aar')) {
                    def fileName = "${project.name}-${variant.baseName}-${version}.aar"
                    output.outputFile = new File(outputFile.parent, fileName)
                }
            }
        }

        dependencies {
            provided 'javax.annotation:jsr250-api:1.0'
        }
    }

    afterEvaluate {
        android.libraryVariants.all { variant ->
            def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
            task.description = "Create jar artifact for ${variant.name}"
            task.dependsOn variant.javaCompile
            task.from variant.javaCompile.destinationDir
            task.destinationDir = project.file("${project.buildDir}/outputs/jar")
            task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
            artifacts.add('archives', task);
        }
    }

    task sourcesJar(type: Jar) {
        from android.sourceSets.main.java.srcDirs
        classifier = 'sources'
    }

    artifacts {
        archives sourcesJar
    }

} else {

    apply plugin: 'java'
    apply plugin: 'maven'

    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7

    install {
        repositories.mavenInstaller {
            pom.artifactId = 'swagger-java-client'
        }
    }

    task execute(type:JavaExec) {
       main = System.getProperty('mainClass')
       classpath = sourceSets.main.runtimeClasspath
    }
}

dependencies {
    compile 'io.swagger:swagger-annotations:1.5.21'
    compile 'com.squareup.okhttp:okhttp:2.7.5'
    compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
    compile 'com.google.code.gson:gson:2.8.2'
    compile 'org.threeten:threetenbp:1.3.5'
    testCompile 'junit:junit:4.12'
}

et d'ajouter android.enableD8 = false mais cela n'a pas aidé non plus.

Voici mes fichiers build.gradle (les premiers qui ont causé les problèmes, sans les corrections suggérées que j'ai essayées jusqu'à présent.)

build.gradle (Module: api ) (généré par Swagger):

android {
    defaultConfig {
        multiDexEnabled true
    }
}

build.gradle (Module: app):

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}


4 commentaires

Question rapide, le problème disparaît-il lorsque vous désactivez ProGuard? Si tel est le cas, vos paramètres ProGuard nécessitent l'ajout d'exclusions!


@JakeSteam comme je l'ai dit, je suis assez nouveau dans le classement, mais j'ai mis à jour la question pour adresser ProGuard


Pouvez-vous publier votre fichier de note?


@SharpMobileCode terminé


3 Réponses :


1
votes

Causé par: com.android.tools.r8.utils.AbortException: Erreur: Type de programme déjà présent: io.swagger.client.ApiCallback

Signifie qu'il y a plusieurs dépendances contenant cette classe, peut-être des versions différentes, vous devez donc les exclure.

  1. Appuyez deux fois sur shift, recherchez io.swagger, puis enregistrez les fichiers jar trouvés.

  2. Si ces fichiers jar sont simplement dupliqués, gardez 1 dans build.gradle.


  1. Si ces fichiers jar sont des modules d'autres dépendances, entrez gradlew -q app: dependencies dans le terminal, recherchez les noms de dépendance racine.

  2. Dans build.gradle, choisissez 1 dépendance à conserver, pour les autres, ajoutez la commande d'exclusion.

Par exemple, remplacez

implementation ('xxx:xxx') { exclude module 'module-name-to-be-excluded' }

par

implementation 'xxx:xxx'

UPDATE strong>

Quelques options à essayer:

Modifiez les variantes de construction des deux modules à publier, puis Build \ Build APK

En cas de succès, copiez le texte de Gradle Console.

Next Build \ Generate Signed APK ...

Comparez le texte de Gradle Console avec celui ci-dessus pour vérifier la différence.


5 commentaires

Je ne sais pas ce que je suis censé voir ici. La console est à peu près englobée par des arbres ascii qui ressemblent à des dépendances, mais comme je suis une recrue, comme je l'ai mentionné dans mon article original, je ne sais pas vraiment quoi rechercher. De plus, étant donné qu'il contient tellement de texte, le terminal est étendu au point où une partie de la sortie est déjà écrasée / inaccessible. Quand j'ai fait 1., un seul fichier est apparu. Donc j'imagine que 3 était juste. Mais je ne comprends pas ce que vous voulez dire d'autre ici. J'obtiens ce que «exclure» pourrait faire, mais je n'obtiens pas ce dont j'ai besoin pour exclure et comment savoir ce que je dois exclure: /


Un seul résultat à l'étape 1!? Pouvez-vous partager une capture d'écran ou ce fichier? et définissez-vous une dépendance différente entre la version et le débogage?


La seule différence que je peux voir où "release" ou "debug" sont spécifiquement mentionnés dans n'importe quel fichier gradle est celui que j'ai fourni mais comme je l'ai dit, le supprimer ne change rien.


TBH Je n'ai aucune idée du tout, j'ai également essayé de créer settings.gradle en 2 modules avec le même nom de projet racine, pas de problème. J'ai ajouté une autre suggestion dans ma réponse peut aider à déboguer ce problème.


Je suis un débutant et je ne sais pas vraiment comment appliquer votre mise à jour de suggestion. Pouvez-vous le décomposer un peu plus et me montrer exactement quoi faire?



2
votes

Voici une solution de contournement:

  • Pouvez-vous s'il vous plaît vous assurer que multiDexEnabled est défini sur true comme indiqué ci-dessous dans vos paramètres de gradation:

    android {
        defaultConfig {
            multiDexEnabled true
        }
    }
    
  • Essayez android.enableD8 = false dans grade.properties final


1 commentaires

Malheureusement, aucune des suggestions n'a fonctionné. android.enableD8 a même amené AS à émettre un avertissement indiquant qu'il était obsolète. J'ajouterai quelques détails supplémentaires à la question, car cela semble être un problème auquel beaucoup de gens sont confrontés. Cela aidera peut-être.



1
votes

J'ai trouvé la réponse à ma question:

Ce que j'ai fait a été de créer le client swagger, de déplacer le dossier créé dans mon projet, d'ajuster le fichier settings.gradle et le fichier build.gradle en conséquence.

/ p>


Ce qui n'a pas fonctionné

De la façon dont je configurais les choses, gradle construisait le projet ´api´ puis le projet app . Pour une raison quelconque, lorsque j'ai configuré les choses en tant que release , le projet app faisait référence au code du projet api , ainsi qu'au fichier .jar . C'est de là que vient le type de programme déjà présent .


Comment je l'ai résolu

  • Exclure le projet api du projet app
  • Créez une api séparément
  • Prenez le fichier .jar résultant et placez-le dans un dossier à l'intérieur de votre dossier app appelé libs
  • Mettez cette ligne dans vos dépendances de gradle pour votre build.gradle (Module: app) : implementation fileTree (dir: 'libs', include: [ '* .jar'])

Cela incluait le fichier .jar terminé dans le projet app et je peux maintenant créer une version. Cela devrait être fait malgré tout, car le client swagger ne devrait pas être modifié de toute façon, car il s'agit de code généré. Donc, même pour ne pas toujours construire cette partie du projet, cela devrait être fait.

Cependant, je ne comprends toujours pas pourquoi il y a cette différence entre la version release et la version debug . Je serais heureux d'avoir un aperçu de cela.


MODIFIER: INFORMATIONS SUPPLÉMENTAIRES

Je viens de découvrir: si, pour une raison quelconque, j'aurais voulu conserver le Module: api dans mon projet, j'aurais pu le faire en supprimant les deux dépendances dans mon Module : application qui commence par implementation fileTree . Le projet api est déjà inclus dans la dépendance projet api (chemin: ': api') . Les lignes de filet étaient celles qui causaient le problème ici, car elles étaient redondantes.

Cependant, je ne sais toujours pas pourquoi il y a une différence entre debug et release


0 commentaires