React Native Android Duplicate file error при создании apk
Когда я пытаюсь создать android apk с помощью ./gradlew installRelease
, я получаю эту ошибку в консоли:
~/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.
Я попробовал Build->Clean Project
через Android Studio и снова запустил ./gradlew installRelease
; это тоже не сработало.
Кроме того, я попытался удалить папку build
, но это тоже не помогает.
Ответы
Ответ 1
Дайте несколько советов для вас, надеюсь, это сработает.
Обновите с помощью "реакции": "16.7.0", "реакция-нативная": "0.57.8"
Пользовательский узел_модулей/реагировать-нативный/реагировать .gradle, чтобы идеально решить ошибку Duplicate file. Добавьте следующий код в блок создания 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
:
"сценарии": { "postinstall": "node./android-release-gradle-fix.js"
},
Это! Запустите npm install
, чтобы стать классным.
Примечание: Если вы запускаете npm install
на ci, как jenkins, вы можете получить ошибку: postinstall: cannot run in wd %s %s (wd=%s) node
=> просто используйте вместо этого npm install --unsafe-perm
Ответ 2
Удалите файлы, которые у вас могут быть:
android/app/src/main/res/drawable-mdpi/
android/app/src/main/res/drawable-xhdpi/
android/app/src/main/res/drawable-xxhdpi/
Запустите Build снова, это исправило проблему для меня.
Ответ 3
На момент написания этой статьи более поздние версии React Native (> 0.57.0) увеличили уровень оболочки Gradle до 4.4, а плагин Gradle - до 3.1.4, как указано в changelog. В результате процесс сборки Gradle сохраняет результаты AAPT, которые теперь необходимы, в другом каталоге, чем ранее.
С точки зрения Нхан Цаопотрясающего обходного пути, нам нужно внести небольшие изменения, чтобы предотвратить повторяющиеся конфликты ресурсов, так как он выглядит как направленный на старый каталог, а не на каталог app 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()
}
Ответ 4
Не запускайте react-native bundle
до ./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}")
Таким образом, вместо жесткого кодирования типа сборки/разновидности в пути, вот так:
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()
}
Ответ 6
Для меня это работает, чтобы удалить папку: android/build
и запустить ./gradlew assembleRelease
снова.
Ответ 7
Способ устранения ошибки:
- поместите ваши изображения в папку android/app/src/main/res/drawable (создайте "drawable" папку, если таковой не существует)
- удалите все папки для рисования, которые имеют суффиксы (т.е. drawable-hdpi, drawable-mdpi и т.д.)
- не связывать активы (т.е. не запускать: реагировать на нативную связку…)
- запустить Gradles собрать
Однако это не идеальное решение, потому что каждое изображение будет иметь только одно разрешение для всех размеров устройства. Для изображений, которые слишком велики для устройства, они уменьшают масштаб до уровня устройства и приводят к проблемам с размером и скоростью загрузки, а для изображений, которые слишком малы для устройства, это приводит к снижению качества изображения.
Я нашел одно удобное решение - использовать плагин Android Studio под названием Android Drawable Importer. Чтобы использовать его после его установки:
- откройте свой проект в Android-студии и перейдите по адресу: Android/App/SRC/Main/Res/Drawable
- щелкните правой кнопкой мыши на папке и выберите: "Создать"> "Пакетный импорт"
- выбрать и настроить изображения для импорта
Плагин будет обрабатывать создание нарисованных папок и корректные размеры изображений. После того, как вы импортировали свое изображение, вы сможете запускать Gradles assemblyRelease без ошибки повторяющихся ресурсов.
Ответ 8
Для меня сработало просто добавить эту дополнительную команду в package.json
и использовать ее для сборки:
"android-build-release": "cd ./android && rm -rf app/src/main/res/drawable* && ./gradlew app:assembleRelease",