生成apk时React Native Android重复文件错误

问题描述 投票:45回答:7

当我尝试使用./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文件夹,但它也没有帮助。

android react-native apk
7个回答
121
投票

给你一些提示,希望它的工作。

用“react”更新:“16.7.0”,“react-native”:“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文件
  2. 创建脚本android-release-gradle-fix.js文件
  3. 更新package.json文件: “scripts”:{“postinstall”:“node ./android-release-gradle-fix.js”},

而已!运行npm install以获得真棒。

注意:如果你像cen一样在jenkins上运行npm install,你可能会收到错误:postinstall: cannot run in wd %s %s (wd=%s) node =>只需使用npm install --unsafe-perm代替


33
投票

删除您可能拥有的文件:

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

再次运行Build,这为我解决了这个问题。


25
投票

在撰写本文时,更新版本的React Native(> 0.57.0)已将Gradle包装器级别增加到4.4,Gradle插件增加到3.1.4,如changelog所示。这样可以使Gradle构建过程将AAPT的结果(现在需要)存储在与以前不同的目录中。

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的解决方案(确保在currentBundleTask中声明doFirst之后将其包含在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()
}

如果您的应用也依赖于/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()
}

14
投票

Do not run react-native bundle prior to ./gradlew assembleRelease.

对于我自己,我在运行react-native bundle之前运行./gradlew assembleRelease

我收到了一个类似的重复错误消息,其中包含我的一个资产。

看看./gradlew assembleRelease输出,我可以告诉它自己构建JS包(感谢你的apply from: "../node_modules/react-native/react.gradle"文件中的build.gradle)所以没有必要手动运行react-native bundle

如果我在运行react-native bundle之前根本没有运行./gradlew assembleRelease,一切都很好。

我测试了Release APK和JS捆绑加载,包括所有图像。

我唯一担心的是是否会创建源映射--sourcemap-output(用于Bugsnag)。如果没有,我相信有一种方法可以让./gradlew assembleRelease产生这些。我还没有测试过它。


5
投票

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

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

所以不要像这样在路径中硬编码构建类型/ flavor:

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

3
投票

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


0
投票

删除错误的方法是:

  • 将您的图像放在android / app / src / main / res / drawable文件夹中(如果不存在,则创建一个“drawable”文件夹)
  • 删除所有具有后缀的可绘制文件夹(即drawable-hdpi,drawable-mdpi等)
  • 不捆绑资产(即不运行:react-native bundle ...)
  • 运行Gradle的assembleRelease

但是,这不是一个理想的解决方案,因为每个图像只有一个分辨率适用于所有设备尺寸。对于对于设备来说太大的图像,它会使设备缩小尺寸并导致下载大小和速度问题,并且对于设备来说太小的图像会导致图像质量下降。

我发现一个方便的解决方案是使用名为Android Drawable Importer的Android Studio插件。安装后使用它:

  • 在Android工作室中打开您的项目并导航到:android / app / src / main / res / drawable
  • 右键单击该文件夹,然后选择:新建>批量可绘制导入
  • 选择并配置要导入的图像资源

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

© www.soinside.com 2019 - 2024. All rights reserved.