DexArchiveMergerException仅在发布时

时间:2019-01-07 18:56:49

标签: android android-studio gradle build swagger

我开发了一个使用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 \ intermediates \ transforms \ dexBuilder \ release \ 54,[。 ..] \ app \ build \ intermediates \ transforms \ externalLibsDexMerger \ release \ 0,[...] \ app \ build \ intermediates \ transforms \ dexBuilder \ release \ 52.jar,[...] \ app \ build \中间体\ transforms \ dexBuilder \ release \ 53.jar


  

原因:com.android.builder.dexing.DexArchiveMergerException:合并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 \版本\ 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尤其令人怀疑。

“ api”和“ app”的settings.gradle具有相同的内容,这可能与它有关吗?两者都看起来像这样:  rootProject.name = "swagger-java-client"。这是文件中的唯一一行,但是据我所知,“ {app}”的settings.gradle已经包含了该内容。我不记得更改了它,所以对我来说奇怪的是它显示了“ 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 :(得分:1)

  

起因:com.android.tools.r8.utils.AbortException:错误:程序类型已存在:io.swagger.client.ApiCallback

意味着此类包含多个依赖项,也许是不同的版本,所以您需要排除它们。

  1. 按两次shift键,搜索io.swagger,然后记录找到的jar文件。

  2. 如果仅复制这些jar文件,则在build.gradle中保留1。


  1. 如果这些jar文件是其他依赖项的模块,请在终端中输入gradlew -q app:dependencies,找到根依赖项名称。

  2. 在build.gradle中,选择1个要保留的依赖项,对于其他依赖项,添加排除命令。

例如更改

implementation 'xxx:xxx'

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

更新

可以尝试的一些选项:

将两个模块的构建变体都更改为要发布,然后构建\构建APK

如果成功,则从Gradle Console复制文本。

下一个版本\生成签名的APK ...

将Gradle Console中的文本与上面的文本进行比较,以检查差异。

答案 1 :(得分:1)

Here是一些解决方法:

  •   

    请确保您在Gradle设置中将multiDexEnabled设置为true,如下所示:

    android {
        defaultConfig {
            multiDexEnabled true
        }
    }
    
  • grade.properties
  • 中尝试android.enableD8 = false

答案 2 :(得分:1)

我找到了问题的答案:

我要做的是创建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客户端生成的代码无论如何都不应该对其进行编辑。因此,即使不总是构建项目的那一部分,也应该这样做。

但是,我仍然不完全理解为什么releasedebug内部版本之间存在这种差异。对此有任何见识将很高兴。


编辑:其他信息

我刚刚发现:如果出于某种原因,我想将Module: api保留在我的项目中,可以通过删除Module: app中以{开头的两个依赖项来实现{1}}。 依赖项implementation fileTree已包含api-project。文件树线是造成此问题的原因,因为它们是多余的。

但是,仍然不知道为什么api project(path: ':api')debug之间存在差异