Android Studio:解决重复类问题

28

当我尝试在Android设备上运行我的应用程序时,Gradle控制台报告以下错误:

Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: com/loopj/android/http/AsyncHttpClient$1.class

当我搜索"AsyncHttpClient"类时,我发现它实际上在两个不同的位置被发现:
/Users/Afflatus/.gradle/caches/modules-2/files-2.1/com.loopj.android/android-async-http/1.4.9/5d171c3cd5343e5997f974561abed21442273fd1/android-async-http-1.4.9-sources.jar!/com/loopj/android/http/AsyncHttpClient.java

/Users/Afflatus/.ideaLibSources/android-async-http-1.4.9-sources.jar!/com/loopj/android/http/AsyncHttpClient.java

第一条路径似乎表明它是一个“缓存”文件...所以我尝试了无效化和重新启动我的缓存,但在gradle重新构建并尝试运行应用程序后仍然存在两个文件。我在其他帖子中读到,可以通过删除其中一个文件来解决这个问题...所以我去了缓存位置并删除了“1.4.9”文件夹中找到的所有文件...不幸的是,在重新打开Android Studio后,会创建一个新的缓存文件,并出现相同的错误。
其他帖子(这里这里这里这里)建议如果我在根目录添加"./gradlew clean",它将再次重建gradle仅供运行使用(就我所知)。所以我也试着做了这个: enter image description here 这使得我的应用程序文件夹看起来像这样: enter image description here 但不幸的是,这并没有帮助我解决问题,我仍然得到相同的错误。我做错了什么?我应该做什么?

2
请问您是如何解决问题的?我遇到了和您完全相同的问题。 - chubao
1
@DavidCheung 我不认为我解决了这个问题。 我尝试了Anders的建议,但对于我的情况似乎没有用。 也许对你有用? - Afflatus
你可以在这里找到好的资料:https://dev59.com/llMI5IYBdhLWcg3whLxC#56029604 - A Farmanbar
8个回答

30
我在我的gradle.properties文件中添加了这行代码,我的应用程序就能正常工作了。 android.enableJetifier=true

这对我起作用了。问题是我从jitpack添加了库。 - undefined

16
有时候,重复类异常意味着你的某个依赖项在隐式地使用比你项目中使用的某个库更新或较旧(带有+)的版本。
为了解决这个问题,你可以在你的build.gradle文件(Module:app)中添加以下代码块(将你的库版本放在'force'之后)。
configurations {
   all {
      resolutionStrategy {
          // do not upgrade above 3.12.0 to support API < 21 while server uses
          // COMPATIBLE_TLS, or okhttp3 is used in project
          force 'com.squareup.okhttp3:okhttp:3.12.0'
          force 'com.squareup.okhttp3:logging-interceptor:3.12.0'
      }
   }
}

您也可以从依赖项中排除某些组。对于单个依赖,您可以编写:

dependencies {

    // example
    implementation('log4j:log4j:1.2.15') {
        exclude group: 'javax.jms', module: 'jms'
    }
}

测试通过 Android Studio 和 Gradle 插件版本 3.4.2 以及 Gradle 版本 5.4.1。鸣谢 gradle.org 讨论组中的 Dimitar Dimitrov 和 Schalk Cronjé。


在强制使用项目路径后,如何使用implementation project(path: ':videocropper')?请告诉我如何使其正常工作。 - Sayyed Rizwan
什么是JMS,为什么要将其排除,在原错误中它与何相关?模块JMS的原因是什么?组javax.jms的原因又是什么?这些信息来自哪里? - toby yeats

10
这是因为您在“libs”文件夹中添加了某个库两次,当您在“libs”文件夹中拥有同一库的多个版本时,有时会发生这种情况。请检查并删除任何重复的jar文件。
第二个可能的选项是您已经在“gradle.build”中添加了依赖项,并且还有一个jar文件在“libs”文件夹中。
因此,请检查这两个位置并删除重复条目,然后重新清理和构建“APK”。

8
libs文件夹的位置在哪里?在项目的根目录吗? - Walter Martin Vargas-Pena
2
这是ProjectFolder/app/libs。 - Atiq
我们可以在本地的 .aar 文件中使用 exclude 并从其中一个 .aar 文件中排除重复的代码吗? - Raghav Sharma

3

删除 libs 文件夹中扩展名重复的 jar 文件。但是,如果没有重复的文件,仍然出现 "Duplicate classes" 错误,请查找错误部分中剩余的 "Duplicate classes ...." 子句中的名称。例如,"duplicated classes 'dagger' bla bla"。从 libs 文件夹中删除名为 'dagger' 的文件。(注意不要使用 Shift 键删除。)


2
在我的情况下,我正在使用sensorocloud.jarcompile'com.loopj.android:android-async-http:1.4.9'在我的gradle中,这导致了与你的相同的错误。因为Sensoro Cloud SDK使用了loopj的async-http
我成功地通过手动删除jar文件中的重复.class文件来解决它。(即
  1. 将扩展名从jar更改为zip
  2. 提取它
  3. 删除com.loopj.android .class文件)
(P.S.我曾尝试通过搜索网页来查看是否可以在gradle中排除某个jar类,但没有成功,例如我引用this SO post)

这个对你有用吗?可以排除一个类packagingOptions { exclude 'okhttp-2.0.0.jar' exclude 'crashlytics.jar' exclude 'DimenRes.class' exclude 'support-v4' exclude 'AccessToken$1.class' } - amdstorm
我认为这与你提到的排除无关。 - chubao

0

这个错误可能由以下几个原因引起:

  1. 包名配置错误
  2. 活动视图绑定不正确。- 只需转到您的启动器活动视图并确保上下文定义良好,例如“com.yourdomain.package”
  3. 重新创建您的BuildConfig并进行良好设置。

-1

检查你的项目 build.gradle 文件。可能存在一些 Maven 重复依赖。


-1

这里是另一种可能会导致 mergeDexClasses 任务中出现重复类的情况。这可能会发生在较新版本的 Android Gradle 中。

如果您的 build.gradle.kts 脚本有以下形式的依赖:

implementation(project(":mylib", configuration="default"))

那么就可能会导致重复类。更正方法很简单。只需将其更改为:

implemenation(project(:mylib"))

这是 Android Studio 团队的解释:

将 project(":lib") 和 project(path: ":lib", configuration: "default") 都添加到运行时类路径中意味着 AGP 获取了 build/classes/java/main 和 build/libs/lib.jar(运行 ./gradlew :lib:outgoingVariants --all 来验证)。由于路径不同,我们将得到两个 dex 转换:一个是增量转换,它在 build/.transforms 下每个类都会生成一个 dex(处理目录的转换),另一个是生成单个 dex 的转换(处理 jar 的转换)。稍后在合并过程中,这会导致失败。 AGP 从不发布到默认配置,实际上,java-library 插件只是为了不破坏旧的构建脚本才这样做。在依赖声明中使用显式配置名称是不鼓励的,应该使用 Gradle 属性代替。

在旧版本的AGP中,我遇到了一个问题,添加配置值“default”可以解决一些问题。但现在这种方法不再适用了,添加“default”配置可能会导致重复类的出现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接