Skip to content

Commit

Permalink
Fix duplicate resource error in Android gradle build (#22234) (#24518)
Browse files Browse the repository at this point in the history
Summary:
Issue #22234 includes a number of people (myself included) suffering with duplicate resource errors while building in Android. We have been collectively using a patch there but I don't believe any attempt has been made to PR it upstream.

I am not excellent at gradle, so I may have approached this in completely the wrong way, but it works for me in the standard init templates, as well as my current work project which has a complicated 2 buildType + 4 productFlavor configuration. If there is a better way to achieve the result I am happy to learn

The approach here is to determine the generated path the resources land in, then move them into the main build output tree. If they remain in the generated path android merging fails with duplicate resource errors, so that move (vs copy) is important.

[Android] [Fixed] - Fix duplicate resource error in Android build
Pull Request resolved: #24518

Differential Revision: D15276981

Pulled By: cpojer

fbshipit-source-id: 3fe8c8556e4dcdac5f96a2d4658ac9b5d9b67379
  • Loading branch information
mikehardy authored and facebook-github-bot committed May 9, 2019
1 parent 6ccdf85 commit 962437f
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions react.gradle
Expand Up @@ -48,6 +48,32 @@ afterEvaluate {
resourcesDir.mkdirs()
}


// If there are flavors, remember the current flavor for use in the resource path we move from
def flavorPathSegment = ""
android.productFlavors.all { flavor ->
if (targetName.toLowerCase().contains(flavor.name)) {
flavorPathSegment = flavor.name + "/"
}
}

// Address issue #22234 by moving generated resources into build dir so they are in one spot, not duplicated
doLast {
def moveFunc = { resSuffix ->
File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}")
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}")
ant.move(file: originalDir, tofile: destDir);
}
}
moveFunc.curry("ldpi").call()
moveFunc.curry("mdpi").call()
moveFunc.curry("hdpi").call()
moveFunc.curry("xhdpi").call()
moveFunc.curry("xxhdpi").call()
moveFunc.curry("xxxhdpi").call()
}

// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir(jsBundleDir)
Expand Down

11 comments on commit 962437f

@co-de
Copy link

@co-de co-de commented on 962437f Aug 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikehardy I have RN 0.63.2 but can't see this change. not merged yet? cause I am still seeing the duplicate resource errors.

@mikehardy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@co-de
Copy link

@co-de co-de commented on 962437f Aug 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikehardy oh.. thanks for pointing this out. And thanks for lightning fast reply.
I came here directly from your comment in this SO post: https://stackoverflow.com/questions/53239705/react-native-error-duplicate-resources-android/53260522
That is why I was missing all the discussions around the fix. Sorry about that..

I added the lines below to my build.gradle (app)

    // This is what most people will need
    bundleInDebug: project.hasProperty("bundleInDebug") ? project.getProperty("bundleInDebug") : false,

    // If you use build variants it has to be like this - put your own names in there
    bundleInDevDebug: project.hasProperty("bundleInDevDebug") ? project.getProperty("bundleInDevDebug") : false,
    bundleInQaDebug: project.hasProperty("bundleInQaDebug") ? project.getProperty("bundleInQaDebug") : false,
    bundleInStagingDebug: project.hasProperty("bundleInStagingDebug") ? project.getProperty("bundleInStagingDebug") : false,
    bundleInProdDebug: project.hasProperty("bundleInProdDebug") ? project.getProperty("bundleInProdDebug") : false

Then ran this command:

ORG_GRADLE_PROJECT_bundleInDevDebug=false npx react-native run-android --variant=release

But unfortunately, I am still getting the duplicate resources errors.

  • What went wrong:
    Execution failed for task ':app:mergeReleaseResources'.

[drawable-xhdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-xhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png [drawable-xhdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-xhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png: Error: Duplicate resources
[drawable-xxhdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png [drawable-xxhdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-xxhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png: Error: Duplicate resources
[drawable-hdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-hdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png [drawable-hdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-hdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png: Error: Duplicate resources
[drawable-mdpi-v4/src_img_avatarunisex] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/src_img_avatarunisex.png [drawable-mdpi-v4/src_img_avatarunisex] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/src_img_avatarunisex.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnativeratings_src_images_rocket] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativeratings_src_images_rocket.png [drawable-mdpi-v4/node_modules_reactnativeratings_src_images_rocket] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnativeratings_src_images_rocket.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnativeratings_src_images_heart] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativeratings_src_images_heart.png [drawable-mdpi-v4/node_modules_reactnativeratings_src_images_heart] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnativeratings_src_images_heart.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnativeratings_src_images_airbnbstarselected] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativeratings_src_images_airbnbstarselected.png [drawable-mdpi-v4/node_modules_reactnativeratings_src_images_airbnbstarselected] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnativeratings_src_images_airbnbstarselected.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backiconmask] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnavigationstack_lib_module_views_assets_backiconmask.png [drawable-mdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backiconmask] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnavigationstack_lib_module_views_assets_backiconmask.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnativeratings_src_images_star] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativeratings_src_images_star.png [drawable-mdpi-v4/node_modules_reactnativeratings_src_images_star] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnativeratings_src_images_star.png: Error: Duplicate resources
[drawable-mdpi-v4/src_img_bb] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/src_img_bb.png [drawable-mdpi-v4/src_img_bb] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/src_img_bb.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnativeratings_src_images_bell] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativeratings_src_images_bell.png [drawable-mdpi-v4/node_modules_reactnativeratings_src_images_bell] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnativeratings_src_images_bell.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnativeratings_src_images_airbnbstar] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativeratings_src_images_airbnbstar.png [drawable-mdpi-v4/node_modules_reactnativeratings_src_images_airbnbstar] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnativeratings_src_images_airbnbstar.png: Error: Duplicate resources
[drawable-mdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-mdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png [drawable-mdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-mdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png: Error: Duplicate resources
[drawable-xxxhdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png [drawable-xxxhdpi-v4/node_modules_reactnavigationstack_lib_module_views_assets_backicon] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/drawable-xxxhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_feather] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_feather.json [raw/node_modules_reactnativevectoricons_glyphmaps_feather] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_feather.json: Error: Duplicate resources
[raw/app] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/app.json [raw/app] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/app.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_fontawesome] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_fontawesome.json [raw/node_modules_reactnativevectoricons_glyphmaps_fontawesome] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_fontawesome.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_zocial] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_zocial.json [raw/node_modules_reactnativevectoricons_glyphmaps_zocial] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_zocial.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_entypo] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_entypo.json [raw/node_modules_reactnativevectoricons_glyphmaps_entypo] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_entypo.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_antdesign] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_antdesign.json [raw/node_modules_reactnativevectoricons_glyphmaps_antdesign] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_antdesign.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_foundation] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_foundation.json [raw/node_modules_reactnativevectoricons_glyphmaps_foundation] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_foundation.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_evilicons] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_evilicons.json [raw/node_modules_reactnativevectoricons_glyphmaps_evilicons] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_evilicons.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_octicons] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_octicons.json [raw/node_modules_reactnativevectoricons_glyphmaps_octicons] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_octicons.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_simplelineicons] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_simplelineicons.json [raw/node_modules_reactnativevectoricons_glyphmaps_simplelineicons] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_simplelineicons.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_materialcommunityicons] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_materialcommunityicons.json [raw/node_modules_reactnativevectoricons_glyphmaps_materialcommunityicons] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_materialcommunityicons.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_materialicons] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_materialicons.json [raw/node_modules_reactnativevectoricons_glyphmaps_materialicons] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_materialicons.json: Error: Duplicate resources
[raw/node_modules_reactnativevectoricons_glyphmaps_ionicons] /Users/co-de/ReactNativeProjects/my_app/android/app/src/main/res/raw/node_modules_reactnativevectoricons_glyphmaps_ionicons.json [raw/node_modules_reactnativevectoricons_glyphmaps_ionicons] /Users/co-de/ReactNativeProjects/my_app/android/app/build/generated/res/react/release/raw/node_modules_reactnativevectoricons_glyphmaps_ionicons.json: Error: Duplicate resources

Am I missing something obvious & easy :( ?

@mikehardy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I can say is look very critically at the commands and variables proposed, they are not one size fits all, you'll need to understand what each is doing and why, and what it should be in your project

You may also need to flush everything out first npx react-native-clean-project

@co-de
Copy link

@co-de co-de commented on 962437f Aug 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Mike. So from your comments, I understand that contrary to what most people are trying to do (copying the drawable* folders from under "generated" to under "src" with a doLast method inside react.gradle) drawable* folders should not exist under "src/main/res" in the first place. Is that correct?

@mikehardy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything should be in src, including drawables if you have them (your icons, perhaps, but not things from other modules)
nothing should be manually copied
gradle can do all the work needed if called correctly

I recognize all that is oblique / vague / etc - but the main point is that manual copying is a "smell" - if you are doing that something is wrong. It might work for a while, it might get you moving for now, but something is wrong

@ankitsinghh121
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@co-de Did you find any fix for this? I am into same problem

@VesperHan
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why cannot push these code to the repo? the react team didn't fix the bug, let the bug exist in today?

@ankitsinghh121
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VesperHan First check whether the problem occurs while running in debug also, if that happens there might be a chance that somebody mistakenly pushed some generated assets and since its is getting generated again while building so throwing the error.
If this happens in only release not debug just check whether you are bundling separately and then then doing assemblerelease with the bundleInRelease flag set to true in your build.gradle. If that's the case just don't bundle because the bundling task is automatically done by react.gradle file.

@mikehardy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VesperHan - your comment is unfortunately full of assumptions, all wrong:

Why cannot push these code to the repo?

There was code pushed to the repo. It turned out to be the wrong solution. It was reverted. Pushing code to a repo is not the issue here

the react team didn't fix the bug, let the bug exist in today?

There is no bug. Your project is doing something wrong. I learned this the very hard way (this was my commit, and it was the wrong solution), you can follow the comments above. You have a project-specific thing to fix, there is no bug and there will be no "fix" here I don't think

@ankitsinghh121
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikehardy Right dude, I had the exact same problem but after a long troubleshooting and digging the old PRs I came to know that this problem occured the last time also when RN Upgrade was done and somebody wrote a script to patch react.gradle to copy assets at one place. What they failed to realise that new react native version introduced react.gradle which will automatically bundle and generate assets based on flag bundleInRelease in build.gradle which was set to true. So I stopped bundling separately and just did assembleRelease and the build worked like charm.
Also I was getting the same issue in debug mode before facing in release build so I just noted down the duplicate assets and deleted them from the project.

Please sign in to comment.