React Native Android Duplicate file error when generating apk

后端 未结 8 1478
生来不讨喜
生来不讨喜 2020-11-30 20:30

When I am trying to generate android apk by using ./gradlew installRelease, I get this error in console:

~/React-Native/mockingbird/android/app/         


        
8条回答
  •  暖寄归人
    2020-11-30 21:23

    At the time of writing, the more recent versions of React Native (>0.57.0) have increased the Gradle wrapper level to 4.4 and Gradle plugin to 3.1.4, as indicated by the changelog. This has the effect of making the Gradle build process store the results of AAPT, which are now required, within a different directory than previously.

    In terms of Nhan Cao's awesome workaround, we need to make a slight modification to prevent duplicate resource collisions, since it looks to be pointed at the old directory and not the app's generated directory. By changing the target directory where these duplicate files are merged together after the resources have been generated, we can still dedup the resources.

    The existing react.gradle refers to the path below:

    $buildDir === /android/app/build
    

    The duplicate file paths can appear between:

    file("$buildDir/../src/main/res/drawable-${resSuffix}")
    file("$buildDir/generated/res/react/release/drawable-${resSuffix}")
    

    As a workaround, we can update Nhan's solution as follows (be sure to include this within the currentBundleTask after the declaration of doFirst in react.gradle:

    doLast {
        def moveFunc = { resSuffix ->
            File originalDir = file("$buildDir/generated/res/react/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()
    }
    

    If your app depends on /raw assets too, the method outlined below should help you:

    doLast {
        def moveFunc = { resSuffix ->
            File originalDir = file("$buildDir/generated/res/react/release/${resSuffix}");
            if (originalDir.exists()) {
                File destDir = file("$buildDir/../src/main/res/${resSuffix}");
                ant.move(file: originalDir, tofile: destDir);
            }
         }
         moveFunc.curry("drawable-ldpi").call()
         moveFunc.curry("drawable-mdpi").call()
         moveFunc.curry("drawable-hdpi").call()
         moveFunc.curry("drawable-xhdpi").call()
         moveFunc.curry("drawable-xxhdpi").call()
         moveFunc.curry("drawable-xxxhdpi").call()
         moveFunc.curry("raw").call()
    }
    

    If your app also uses custom "build types" other than release, such as preRelease or stagingRelease(Android Gradle Plugin allows you to define them in build.gradle), you should change originalDir variable like below:

    # from
    File originalDir = file("$buildDir/generated/res/react/release/drawable-${resSuffix}");
    # to 
    File originalDir = file("$buildDir/generated/res/react/${targetName}/drawable-${resSuffix}");
    

提交回复
热议问题