React Native: Ошибка: дублирующиеся ресурсы - Android - PullRequest
0 голосов
/ 10 ноября 2018

Я пытался создать APK-файл релиза из Android, но когда я создаю APK-файл релиза с изображением PNG, я получаю ошибку Duplicate Resource. Сначала я думал, что это происходит, потому что я допустил ошибку в существующем проекте, но когда я создал новый проект с одним компонентом Image, я получаю ошибку Duplicate Resource. Вот шаги, за которыми я следовал

  1. Создать приложение - react-native init demo
  2. Создайте папку ресурсов в корневой папке проекта.
  3. Добавить изображение PNG в папку ресурсов.
  4. Теперь добавьте компонент Image с изображением PNG, приведенным выше.
  5. Теперь свяжите его, используя cmd

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

  6. Затем сгенерируйте релиз apk, используя Generate Signed APK из Android Studio.

Это выдаст следующую ошибку:

[drawable-mdpi-v4/assets_mario] /Users/jeffreyrajan/Tutorials/RN/errorCheck/android/app/src/main/res/drawable-mdpi/assets_mario.png [drawable-mdpi-v4/assets_mario] /Users/jeffreyrajan/Tutorials/RN/errorCheck/android/app/build/generated/res/react/release/drawable-mdpi-v4/assets_mario.png: Error: Duplicate resources
:app:mergeReleaseResources FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeReleaseResources'.
> [drawable-mdpi-v4/assets_mario] /Users/jeffreyrajan/Tutorials/RN/errorCheck/android/app/src/main/res/drawable-mdpi/assets_mario.png   [drawable-mdpi-v4/assets_mario] /Users/jeffreyrajan/Tutorials/RN/errorCheck/android/app/build/generated/res/react/release/drawable-mdpi-v4/assets_mario.png: Error: Duplicate resources

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 22s

Примечание. Когда вы генерируете release apk без изображения PNG, вы не получите никакой ошибки, оно создаст вам release apk.

Вот код других файлов.

App.js

import React, {Component} from 'react';
import {Platform, StyleSheet, Image, View} from 'react-native';

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Image source={require('./assets/mario.png')} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

package.json

{
  "name": "errorCheck",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.6.0-alpha.8af6728",
    "react-native": "0.57.4"
  },
  "devDependencies": {
    "babel-jest": "23.6.0",
    "jest": "23.6.0",
    "metro-react-native-babel-preset": "0.49.0",
    "react-test-renderer": "16.6.0-alpha.8af6728"
  },
  "jest": {
    "preset": "react-native"
  }
}

Есть какое-нибудь решение для этого?

Обновление:

Вот другие детали

classpath 'com.android.tools.build:gradle:3.1.4'

ext {
        buildToolsVersion = "27.0.3"
        minSdkVersion = 16
        compileSdkVersion = 27
        targetSdkVersion = 26
        supportLibVersion = "27.1.1"
    }

distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

Пробовал с Android Studio 3.0, 3.0.1, 3.1, 3.1.4 & 3.2

Ответы [ 5 ]

0 голосов
/ 25 июля 2019

Так что, в основном, отредактируйте файл /node_modules/react-native/react.gradle и добавьте doLast сразу после блока doFirst вручную.

doFirst { ... }
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()
}
0 голосов
/ 01 марта 2019

Удалите файлы, которые у вас могут быть:

Android / приложение / SRC / основные / RES / вытяжке-MDPI / Android / приложение / SRC / основные / RES / вытяжке-xhdpi / Android / приложение / SRC / основные / RES / вытяжке-xxhdpi / Запустите Build снова, это исправило проблему для меня.

0 голосов
/ 12 ноября 2018

Попробовав множество решений, я обнаружил, что работает только два решения. Вот они

Решение 1:

После объединения удалите папку drawable из Android Studio. Вы можете найти это в android/app/src/main/res/drawable

Решение 2:

В этом решении вам не нужно удалять какие-либо папки для рисования. Просто добавьте следующий код в файл act.gradle , который вы можете найти в node_modules/react-native/react.gradle path

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

Для справки я добавлю полный реаги.граль код файла здесь

import org.apache.tools.ant.taskdefs.condition.Os

def config = project.hasProperty("react") ? project.react : [];

def cliPath = config.cliPath ?: "node_modules/react-native/local-cli/cli.js"
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
def entryFile = config.entryFile ?: "index.android.js"
def bundleCommand = config.bundleCommand ?: "bundle"
def reactRoot = file(config.root ?: "../../")
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" : null ;


afterEvaluate {
    android.applicationVariants.all { def variant ->
        // Create variant and target names
        def targetName = variant.name.capitalize()
        def targetPath = variant.dirName

        // React js bundle directories
        def jsBundleDir = file("$buildDir/generated/assets/react/${targetPath}")
        def resourcesDir = file("$buildDir/generated/res/react/${targetPath}")

        def jsBundleFile = file("$jsBundleDir/$bundleAssetName")

        // Additional node and packager commandline arguments
        def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
        def extraPackagerArgs = config.extraPackagerArgs ?: []

        def currentBundleTask = tasks.create(
            name: "bundle${targetName}JsAndAssets",
            type: Exec) {
            group = "react"
            description = "bundle JS and assets for ${targetName}."

            // Create dirs if they are not there (e.g. the "clean" task just ran)
            doFirst {
                jsBundleDir.deleteDir()
                jsBundleDir.mkdirs()
                resourcesDir.deleteDir()
                resourcesDir.mkdirs()
            }

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

            // Set up inputs and outputs so gradle can cache the result
            inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
            outputs.dir jsBundleDir
            outputs.dir resourcesDir

            // Set up the call to the react-native cli
            workingDir reactRoot

            // Set up dev mode
            def devEnabled = !(config."devDisabledIn${targetName}"
                || targetName.toLowerCase().contains("release"))

            def extraArgs = extraPackagerArgs;

            if (bundleConfig) {
                extraArgs = extraArgs.clone()
                extraArgs.add("--config");
                extraArgs.add(bundleConfig);
            }

            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                commandLine("cmd", "/c", *nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}",
                    "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs)
            } else {
                commandLine(*nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}",
                    "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs)
            }

            enabled config."bundleIn${targetName}" ||
                config."bundleIn${variant.buildType.name.capitalize()}" ?:
                targetName.toLowerCase().contains("release")
        }

        // Expose a minimal interface on the application variant and the task itself:
        variant.ext.bundleJsAndAssets = currentBundleTask
        currentBundleTask.ext.generatedResFolders = files(resourcesDir).builtBy(currentBundleTask)
        currentBundleTask.ext.generatedAssetsFolders = files(jsBundleDir).builtBy(currentBundleTask)

        // registerGeneratedResFolders for Android plugin 3.x
        if (variant.respondsTo("registerGeneratedResFolders")) {
            variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders)
        } else {
            variant.registerResGeneratingTask(currentBundleTask)
        }
        variant.mergeResources.dependsOn(currentBundleTask)

        // packageApplication for Android plugin 3.x
        def packageTask = variant.hasProperty("packageApplication")
            ? variant.packageApplication
            : tasks.findByName("package${targetName}")

        def resourcesDirConfigValue = config."resourcesDir${targetName}"
        if (resourcesDirConfigValue) {
            def currentCopyResTask = tasks.create(
                name: "copy${targetName}BundledResources",
                type: Copy) {
                group = "react"
                description = "copy bundled resources into custom location for ${targetName}."

                from resourcesDir
                into file(resourcesDirConfigValue)

                dependsOn(currentBundleTask)

                enabled currentBundleTask.enabled


            }

            packageTask.dependsOn(currentCopyResTask)
        }

        def currentAssetsCopyTask = tasks.create(
            name: "copy${targetName}BundledJs",
            type: Copy) {
            group = "react"
            description = "copy bundled JS into ${targetName}."

            if (config."jsBundleDir${targetName}") {
                from jsBundleDir
                into file(config."jsBundleDir${targetName}")
            } else {
                into ("$buildDir/intermediates")
                into ("assets/${targetPath}") {
                    from jsBundleDir
                }

                // Workaround for Android Gradle Plugin 3.2+ new asset directory
                into ("merged_assets/${targetPath}/merge${targetName}Assets/out") {
                    from jsBundleDir
                }
            }

            // mergeAssets must run first, as it clears the intermediates directory
            dependsOn(variant.mergeAssets)

            enabled currentBundleTask.enabled
        }

        packageTask.dependsOn(currentAssetsCopyTask)
    }
}

Кредит: ZeroCool00 mkchx

0 голосов
/ 18 декабря 2018

Я столкнулся с той же проблемой после использования 0.57.7, Посмотрите на файл node_modules/react-native/react.gradle, Выходной каталог ресурса - $buildDir/generated/res/react/${targetPath}. Посмотрите на адрес из журнала как app/build/generated/res/react/release,

Command React-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src /main/res/

Каталог вывода ресурса android/app/src/main/res/

Проблема здесь.

Я решил это:

  1. Удалить дубликаты файлов в android/app/res (Если ваши ресурсы импортированы из React Native, вы можете напрямую удалить каталог под res).

  2. Удалить папку App/build.

  3. Будет react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/ App/src/main/res/

изменить на react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle

Больше не указывайте --assets-dest Запустить команду

  1. Используйте Android Studio's Generate Signed APK для правильной упаковки.

выше

0 голосов
/ 10 ноября 2018

Используйте com.android.tools.build:gradle:3.1.4. Это должно работать. RN 0.57 имеет проблемы со сборкой в ​​3.2

Этот вопрос является возможным дубликатом:

Реагирует на собственную ошибку: дубликаты ресурсов, ресурсы, приходящие на некоторые экраны и не входящие на другие в выпуске Android APK

Если это все еще не работает, попробуйте использовать RN 0.57.2, я использую его, и создание релизов очень хорошо работает с этими deps:

   "dependencies": {
    "react": "16.5.0",
    "react-native": "0.57.2",
    .......
  }

  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-proposal-decorators": "^7.0.0",
    "@babel/plugin-proposal-do-expressions": "^7.0.0",
    "@babel/plugin-proposal-export-default-from": "^7.0.0",
    "@babel/plugin-proposal-export-namespace-from": "^7.0.0",
    "@babel/plugin-proposal-function-bind": "^7.0.0",
    "@babel/plugin-proposal-function-sent": "^7.0.0",
    "@babel/plugin-proposal-json-strings": "^7.0.0",
    "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
    "@babel/plugin-proposal-numeric-separator": "^7.0.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
    "@babel/plugin-proposal-optional-chaining": "^7.0.0",
    "@babel/plugin-proposal-pipeline-operator": "^7.0.0",
    "@babel/plugin-proposal-throw-expressions": "^7.0.0",
    "@babel/plugin-syntax-dynamic-import": "^7.0.0",
    "@babel/plugin-syntax-import-meta": "^7.0.0",
    "@babel/plugin-syntax-object-rest-spread": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-flow": "^7.0.0",
    "@babel/register": "^7.0.0",
    "babel-core": "^7.0.0-bridge.0",
    "babel-preset-react-native-stage-0": "^1.0.1",
    .....
}

Грейдс:

classpath 'com.android.tools.build:gradle:3.1.4'
classpath "io.realm:realm-gradle-plugin:4.0.0"

Приложение Gradle

compileSdkVersion 27
    buildToolsVersion "27.0.3"

    defaultConfig {
        applicationId "de.burda.buntede"
        minSdkVersion 17
        targetSdkVersion 27

Реквизит грейфера:

distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

...