DexArchiveMergerException только при выпуске - PullRequest
0 голосов
/ 07 января 2019

Я разработал приложение, которое использует сгенерированный swagger Java-клиент. Клиент находится в проекте под названием «api», а приложение в проекте под названием «app».

Когда я собираю приложение через Build/Make Project, все работает нормально. Также при попытке запустить приложение на эмулируемом или физическом устройстве Run/Run 'app'. Запуск с отладчиком работает также. Даже когда я собираю проект через Buid/Generate Signed Bundle/APK и выбираю опцию отладки, он работает.

Теперь. Сборка завершается неудачно, когда я пытаюсь создать подписанную сборку релиза. Следующие сообщения показывают:

Вызвано: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: ошибка при объединении dex-архивов: [...] \ app \ build \ промежуточные \ transforms \ dexBuilder \ release \ 54, [. ..] \ app \ build \ middleates \ transforms \ externalLibsDexMerger \ release \ 0, [...] \ app \ build \ middleates \ transforms \ dexBuilder \ release \ 52.jar, [...] \ app \ build \ промежуточные \ прообразы \ dexBuilder \ выпуска \ 53.jar


Вызывается: com.android.builder.dexing.DexArchiveMergerException: Ошибка при объединении архивов dex: [...] \ app \ build \ промежуточные \ transforms \ dexBuilder \ release \ 54, [...] \ app \ build \ промежуточные звенья \ transforms \ externalLibsDexMerger \ release \ 0, [...] \ app \ build \ промежуточные звенья \ transforms \ dexBuilder \ release \ 52.jar, [...] \ app \ build \ промежуточные звенья \ transforms \ dexBuilder \ релиз \ 53.jar


Причина: com.android.tools.r8.CompilationFailedException: не удалось завершить компиляцию


Вызывается: com.android.tools.r8.utils.AbortException: ошибка: тип программы уже существует: io.swagger.client.ApiCallback

Я довольно новичок в разработке с android-studio и gradle, поэтому не стесняйтесь ожидать здесь ошибок новичка. Я попробовал некоторые решения на Stackoverflow, которые уже предлагали добавить некоторые библиотеки, но пока ни одна из них не работала с моей проблемой.

Мне особенно подозрительно, что последнее сообщение об ошибке указывает на io.swagger.client.ApiCallback.

Может ли это быть как-то связано с тем, что и settings.gradle для "api" и "app" имеют одинаковое содержимое? Оба выглядят так: rootProject.name = "swagger-java-client". Это единственная строка в файле, но, насколько я знаю, settings.gradle для «app» уже содержит этот контент. Я не могу вспомнить, чтобы изменить его так странно для меня, что он показывает "swagger-java-client". Это нормально?

ОБНОВЛЕНИЕ 1: ProGuard упоминается в комментариях, что может быть проблемой. Это единственный случай, который я смог найти, ссылаясь на него. В моем build.gradle для "app" -проекта есть эта часть:

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

Однако удаление его ничего не изменило.

ОБНОВЛЕНИЕ 2:

При поиске "io.swagger" AS только находит это: only one match found

При поиске «io.swagger.client.ApiCallback» AS только находит это: only one match found

ОБНОВЛЕНИЕ 3:

Как и предлагалось, я попытался добавить

android {
    defaultConfig {
        multiDexEnabled true
    }
}

и добавление android.enableD8 = false, но это тоже не помогло.

Вот мои файлы build.gradle-Files (первые, которые вызвали проблемы, без предложенных исправлений, которые я до сих пор пробовал).

build.gradle (Модуль: API) (генерируется swagger):

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'
}

build.gradle (Модуль: приложение):

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'
}

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Здесь некоторые обходные пути:

  • Не могли бы вы убедиться, что для multiDexEnabled установлено значение true, как показано ниже в настройках Gradle:

    android {
        defaultConfig {
            multiDexEnabled true
        }
    }
    
  • Попробуйте android.enableD8 = false в grade.properties
0 голосов
/ 11 февраля 2019

Я нашел ответ на свой вопрос:

Я создал клиента Swagger, переместил созданную папку в мой проект, соответственно скорректировал файл settings.gradle и файл build.gradle.


Что пошло не так

Как я настроил, gradle создаст проект «api», а затем проект app. По какой-то причине, когда я настроил вещи как release, проект app ссылался на код проекта api, а также на полученный файл .jar. Вот откуда взялся Program type already present.


Как я это исправил

  • Исключить проект api из проекта app
  • Сборка api отдельно
  • Возьмите полученный файл .jar и поместите его в папку внутри вашей папки app с именем libs
  • Поместите эту строку в ваш gradle dependencies для вашего build.gradle (Module: app): implementation fileTree(dir: 'libs', include: ['*.jar'])

Это включало готовый файл .jar в проект app, и теперь я могу собрать релиз. Это должно быть сделано независимо от того, что клиент swagger не должен быть отредактирован в любом случае, так как это сгенерированный код. Поэтому даже для того, чтобы не всегда создавать эту часть проекта, это должно быть сделано.

Однако я до сих пор не до конца понимаю, почему существует разница между сборкой release и debug. Был бы рад любому пониманию этого.


РЕДАКТИРОВАТЬ: ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Я только что узнал: если бы по какой-то причине я хотел бы сохранить Module: api в своем проекте, я мог бы сделать это, удалив две зависимости в моем Module: app, которые начинаются с implementation fileTree. Api-проект уже включен зависимостью api project(path: ':api'). Строки файлового дерева были причиной проблемы, так как они были избыточными.

Однако до сих пор не известно, почему существует разница между debug и release

0 голосов
/ 14 января 2019

Причина: com.android.tools.r8.utils.AbortException: ошибка: тип программы уже существует: io.swagger.client.ApiCallback

Означает, что этот класс содержит несколько зависимостей, возможно, разные версии, поэтому их необходимо исключить.

  1. Нажмите дважды shift, найдите io.swagger, затем запишите найденные файлы jar.

  2. Если эти файлы JAR просто дублируются, сохраните 1 в build.gradle.


  1. Если эти jar-файлы являются модулями другой зависимости, введите gradlew -q app:dependencies в терминале, найдите имена корневой зависимости.

  2. В build.gradle выберите 1 зависимость для сохранения, для других добавьте команду exclude.

Например изменить

implementation 'xxx:xxx'

до

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

UPDATE

Некоторые варианты попробовать:

Измените варианты сборки обоих модулей, затем Build \ Build APK

В случае успеха скопируйте текст из Gradle Console.

Следующая сборка \ Создать подписанный APK ...

Сравните текст в Gradle Console с приведенным выше, чтобы проверить разницу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...