When I try to run my android application on an Android device, the gradle console reports the following error:
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
When I search for the "AsyncHttpClient" class, I see that it's indeed being found in two separate locations:
/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
The first path seems to suggest it's a "cache" file... so I've tried invalidating & restarting my cache, but both files are still there after the gradle gets rebuilt and I try to run the application. I've read in alternate posts that it can be resolved by deleting one of the files... So I went to the cache location and deleted all the files found in the "1.4.9" folder... unfortunantly after reopening Android Studio, a new cache file gets created and I get the same error.
Other posts (here, here,here, and here) suggest if I add "./gradlew clean" to the root directory it would rebuild the gradle again just for the run (as far as I understand). So I tried doing that as well:
Which made my app's folder look like this:
But unfortunantly, that didn't help things I still get the same error. What am I doing wrong? What should I be doing?
I added this line to my gradle.properties file and my app worked
android.enableJetifier=true
Sometimes duplicate classes exception means that one of your dependencies uses implicitly the older or newer (with +) version of some library you also use in your project,
To resolve this issue you may add such block of code (put your library version after 'force') to your build.gradle file (Module:app):
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'
}
}
}
You may also exclude some group from your dependencies.
For a single dependency you way write:
dependencies {
// example
implementation('log4j:log4j:1.2.15') {
exclude group: 'javax.jms', module: 'jms'
}
}
Tested to work on Android Studio with Gradle Plugin version 3.4.2 and Gradle version 5.4.1.
Credits go to Dimitar Dimitrov and Schalk Cronjé from gradle org discussion group
That's because you have added some library two times in libs folder, this could happen sometimes when you have multiple versions of the same library in the libs folder. Check it and remove any duplicate jar files.
And the second option could be you have also added the dependency in gradle.build and also have a jar in libs folder.
So check both places and remove duplicate entries and then clean and build APK again.
Delete files with duplicate jar extensions in the libs folder. However, if there are no duplicate files and there is still a "Duplicate classes" error, look for the name in the rest of the "Duplicate classes ...." clause in the error section. For example, "duplicated classes 'dagger' bla bla". Delete the file named 'dagger' from the libs folder. (Be careful not to delete it with shift.)
In my case, I am using sensorocloud.jar and the compile 'com.loopj.android:android-async-http:1.4.9' in my gradle which caused the same error as yours. Because sensoro cloud SDK used loopj's async-http.
I managed to solve it by manually removing the duplicate .class files in the jar file. (i.e.
changing the extension from jar to zip
extract it
remove the com.loopj.android .class files)
(P.S. I have tried to search through the web to see if I could exclude certain class of a jar in gradle, but not succeed, e.g. I referenced this SO post)
This error can be caused by several things;
misconfigured package name
Activity views that is not well binded. - simply go to your launcher activity view and ensure context is defined well e.g "com.yourdomain.package"
Re-create your BuildConfig and set it up well.
Check if your project build.gradle. There it might be some maven duplicate dependency
Here's another situation that can cause duplicate class during the mergeDexClasses task. This can happen with later versions of android gradle.
If your build.gradle.kts script has a dependency in the form:
implementation(project(":mylib", configuration="default"))
that can cause duplicate classes. The correction is simple. Just change it to:
implemenation(project(:mylib"))
Here's the Android Studio's Team explanation:
Having both project(":lib") and project(path: ":lib", configuration: "default") in the runtime classpath means that AGP gets both build/classes/java/main and build/libs/lib.jar (run ./gradlew :lib:outgoingVariants --all to verify). Because paths differ, we'll get 2 dexing transforms happening: 1 incremental that produces dex per class under build/.transforms (the one processing dir) and another one which produces single dex (the one processing jar). Later on during merging this causes failure.
AGP never publishes to the default configuration, in fact java-library plugin does it only so it does not break older build scripts. Having an explicit configuration name used in the dependency declaration is discouraged and Gradle attributes should be used instead.
In an older version of AGP, I ran into a problem where adding the configuration value "default" fixed some issue I was having. Well that no longer works, and adding the "default" configuration you can get duplicate classes.
Related
I have only one dynamic feature module in my project called search, But when I try to build project, I get that Error:
[:search, :search] all package the same library [androidx.recyclerview:recyclerview].
Multiple APKs packaging the same library can cause runtime errors.
Placing each of the above libraries in its own dynamic feature and adding that
feature as a dependency of modules requiring it will resolve this issue.
Libraries that are always used together can be combined into a single feature
module to be imported by their dependents. If a library is required by all
feature modules it can be added to the base module instead.
Of Course, the first thing I did is to research about people who had the same problem And I found:
1- This Question
2- This medium article
Both Introduce the same solution (Use Android Gradle Plugin 4.0) and my project uses AGP 4.0.1, But the problem is that I have only one dynamic module called search. I don't have any other dynamic modules, even further I don't have the dependency of RecyclerView: androidx.recyclerview:recyclerview in my search gradle file, So this is maybe a transitive dependency.
Also, you can find that duplicated dependency in one of two ways:
1-Navigate to: PROJECT_NAME/module_name(In my case: search)/build/intermediates/
and then search for "deps.txt" file in that directory, Open the file and you will see all your module dependencies direct and transitive ones
2- run ./gradlew :module_name:dependencies task
If you tried to remove that duplicated line: androidx.recyclerview:recyclerview from "deps.txt" file, it gets generated again after each build.
That being said, I need some rule in my packagingOptions {} like exclude to prevent that conflict between search.aar and and any other search.* format
Can anyone help, please?
In my case, I removed the below from one of the modules
Note: not from the base module
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
In recent release of our library we decided to add some kotlin-dsl features to our build, though for now we've added buildSrc build.gradle.kts and Dependencies.kts file containing libraries versions for easier use across all modules.
The problem is that this version builds successfuly on jitpack, but downloaded jars are empty. How do I fix this? Also all the resource files are present. The build log file also differs much from previous ones.
Problematic build log file
Working build log file
A link to library on jitpack: https://jitpack.io/#netigenkluzowicz/api_android
Github link
branch to reproduce these build problems is feature/kotlin, we're working to fix it on fix/jitpack-build branch
To Reproduce
Add this dependency to an Android project, sync and check classes.jars
implementation 'com.github.netigenkluzowicz:api_android:2.4.1'
What we did before this problem started to occur:
Added buildSrc directory with build.gradle.kts and Dependencies.kts.
We also extracted android { } block from our modules build.gradle files, it is now applied from android.gradle file.
I've already went through jitpack issues on github, all I found so far are build errors with kotlin-dsl from late 2018. Was following this guide to make a use of kotlin-dsl, though due to having issues with android { } block I didn't migrate all of our gradle files.
I have a library project used by my project. Also my project has several build flavors. In code I reference some classes from that library. I need that library to be removed from my .apk for some of the flavors. I know that this will lead to NoClassDefFoundError but it's ok for me.
I tried to use flavorCompiletask instead of compile but this were leading to errors during compilation of my project (as expected). So how can I make that libeaey project present during compilation but removed from .apk?
P.S. I know that I can remove it during compilation AND alter some of the code files which are using the classes from that library but for me NoClassDefFoundError is ok so I'd like to not have different versions of the same .java files per flavor.
EDIT1
I've found this article but Gradle version seems to be older then current one. Also now I know that I'm looking fot ability to add compile time dependencies.
you could add flavour specific compile block in dependencies, so ex. if you have flavour free and pay
use
dependencies {
payCompile '<something>'
}
you might use provided:
dependencies {
provided 'optional-lib'
}
I've moved my project to Android Studio a month ago, and I'm glad I did, despite the need to switch to a new (and more powerful) build system (gradle). One thing I'd have known in Eclipse, but I can't figure out how to achieve now, is patching the support library. I know that it does not sound like a good practice, but a couple of code lines are driving me crazy, and the solution would be to simply modify it to solve my problem.
I've tried to modify the code in the sdk's ".\extras\android\m2repository\com\android\support" directory, but that does not seem to affect the code that is really used for compilation.
Any idea about how to achieve this ?
Edit:
I tried to create a module "SupportLibraryV4" in my project, and this is what gradle tells me when I try to build it :
Error Code:
1
Output:
trouble processing "java/android/support/v4/R$anim.class":
Ill-advised or mistaken usage of a core class (java.* or javax.*)
when not building a core library.
This is often due to inadvertently including a core library file
in your application's project, when using an IDE (such as
Eclipse). If you are sure you're not intentionally defining a
core class, then this is the most likely explanation of what's
going on.
However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example,
from a non-Android virtual machine project. This will most
assuredly not work. At a minimum, it jeopardizes the
compatibility of your app with future versions of the platform.
It is also often of questionable legality.
If you really intend to build a core library -- which is only
appropriate as part of creating a full virtual machine
distribution, as opposed to compiling an application -- then use
the "--core-library" option to suppress this error message.
If you go ahead and use "--core-library" but are in fact
building an application, then be forewarned that your application
will still fail to build or run, at some point. Please be
prepared for angry customers who find, for example, that your
application ceases to function once they upgrade their operating
system. You will be to blame for this problem.
If you are legitimately using some code that happens to be in a
core package, then the easiest safe alternative you have is to
repackage that code. That is, move the classes in question into
your own package namespace. This means that they will never be in
conflict with core system classes. JarJar is a tool that may help
you in this endeavor. If you find that you cannot do this, then
that is an indication that the path you are on will ultimately
lead to pain, suffering, grief, and lamentation.
1 error; aborting
impressive !
Android sdk doesn't have all required files for building support library.
You need to checkout additional repositories from https://android.googlesource.com:
platform/frameworks/support
platform/prebuilts/gradle-plugin
platform/prebuilts/maven_repo/android
platform/prebuilts/sdk
platform/prebuilts/tools
Please, keep the directory structure as in android repository.
Now you could change any code in support library. If you need to change support library for api v.4 do it in "platform\frameworks\support\v4". For building patched version of support library use gradle with next command:
platform\frameworks\support\v4\gradle clean jar
Resulted jar could be found in "platform\out\host\gradle\frameworks\support\v4\libs\". Put it to the libs folder of your project and add in build.gradle file.
Updated answer 2016 for Linux and OS X using the bundled gradle wrapper instead of the system's gradle installation:
Checkout the following repositories from https://android.googlesource.com and keep the directory structure:
platform/frameworks/support
platform/prebuilts/gradle-plugin
platform/prebuilts/maven_repo/android
platform/prebuilts/sdk
platform/prebuilts/tools
platform/tools/external/gradle
Modify files in the library:
Change files in platform/frameworks/support/
Build AAR
cd platform/frameworks/support
./gradlew jarRelease
The resulting .aar is in platform/out/host/gradle/frameworks/support/<module>/build/outputs/aar/
Add to project
Create a libs/ folder next to your app's build.gradle
Add libs folder to build.gradle: repositories{ flatDir{ dirs 'libs' } }
Copy the .aar file to libs/
Add aar to your dependencies section in build.gradle, e.g.: dependencies { compile(name:'my_custom_supportlib_module', ext:'aar') }
Module already in project
When you patches a support library module that other modules depend on, you'll have it twice in the build causing errors. This can be avoided by excluding the original dependency.
If you for example patch recyclerview-v7 and add
dependencies {
compile(name:'recyclerview-v7-release', ext:'aar')
}
you have to exclude the dependency like this. Change
compile "com.android.support:design:24.2.1"
to
compile("com.android.support:design:24.2.1") {
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
for all modules that depend on the patched module.
Patch the SupportLib and add it manually as a jar:
Put the SupportLib jar into the libs folder
Right click it and hit 'Add as library'
Ensure that compile files('libs/supportlib.jar') is in your build.gradle file
Do a clean build
Disclaimer: Android Studio: Add jar as library?
Turns out that Ilya Tretyakov's answer only works for parts of the support library that don't have resources because they can't be put into a .jar.
The correct way to build for example the design-support-library is as follows:
checkout these repos from https://android.googlesource.com and keep the file structure:
platform/frameworks/support
platform/prebuilts/gradle-plugin
platform/prebuilts/maven_repo/android
platform/prebuilts/sdk
platform/prebuilts/tools
navigate to platform/frameworks/support/design and edit whatever file you want. Now rebuild everything with gradle clean assembleRelease
you can find the resulting library file support-design-release.aar in platform/out/host/gradle/frameworks/support/support-design/build/outputs/aar
create an app/libs folder in your project and edit the app/build.gradle:
repositories{
flatDir{
dirs 'libs'
}
}
dependencies {
compile(name:'support-design-release.aar', ext:'aar')
}
do a clean rebuild of your project and everything will work as intended
I am currently in the process of converting one of our projects to Gradle from maven. The folder structure is as follows:
gitRoot
settings.gradle
build.gradle
ProjectA
build.gradle
src/main/java
Libraries
SomeLib (git submodule)
ProjectBRoot (git submodule)
settings.gradle
build.gradle
ProjectB
build.gradle
src/main/java
Libraries
FacebookSDK/facebook
build.gradle
src
So already it looks complicated. But the idea is that ProjectB is a library project and it should be able to be built and packaged separately, which is why it has its own settings.gradle and as far as i can tell it seems to be working ok, i have it building and its finding facebook just fine.
The ProjectB/build.gradle contains this line
compile project(':libraries:facebook-android-sdk:facebook')
The ProjectBRoot/settings.gradle contains this line
include ':ProjectB', ':libraries:facebook-android-sdk:facebook'
The gitRoot/settings.gradle contains this line
include ':ProjectA', ':Libraries:ProjectBRoot:ProjectB'
The ProjectA/build.gradle contains this line
compile project(':Libraries:ProjectBRoot:ProjectB')
When I run the build i get this error
The TaskContainer.add() method has been deprecated and is scheduled to be removed in Gradle 2.0. Please use the create() method instead.
FAILURE: Build failed with an exception.
* Where:
Build file '/gitRoot/Libraries/ProjectBRoot/ProjectB/build.gradle' line: 17
* What went wrong:
A problem occurred evaluating project ':Libraries:ProjectBRoot:ProjectB'.
> Project with path ':libraries:facebook-android-sdk:facebook' could not be found in project ':Libraries:ProjectBRoot:ProjectB'.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 4.652 secs
So my guess as to whats wrong is that facebook is not in a direct subfolder from ProjectB...but that doesn't matter when building within ProjectBRoot. This is probably due to the face that I am referencing ProjectB directly and not through the ProjectBRoot/gradle.build but I tried that and it also did not work. Can someone please help me out, I have looked through the documentation and it doesn't talk about multiple projects that have their own settings.gradle files and I think thats the thing that is messing me up.
Update:
So I followed Xav's answer and I am now able to build with the command line however i can't import/build with android studio. I know the problem is still with the facebook project. The error i get is that it could not configure ProjectB.
Gradle: A problem occurred configuring project ':ProjectA'.
> Failed to notify project evaluation listener.
> A problem occurred configuring project ':Libraries:ProjectBRoot:ProjectB'.
> Failed to notify project evaluation listener.
> Configuration with name 'default' not found.
The error is caused by the line
compile project(':facebook-sdk')
inside the ProjectB/build.gradle
settings.gradle must define all the modules. It won't load other settings.gradle found in the tree to load more module.
You'll have to either
define a module for the facebook SDK in the top level settings.gradle. Yes it's redundant with the other settings.gradle.
publish Project B somehow (as well as its dependencies so in this case the facebook SDK library), somewhere (a corporate artifact repository for instance) and access it from Project A.
While #1 is better, it makes the ProjectB -> Facebook dependency tricky as the path will be different depending on the settings.gradle used. One way to fix this is to split the module name/path from its actual location on disk. this is done inside the settings.gradle file.
In your top level settings.gradle file, do
include 'facebook-sdk'
project(':facebook-sdk').projectDir = new File('Libraries/ProjectBRoot/Libraries/FacebookSDK/facebook')
In the setting.gradle file inside your Project B, do the same with the different relative path:
include 'facebook-sdk'
project(':facebook-sdk').projectDir = new File('Libraries/FacebookSDK/facebook')
This makes both project setup define the same 'facebook-sdk' module located at the same absolute location on disk.
All projects depending on this module should just declare the dependency as
compile project(':facebook-sdk')
This isn't the answer that you are looking for, but...
I spent about 4 days trying to migrate my complex project structure (much like yours actually), into gradle. In the end, I ditched the entire sub-project concept (since in my case, it just didn't work), and I opted to use the local maven repository approach, as described in this article: http://www.flexlabs.org/2013/06/using-local-aar-android-library-packages-in-gradle-builds
So, in my Library projects that had sub-projects, I basically created complete library projects for each of those, and then I used the link above to publish those to the maven local repository. Then in the parent project, I removed any references to sub projects, and in the dependencies, I just referenced the published libraries. And then in my main project, I removed all references to sub-projects, and I referenced published maven local versions of my libraries.
In the end, it all works very well, but it did take some time to convert everything over. I had about 6 library projects with sub projects, that that sub projects, etc, and now everything works fine.
The thing that I dislike about systems like Gradle and Maven is that they really expect you to change "how" you structure your code/projects. So, if you are migrating to Gradle vs starting with Gradle, then the process can be quite frustrating. Once you figure it out though, the next time is much easier ;)
I would just have the app with the libraries all at the same level. You can still build and package each library based on the build.gradle file. I might be missing something, but the structure isn't as important as what's in the build.gradle files. You could still have projectB depend on Facebook, even if they are at the same folder level.
Had the same problem, in my case, I just forgot to add the project in settings.gradle. After that, it worked
I have finally managed to build the project (without gradle errors). Answer from Xavier was very helpful.
I spend almost 3 days trying to setup my project, I know I am very close to be finsihed but I have UNEXPECTED TOP-LEVEL EXCEPTION at very last step of gradle build process (dexDebug).
My project setup is very similar to Stoyan's however I have multiple android-library projects that are referencing android-support libraries. I suggest that if you have problems with compiling your top root project (error saying support android is already added) than you need to move the jar into separate android library project (decompose/separate into stand alone instance).
Example
--| ProjectARoot
--| ProjectA (where main/java etc are)
--| build.gradle
--| settings.gradle
--| libraries
--| ProjectBRoot
--| settings.gradle
--| ProjectB
--| libraries
--| android-supports (android lib project)
--| libs
--| android-support-v4.jar
--| android-support-v13.jar
--| build.gradle
--| libA
--| build.gradle (referencing android-supports)'
Example build scrip for libA referencing android supports projects
buildscript {
repositories {
maven { url 'http://repo1.maven.org/maven2' }
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4'
}
}
apply plugin: 'android-library'
dependencies {
compile project(':android-support')
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
defaultConfig {
minSdkVersion 7
targetSdkVersion 17
}
}
// top root settings.gradle
include 'ProjectB', 'android-support', ':ProjectA' (notice Project B is first than android-support and lastly Project A)
project(':android-support').projectDir = new File('libraries/ProjectBRoot/libraries/android-support')
project(':ProjectB').projectDir = new File('libraries/ProjectBRoot/ProjectB')
Currently when I run gradle build I get this error
:ProjectA:dexDebug
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat;
at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
at com.android.dx.command.dexer.Main.processClass(Main.java:490)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:459)
at com.android.dx.command.dexer.Main.access$400(Main.java:67)
at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:398)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
at com.android.dx.command.dexer.Main.processOne(Main.java:422)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:333)
at com.android.dx.command.dexer.Main.run(Main.java:209)
at com.android.dx.command.dexer.Main.main(Main.java:174)
at com.android.dx.command.Main.main(Main.java:91)
1 error; aborting
:ProjectA:dexDebug FAILED