当我尝试使用./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
文件夹,但它也没有帮助。
给你一些提示,希望它的工作。
用“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()
}
您可以创建脚本以自动执行此操作。
android-react-gradle-fix
文件android-release-gradle-fix.js
文件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
代替
删除您可能拥有的文件:
android/app/src/main/res/drawable-mdpi/
android/app/src/main/res/drawable-xhdpi/
android/app/src/main/res/drawable-xxhdpi/
再次运行Build,这为我解决了这个问题。
在撰写本文时,更新版本的React Native(> 0.57.0)已将Gradle包装器级别增加到4.4,Gradle插件增加到3.1.4,如changelog所示。这样可以使Gradle构建过程将AAPT的结果(现在需要)存储在与以前不同的目录中。
就Nhan Cao的awesome 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()
}
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
产生这些。我还没有测试过它。
为了让我的构建工作为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()
}
对我来说,删除文件夹:android/build
并再次运行./gradlew assembleRelease
。
删除错误的方法是:
但是,这不是一个理想的解决方案,因为每个图像只有一个分辨率适用于所有设备尺寸。对于对于设备来说太大的图像,它会使设备缩小尺寸并导致下载大小和速度问题,并且对于设备来说太小的图像会导致图像质量下降。
我发现一个方便的解决方案是使用名为Android Drawable Importer的Android Studio插件。安装后使用它:
该插件将处理可绘制文件夹的生成和正确的图像大小。导入图像后,您应该能够运行Gradle的assembleRelease而不会出现重复资源错误。