Reputation: 121
I'm getting the following exception while trying to package a React Native project into a production apk (running gradlew assembleRelease with the config taken from here):
* What went wrong:
Execution failed for task ':app:transformDexWithDexForRelease'.
> com.android.build.api.transform.TransformException:
com.android.ide.common.process.ProcessException:
java.util.concurrent.ExecutionException: com.android.dex.DexException:
Multiple dex files define Lcom/facebook/binaryresource/BinaryResource;
While attempting to package for debug, app appears to be working perfectly on an emulator (either by running react-native run-android or by executing gradlew assembleDebug).
This is happening on a project that used to package correctly (production apk as well), but has not been built for a while due to iOS-focused development (we were only running react-native run-android every once in a while to make sure nothing is broken, apparently that's not enough). During this time, the Android configuration was not touched or changed at all, all changes were done either to the iOS app or to the Javascript code (a few new npm packages were installed, but they are all pure JS and do not require any linking).
I have uploaded the full gradle stack trace here.
I'm using the latest react-native version (0.55.4) and react version 16.3.2. Have also tried updating various packages, and running gradlew clean.
Would appreciate any help with the matter. I'm happy to provide any configuration segments that may be relevant, I just didn't know what to provide as no android-related config/code was changed since the last time it was working.
Thanks!
Upvotes: 1
Views: 853
Reputation: 3225
Here's a method that can help with diagnosing the problem.
A bit before the final error message you'll get the list of JAR files that Gradle is trying to merge (usually in android\app\build\intermediates\transforms\preDex\release
). Each of these JAR files comes from some dependency of your project.
You can unzip the JAR files and look for the name of the class that's causing the conflict. In my case, it was INotificationSideChannel
, in the asker's it was BinaryResource
.
! grep INotificationSideChannel * -irl
50/classes.dex
80/classes.dex
So the conflict is between 50.jar
and 80.jar
. Looking inside the extracted directories, there's the 50/META-INF/com.android.support_support-compat.version
and 80/META-INF/androidx.core_core.version
files, which indicate that these files represent the com.android.support:support-compat
and androidx.core:core
dependencies respectively.
For the record, AndroidX is meant as a replacement to the Android Support Library, so it makes sense that having both of them in the build would cause a conflict. Time to check the project dependency tree:
! gradlew app:dependencies
Going through the list I can see that androidx
is only required once, through the com.google.android.gms:play-services-gcm:17.0.0
dependency, which in turn is referenced by react-native-device-info
.
A little Googling indicates that play-services-gcm
used to reference com.android.support
in 16.1.0
, which led me to the following snippet in android/build.gradle which solved the problem for me:
subprojects {
project.configurations.all {
resolutionStrategy.eachDependency { details ->
// normalize com.android.support library versions
if (details.requested.group == 'com.android.support'
&& !details.requested.name.contains('multidex') ) {
details.useVersion "28.0.0"
}
// downgrade play-services-gcm version to avoid referencing androidx
if (details.requested.group == 'com.google.android.gms' &&
details.requested.name == 'play-services-gcm') {
details.useVersion "16.1.0"
}
}
}
...
In case your conflicting JARs don't have .version files, you can try to identify them from the class folder structure in the jar (e.g. okhttp3/internal will lead you to okhttp3), the name of the conflicting class in the Gradle log, or you can delete the two JARs and look for clues in the log.
Upvotes: 1
Reputation: 19220
The error Multiple dex files define ... happens when you have MultiDex and Duplication of libraries..
Let's say you have added a support-v4
library via aar
file and also using the gradle.
This'll cause the gradle to add both and that error occurres.
You should look for the library that might have been added twice.
In my case an aar
and it's classes.jar
both was added while multidex was enabled, so this happened.
Upvotes: 0
Reputation: 1586
I will let this here for anyone else that might need help.
On android/app/build.gradle, under defaultConfig object put this tag: multiDexEnabled true
, if this starts to raise a zip error, put this at the end of the file
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion '27.1.0'
}
}
}
}
This worked for me when I had a multiDex problem, may not work for everyone
Upvotes: 5