React原生Android生成apk时出现重复文件错误

4xy9mtcn  于 2023-01-21  发布在  React
关注(0)|答案(9)|浏览(204)

当我试图通过使用./gradlew installRelease生成Android APK时,我在控制台中得到这个错误:

~/React-Native/mockingbird/android/app/build/intermediates/res/merged/release/drawable-mdpi-v4/src_resources_img_loading.gif: error: Duplicate file.
~/React-Native/mockingbird/android/app/build/intermediates/res/merged/release/drawable-mdpi/src_resources_img_loading.gif: Original is here. The version qualifier may be implied.

我通过Android Studio尝试了Build->Clean Project,并再次运行./gradlew installRelease;也没成功。
此外,我尝试删除build文件夹,但它也没有帮助。

ltskdhd1

ltskdhd11#

给予你点建议,希望有用。
更新为“React”:“16.7.0”,“天然React”:“0.57.8”
自定义node_modules/react-native/react.gradle以完美解决 * 重复文件错误 *。将以下代码添加到currentBundleTask的创建块中(在doFirst块之后

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

您可以创建脚本来自动执行此操作。
1.创建android-react-gradle-fix文件
1.创建脚本android-release-gradle-fix.js文件
1.更新package.json文件:
“脚本”:{“安装后配置”:“节点。/安卓发布版本升级版修复。js”},
就是这样!运行npm install来获得awesome。

**注意:**如果像jenkins那样在ci上运行npm install,可能会出现错误:postinstall: cannot run in wd %s %s (wd=%s) node =〉只需使用npm install --unsafe-perm即可

xnifntxz

xnifntxz2#

在撰写本文时,更新版本的React Native(〉0.57.0)已将Gradle Package 器级别提升至4.4,并将Gradle插件提升至3.1.4,如changelog所示。这使得Gradle构建流程将AAPT的结果(现在是required)存储在与之前不同的目录中。
对于Nhan Caoawesome workaround,我们需要做一个小的修改,以防止重复资源冲突,因为它看起来指向旧目录,而不是应用的generated目录。通过更改在资源生成后合并这些重复文件的目标目录,我们仍然可以对资源进行重复数据删除。
现有的react.gradle引用以下路径:

$buildDir === <project-working-directory>/android/app/build

重复的文件路径可能出现在以下位置:

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

作为一种解决方案,我们可以按如下所示更新Nhan的解决方案(确保在react.gradle中声明doFirst之后将其包含在currentBundleTask中:

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()
}

如果您的应用也依赖于/raw资产,下面概述的方法应该会对您有所帮助:

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()
}

如果您的应用还使用release以外的自定义“构建类型”,如preReleasestagingRelease(Android Gradle插件允许您在build.gradle中定义它们),则应按如下所示更改originalDir变量:

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

carvr3hs3#

删除您在以下位置可能拥有的文件:

android/app/src/main/res/drawable-mdpi/
android/app/src/main/res/drawable-xhdpi/
android/app/src/main/res/drawable-xxhdpi/

再次运行生成,这为我修复了问题。

hgb9j2n6

hgb9j2n64#

不要在运行./gradlew assembleRelease之前运行react-native bundle

就我自己而言,我在运行./gradlew assembleRelease之前运行的是react-native bundle
我的一个资产收到了类似的重复错误消息。
查看./gradlew assembleRelease的输出,我可以看出它自己构建了JS包(多亏了build.gradle文件中的apply from: "../node_modules/react-native/react.gradle"),所以没有必要事先手动运行react-native bundle
如果我只是在运行./gradlew assembleRelease之前没有运行react-native bundle,那么一切都运行得很好。
我测试了发布版APK,JS捆绑包加载正常,包括所有图像。
我唯一关心的是--sourcemap-output的源代码Map(用于Bugsnag)是否会被创建。如果没有,我相信有一种方法可以让./gradlew assembleRelease也生成这些Map。只是我还没有测试它。

r6hnlfcb

r6hnlfcb5#

为了让我的构建能够在React Native 0.57.5上运行,我使用了Mapsy的答案,并做了一些小的改进。我需要能够构建多种风格,通常我会尽量避免硬编码。当查看我的react.gradle文件时,我发现它定义了以下变量:

def resourcesDir = file("$buildDir/generated/res/react/${targetPath}")

因此,不要像这样在路径中硬编码构建类型/风味:

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

我改为使用resourcesDir变量来设置originalDir路径,如下所示:

File originalDir = file("${resourcesDir}/drawable-${resSuffix}");

因此,我的doLast看起来像这样:

doLast {
            def moveFunc = { resSuffix ->
                File originalDir = file("${resourcesDir}/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()
        }
exdqitrt

exdqitrt6#

对我来说,它的工作删除文件夹:android/build并再次运行./gradlew assembleRelease

qnyhuwrf

qnyhuwrf7#

对我有效的方法是在package.json中添加这个额外的命令,并使用它来构建:

"android-build-release": "cd ./android && rm -rf app/src/main/res/drawable* && ./gradlew app:assembleRelease",
qeeaahzv

qeeaahzv8#

1.删除drawable-xxx文件夹2.删除src -〉main -〉res文件夹中的原始文件,然后
3.run 终端中的此命令:

react-native bundle --dev false --platform android --entry-file index.js --bundle-output ./android/app/src/main/assets/index.android.bundle --assets-dest ./android/app/src/main/res_temp

4.然后使用终端或android studio生成使用密钥库,别名和密码签名的apk

4dbbbstv

4dbbbstv9#

消 debugging 误的方法是:

  • 把你的图像放在android/app/src/main/res/drawable文件夹中(创建一个“drawable”文件夹如果它不存在)
  • 删除所有带后缀的可绘制文件夹(即drawable-hdpi,drawable-mdpi,etc)
  • 不要捆绑资产(即不要运行:React-本机捆绑包...)
  • 运行Gradle的组装发布

然而,这并不是一个理想的解决方案,因为对于所有设备大小,每个图像都只有一个分辨率。对于对于设备来说太大的图像,它会让设备去缩小,并导致下载大小和速度问题,而对于设备来说太小的图像,它会导致图像质量下降。
我发现的一个方便的解决方案是使用一个名为Android Drawable Importer的Android Studio插件。要在安装后使用它:

  • 在Android Studio中打开您的项目,然后导航至:安卓/应用程序/源代码/主文件/res/可绘制
  • 右键单击文件夹并选择:新建〉批量可绘制导入
  • 选择并配置要导入的图像资源

该插件将处理可绘制文件夹的生成和正确的图像大小。导入图像后,您应该能够运行Gradle的assembleRelease,而不会出现重复资源错误。

相关问题