Duplicate class found in modules (exclude packages) - java

I have added 2 modules in my project but I got the following error
Duplicate class com.bumptech.glide.GeneratedAppGlideModuleImpl found in modules jetified-XXX-XXX-XXX_XXX_0.2-runtime (com.github.YYY:YYY:YYYY_0.2) and jetified-XXX-XXX-XXX-1.0.24-runtime (com.github.XXX:XXX-XXX-XXX:1.0.24)
Duplicate class com.bumptech.glide.GeneratedRequestManagerFactory found in modules jetified-YYY-YYY-YYY_0.2-runtime (com.github.nithraedu:YYYY-YYY:YYY_0.2) and jetified-XXX-XXX-XXX-1.0.24-runtime (com.github.XXX:XXX-XXX-XXX:1.0.24)
how do I solve this problem?

If you have duplicate classes, it shows that you have added dependencies that use the same modules and classes so you must find these dependencies and exclude the duplicates. In your case I think you want to use glide library so you can simply add:
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
In your app level build.gradle file. This is an issue for some of the dependencies that used same classes before AndroidX. The other option for you is to simply migrate to AndroidX which solves these kinds of problems.
if you want to see your dependency_tree and identify what's causing the duplication you can use this command:
gradle -q dependencies yourProject:dependencies --configuration compile
or you can find your dependency_tree in view -> tool-windows -> gradle -> YourAppName -> tasks -> android -> androidDependencies
after that you must find the duplicated module and exclude it from the library dependency to avoid duplication for example:
implementation('com.example.m:m:1.0') {
exclude group: 'org.unwanted', module: 'x
}

https://bumptech.github.io/glide/doc/configuration.html#avoid-appglidemodule-in-libraries
The libraries which you are using glide and it extends the AppGlideModule instead of LibraryGlideModule.

Related

How to exclude library from dependencies?

I have a gradle project with several modules in it. In the main module I have id "io.spring.dependency-management" plugin. In the adapters module I have dependency on the main one implementation project(":main") with runtimeOnly 'io.r2dbc:r2dbc-postgresql in dependency block, which pulls 0.8.12.RELEASE version of the r2dc-postgresql driver.
Now I want to use 0.8.13.RELEASE verision of the driver, so I simply added runtimeOnly 'io.r2dbc:r2dbc-postgresql:0.8.13.RELEASE to the dependency declaration, but now I have two versions of this library in external libraries section (0.8.12.RELEASE and 0.8.13.RELEASE), but ./gradlew adapters:dependencies displays only 0.8.13.RELEASE version.
How to find out where 0.8.12.RELEASE is coming from now and remove it?
I tried
exlude(group = 'io.r2dbc', module = 'r2dbc-postgresql')
but it didn't work
have you had a look at e.g.:
https://docs.gradle.org/current/userguide/resolution_rules.html
or
How to exclude library from all dependencies in Kotlin DSL build.gradle?
or
What does this "all*.exclude" means in Gradle transitive dependency?

Gradle dependencies: package does not exist

I know this has been asked multiple times but the questions have multiple answers.
I'm trying to use a Java package that's a dependency of my dependency. Let's say I've built this gradle project called "ee_tools". And that has a dependency called "my_models", which has a package called "com.mycompany.my_models.db". So in the ee_tools project build.gradle, I've got
dependencies {
// My stuff
implementation group: "com.mycompany", name: "my_models", version: "1.0.0"
}
Then in my current project, I've got
dependencies {
// My stuff
implementation group: "com.mycompany", name: "ee_tools", version: "1.0.0"
Shouldn't this mean that the public classes in my_models are accessible through ee_tools to my current project? Gradle was able to find both in my artifactory instance. And the gradle dependencies command shows ee_tools under the compileClasspath, implementation, and testCompileClasspath trees, but not with its children dependencies. It also shows up in the runtimeClasspath and testRuntimeClasspath trees with its children dependencies, including my_models.
I am also able to see that package inside the jar on the left side of IntelliJ, under the "External Libraries" tree, along with some classes.
But when I try to use the my_models package in my current project, IntelliJ can't find it and it fails a gradle build with the error
error: package com.company.my_models.db does not exist
It can't find any package in that dependency. What gives? Am I declaring the dependencies incorrectly? Or is this a gap between the gradle binary in my command line vs IntellJ and gradlew?
If ee_tools depends on my_models, then your gradle file in ee_tools should be like
implementation project(path: ":path:to:my_models", configuration: 'default')
:path:to:my_models is defined in settings.gradle in project root path like this:
include ':path:to:my_models'

How do I fix this "Duplicate class error" in Android Studio

I updated implementation com.google.android.gms:play-services-ads:19.8.0 to implementation com.google.android.gms:play-services-ads:20.4.0 and now I get this error:
Duplicate class com.google.android.gms.internal.measurement.zzbs found in modules jetified-play-services-measurement-18.0.2-runtime (com.google.android.gms:play-services-measurement:18.0.2) and jetified-play-services-measurement-sdk-api-18.0.3-runtime (com.google.android.gms:play-services-measurement-sdk-api:18.0.3)
Duplicate class com.google.android.gms.internal.measurement.zzl found in modules jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2) and jetified-play-services-measurement-sdk-api-18.0.3-runtime (com.google.android.gms:play-services-measurement-sdk-api:18.0.3)
Duplicate class com.google.android.gms.measurement.internal.zzfh found in modules jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3) and jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2)
Duplicate class com.google.android.gms.measurement.internal.zzgn found in modules jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3) and jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2)
Duplicate class com.google.android.gms.measurement.internal.zzgo found in modules jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3) and jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2)
Duplicate class com.google.android.gms.measurement.internal.zzgp found in modules jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3) and jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2)
Duplicate class com.google.android.gms.measurement.internal.zzgq found in modules jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3) and jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2)
Duplicate class com.google.android.gms.measurement.internal.zzhs found in modules jetified-play-services-measurement-18.0.2-runtime (com.google.android.gms:play-services-measurement:18.0.2) and jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3)
Duplicate class com.google.android.gms.measurement.internal.zzhx found in modules jetified-play-services-measurement-base-18.0.3-runtime (com.google.android.gms:play-services-measurement-base:18.0.3) and jetified-play-services-measurement-impl-18.0.2-runtime (com.google.android.gms:play-services-measurement-impl:18.0.2)
How to fix this error?
I ran into the same issue today, and after many trial and errors, I finally found that it was caused by a firebase dependency. If you're using firebase in your project, make sure to use the latest BoM version in app/build.gradle:
dependencies{
// implementation platform('com.google.firebase:firebase-bom:25.12.0') <-- Produces errors
implementation platform('com.google.firebase:firebase-bom:29.0.0') //<-- This works
}
If you are not using firebase and still get this error, you can try excluding the offending classes directly in app/build.gradle:
android {
defaultConfig {
...
}
buildTypes {
...
}
configurations {
all {
exclude group: "com.google.android.gms", module: "play-services-measurement-impl"
exclude group: "com.google.android.gms", module: "play-services-measurement"
}
}
}
I am having the same issue and I fixed it by downgrading play-services-ads dependency like this. So you can try.
def ads_version = "20.3.0"
implementation "com.google.android.gms:play-services-ads:$ads_version"
The error is being produced due to the conflicts between firebase & google service dependency. So you have 2 options.
You can change the versions and keep doing that until you find the perfect working combination which is time consuming or you can find a solution that works every time so you don't have to play with the versions every time. You just use that solution wherever you get such error.
Here, you need to use the updated method of injecting the firebase dependency as shown in the official documentation.
Put this line in your dependency :
implementation platform('com.google.firebase:firebase-bom:28.1.0')
Then, You can use any firebase dependency without specifying the versions, and it will work flawlessly all the time!
The final code looks like this,
implementation platform('com.google.firebase:firebase-bom:28.1.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-config'
implementation 'com.google.firebase:firebase-crashlytics'
And it won't produce any duplication related errors with the play-services dependency.
Best way to fix this and prepare your project for later is to migrate completely to AndroidX. First check if your project is ready, Refactor > Migrate to AndroidX. Once your project is independent of jcenter or any other older library/repo and compatible with AndroidX you won't need Jetifier anymore, so either comment it out or remove it. This should possibly fix the problem.
...
#android.enableJetifier=false
...
In my case this wasn't enough to solve the problem, if you still receive the same error but from a different library, it's possibly because of other existing dependencies, avoid using bundled libraries or wildcard ones (in which system is left to guess) make sure you update them all and clean rebuild the project.
If you still have to keep some conflicting library, try excluding individual classes to avoid the error like this from build.gradle:
android {
...
defaultConfig {
...
}
buildTypes {
...
}
configurations {
all { // You should exclude one of them not both of them
exclude group: "com.android.support", module: "support-core-ui"
exclude group: "com.android.support", module: "support-compat"
}
}
}
Official docs on module exclusion - Excluding transitive dependencies
I also tried few more things before figuring the solution, like deleting .gradle from local machine, incase some old libraries got cached and causing the error, or resetting Android Studio, it just won't work.
Repo I tested the solution here, as you can see in this line I had to comment out the bundle module and specify latest updates to individual dependencies.
You can read more on module dependency errors for reference.
Add this line android.enableJetifier=true to your gradle.properties

Replace android.support.v4.util.ArraySet with androidx.collection.ArraySet in Maven library

I have a 3rd party library that depends on:
import android.support.v4.util.ArraySet;
And I want to use the latest Android libraries in the rest of my project:
import androidx.collection.ArraySet;
However, since I'm getting the library via Maven, I can't seem to force it to replace the v4 dependency for the androidx one and have it refer to the right class.
I've already tried:
implementation 'androidx.collection:collection:1.1.0'
implementation('some-library:v1') {
exclude group: 'com.android.support', module: 'support-v4'
}
And:
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute module('com.android.support:support-v4') with module('androidx.collection:collection:1.1.0')
}
}
I've even tried a few more things including the force=true for the dependencies I want.
However I'm still getting:
java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/util/ArraySet;
How can I tell Gradle to resolve the imports for android.support.v4.util.ArraySet to androidx.collection.ArraySet when I don't have access to the source code?
As per the Migrate to AndroidX guide:
android.enableJetifier=true
The Android plugin automatically migrates existing third-party libraries to use AndroidX by rewriting their binaries.
So this rewriting of Maven dependencies is exactly what Jetifier does for you. Make sure you've added the android.enableJetifier=true to your gradle.properties file to enable Jetifier.

Multi-project test dependencies with gradle

I have a multi-project configuration and I want to use gradle.
My projects are like this:
Project A
-> src/main/java
-> src/test/java
Project B
-> src/main/java (depends on src/main/java on Project A)
-> src/test/java (depends on src/test/java on Project A)
My Project B build.gradle file is like this:
apply plugin: 'java'
dependencies {
compile project(':ProjectA')
}
The task compileJava work great but the compileTestJava does not compile the test file from Project A.
Deprecated - For Gradle 5.6 and above use this answer.
In Project B, you just need to add a testCompile dependency:
dependencies {
...
testCompile project(':A').sourceSets.test.output
}
Tested with Gradle 1.7.
This is now supported as a first class feature in Gradle. Modules with java or java-library plugins can also include a java-test-fixtures plugin which exposes helper classes and resources to be consumed with testFixtures helper. Benefit of this approach against artifacts and classifiers are:
proper dependency management (implementation/api)
nice separation from test code (separate source set)
no need to filter out test classes to expose only utilities
maintained by Gradle
Example
:modul:one
modul/one/build.gradle
plugins {
id "java-library" // or "java"
id "java-test-fixtures"
}
modul/one/src/testFixtures/java/com/example/Helper.java
package com.example;
public class Helper {}
:modul:other
modul/other/build.gradle
plugins {
id "java" // or "java-library"
}
dependencies {
testImplementation(testFixtures(project(":modul:one")))
}
modul/other/src/test/java/com/example/other/SomeTest.java
package com.example.other;
import com.example.Helper;
public class SomeTest {
#Test void f() {
new Helper(); // used from :modul:one's testFixtures
}
}
Further reading
For more info, see the documentation:
https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
It was added in 5.6:
https://docs.gradle.org/5.6/release-notes.html#test-fixtures-for-java-projects
Simple way is to add explicit task dependency in ProjectB:
compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')
Difficult (but more clear) way is to create additional artifact configuration for ProjectA:
task myTestsJar(type: Jar) {
// pack whatever you need...
}
configurations {
testArtifacts
}
artifacts {
testArtifacts myTestsJar
}
and add the testCompile dependency for ProjectB
apply plugin: 'java'
dependencies {
compile project(':ProjectA')
testCompile project(path: ':ProjectA', configuration: 'testArtifacts')
}
I've come across this problem myself recently, and man is this a tough issues to find answers for.
The mistake you are making is thinking that a project should export its test elements in the same way that it exports its primary artifacts and dependencies.
What I had a lot more success with personally was making a new project in Gradle. In your example, I would name it
Project A_Test
-> src/main/java
I would put into the src/main/java the files that you currently have in Project A/src/test/java. Make any testCompile dependencies of your Project A compile dependencies of Project A_Test.
Then make Project A_Test a testCompile dependency of Project B.
It's not logical when you come at it from the perspective of the author of both projects, but I think it makes a lot of sense when you think about projects like junit and scalatest (and others. Even though those frameworks are testing-related, they are not considered part of the "test" targets within their own frameworks - they produce primary artifacts that other projects just happen to use within their test configuration. You just want to follow that same pattern.
Trying to do the other answers listed here did not work for me personally (using Gradle 1.9), but I've found that the pattern I describe here is a cleaner solution anyway.
I know it's an old question but I just had the same problem and spent some time figuring out what is going on. I'm using Gradle 1.9. All changes should be in ProjectB's build.gradle
To use test classes from ProjectA in tests of ProjectB:
testCompile files(project(':ProjectA').sourceSets.test.output.classesDir)
To make sure that sourceSets property is available for ProjectA:
evaluationDependsOn(':ProjectA')
To make sure test classes from ProjectA are actually there, when you compile ProjectB:
compileTestJava.dependsOn tasks.getByPath(':ProjectA:testClasses')
Please read the update bellow.
Similar problems described by JustACluelessNewbie occurs in IntelliJ IDEA. Problem is that dependency testCompile project(':core').sourceSets.test.output actually means: "depend on classes generated by gradle build task". So if you open clean project where classes are not generated yet IDEA won't recognise them and reports error.
To fix this problem you have to add a dependency on test source files next to dependency on compiled classes.
// First dependency is for IDEA
testCompileOnly files { project(':core').sourceSets.test.java.srcDirs }
// Second is for Gradle
testCompile project(':core').sourceSets.test.output
You can observe dependencies recognised by IDEA in Module Settings -> Dependencies (test scope).
Btw. this is not nice solution so refactoring is worth considering. Gradle itself does have special subproject containing test-support classes only. See https://docs.gradle.org/current/userguide/test_kit.html
Update 2016-06-05
More I am thinking about proposed solution less I like it. There are few problems with it:
It creates two dependencies in IDEA. One points to test sources another to compiled classes. And it is crucial in which order these dependencies are recognised by IDEA. You can play with it by changing dependency order in Module settings -> Dependencies tab.
By declaring these dependencies you are unnecessarily polluting dependency structure.
So what's the better solution? In my opinion it's creating new custom source set and putting shared classes into it. Actually authors of Gradle project did it by creating testFixtures source set.
To do it you just have to:
Create source set and add necessary configurations. Check this script plugin used in Gradle project: https://github.com/gradle/gradle/blob/v4.0.0/gradle/testFixtures.gradle
Declare proper dependency in dependent project:
dependencies {
testCompile project(path: ':module-with-shared-classes', configuration: 'testFixturesUsageCompile')
}
Import Gradle project to IDEA and use the "create separate module per source set" option while importing.
New testJar based (trnsitive dependancies supported) solution available as gradle plugin:
https://github.com/hauner/gradle-plugins/tree/master/jartest
https://plugins.gradle.org/plugin/com.github.hauner.jarTest/1.0
From documentation
In case you have a multi-project gradle build you may have test
dependencies between sub-projects (which probably is a hint that your
projects are not well structured).
For example assume a project where the sub-project Project B depends
on Project A and B does not only have a compile dependency on A but
also a test dependency. To compile and run the tests of B we need some
test helper classes from A.
By default gradle does not create a jar artifact from the test build
output of a project.
This plugin adds a testArchives configuration (based on testCompile)
and a jarTest task to create a jar from the test source set (with the
classifier test added to name of the jar). We can then depend in B on
the testArchives configuration of A (which will also include the
transitive dependencies of A).
In A we would add the plugin to build.gradle:
apply plugin: 'com.github.hauner.jarTest'
In B we reference the
testArchives configuration like this:
dependencies {
...
testCompile project (path: ':ProjectA', configuration: 'testArchives')
}
The Fesler's solution haven't worked for me, when i tried it to build an android project (gradle 2.2.0).
So i had to reference required classes manually :
android {
sourceSets {
androidTest {
java.srcDir project(':A').file("src/androidTest/java")
}
test {
java.srcDir project(':A').file("src/test/java")
}
}
}
Here if you are using Kotlin DSL, you should create your task like that according to Gradle documentation.
Like some previous answer, you need to create a special configuration inside the project that will share its tests class, so that you don't mix test and main classes.
Simple steps
In project A you would need to add in your build.gradle.kts :
configurations {
create("test")
}
tasks.register<Jar>("testArchive") {
archiveBaseName.set("ProjectA-test")
from(project.the<SourceSetContainer>()["test"].output)
}
artifacts {
add("test", tasks["testArchive"])
}
Then in your project B in the dependencies, you will need to add in your build.gradle.kts:
dependencies {
implementation(project(":ProjectA"))
testImplementation(project(":ProjectA", "test"))
}
I'm so late to the party (it is now Gradle v4.4) but for anyone else who finds this:
Assuming:
~/allProjects
|
|-/ProjectA/module-a/src/test/java
|
|-/ProjectB/module-b/src/test/java
Go to the build.gradle of project B (the one that needs some test classes from A) and add the following:
sourceSets {
String sharedTestDir = "${projectDir}"+'/module-b/src/test/java'
test {
java.srcDir sharedTestDir
}
}
or (assuming your project is named ProjectB)
sourceSets {
String sharedTestDir = project(':ProjectB').file("module-b/src/test/java")
test {
java.srcDir sharedTestDir
}
}
Voila!
Creating test-jar For Gradle 6.6.x
I know that there are many sources telling you, that is not OK, fe:
https://github.com/gradle/gradle/issues/11280
https://gradle.org/whats-new/gradle-6/#better-builds
But this is so damn simple and I just don't like the idea of having common test classes separately in testFixtures folder.
So in module A:
task jarTests(type: Jar, dependsOn: testClasses) {
classifier = 'tests'
from sourceSets.test.output
}
configurations {
tests {
extendsFrom testRuntime
}
}
artifacts {
tests jarTests
}
And in module B:
testImplementation project(':moduleA')
testImplementation project(path: ':moduleA', configuration: 'tests')
And it just works!
If you want to use artifact dependencies to have:
ProjectB's source classes depend on Project A's source classes
ProjectB's test classes depend on Project A's test classes
then ProjectB's dependencies section in build.gradle should look something like this:
dependencies {
compile("com.example:projecta:1.0.0")
testCompile("com.example:projecta:1.0.0:tests")
}
For this to work ProjectA needs to build a -tests jar and include it in the artifacts it produces.
ProjectA's build.gradle should contain configuration like this:
task testsJar(type: Jar, dependsOn: testClasses) {
classifier = 'tests'
from sourceSets.test.output
}
configurations {
tests
}
artifacts {
tests testsJar
archives testsJar
}
jar.finalizedBy(testsJar)
When ProjectA's artifacts are published to your artifactory they will include a -tests jar.
The testCompile in ProjectB's dependencies section will bring in the classes in the -tests jar.
If you want to includeFlat ProjectA's source and test classes in ProjectB for development purposes then the dependencies section in ProjectB's build.gradle would look like this:
dependencies {
compile project(':projecta')
testCompile project(path: ':projecta', configuration: 'tests')
}
If you have mock dependencies which you need to share between tests, you can create new project projectA-mock and then add it as test dependency to ProjectA and ProjectB:
dependencies {
testCompile project(':projectA-mock')
}
This is clear solution to share mock dependencies, but if you need to run tests from ProjectA in ProjectB use other solution.
The solution mentioned by Nikita for Android + Kotlin looks like this:
task jarTests(type: Jar, dependsOn: "assembleDebugUnitTest") {
getArchiveClassifier().set('tests')
from "$buildDir/tmp/kotlin-classes/debugUnitTest"
}
configurations {
unitTestArtifact
}
artifacts {
unitTestArtifact jarTests
}
Gradle for project that is going to use dependencies:
testImplementation project(path: ':shared', configuration: 'unitTestArtifact')
If you are struggling to adapt the solution to the Gradle Kotlin DSL this is the equivalent:
configurations {
register("testClasses") {
extendsFrom(testImplementation.get())
}
}
val testJar = tasks.register<Jar>("testJar") {
archiveClassifier.set("test")
from(sourceSets.test)
}
artifacts.add("testClasses", testJar)
Some of the other answers caused errors one way or another - Gradle did not detect test classes from other projects or Eclipse project had invalid dependencies when imported. If anyone has the same problem, I suggest going with:
testCompile project(':core')
testCompile files(project(':core').sourceSets.test.output.classesDir)
The first line forces the Eclipse to link the other project as dependency, so all sources are included and up to date. The second allows Gradle to actually see the sources, while not causing any invalid dependency errors like testCompile project(':core').sourceSets.test.output does.
in project B:
dependencies {
testCompile project(':projectA').sourceSets.test.output
}
Seems to work in 1.7-rc-2

Categories