71 votes

Réaction native erreur de fichier dupliqué Android lors de la génération apk

Lorsque j'essaie de générer un apk Android en utilisant ./gradlew installRelease , j'obtiens cette erreur dans la console:

 ~/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.
 

J'ai essayé Build->Clean Project via Android Studio couru ./gradlew installRelease à nouveau; cela n'a pas fonctionné non plus.

En outre, j'ai essayé de supprimer le dossier build , mais cela n'aide pas non plus.

147voto

Nhan Cao Points 1430

Donner quelques conseils pour vous, j'espère que c'est le travail.

Mise à jour avec "réagir": "16.7.0", "réagir indigènes": "0.57.8"

Personnalisé node_modules/réagir indigènes/réagir.gradle pour résoudre la Double erreur de fichier parfaitement. Ajouter le code suivant dans currentBundleTask's de création de bloc (après doFirst bloc)

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

Vous pouvez créer un script pour le faire automatiquement.

  1. Créer android-react-gradle-fix le fichier
  2. Créer un script android-release-gradle-fix.js le fichier
  3. Mise à jour de package.json le fichier:

    "scripts": { "postinstall": "nœud ./android-release-gradle-fix.js" },

Ça y est! Exécutez npm install pour obtenir impressionnant.

Remarque: Si vous exécutez npm install de ci, comme jenkins, vous pouvez obtenir l'erreur: postinstall: cannot run in wd %s %s (wd=%s) node => suffit d'utiliser npm install --unsafe-perm au lieu

40voto

Mapsy Points 2195

Au moment de la rédaction, les versions les plus récentes de Réagir Natif (>0.57.0) ont augmenté la Gradle wrapper niveau de 4,4 et Gradle plugin pour 3.1.4, comme indiqué par le changelog. Cela a pour effet de rendre le processus de build Gradle stocker les résultats de AAPT, qui sont maintenant nécessaires, dans un autre répertoire que précédemment.

En termes de Nhan Cao's awesome solution de contournement, nous avons besoin de faire une légère modification pour empêcher la duplication des ressources collisions, car il a l'air d'être signalé à l'ancien répertoire et non pas l'application de l' generated répertoire. En changeant le répertoire cible où ces fichiers en double sont fusionnées après les ressources ont été générés, on peut encore dedup les ressources.

Existants react.gradle désigne le chemin d'accès ci-dessous:

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

Le double de chemins de fichier peuvent apparaître entre:

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

Comme solution, nous pouvons mettre à jour Nhan de la solution comme suit (assurez-vous d'inclure ceci dans l' currentBundleTask après la déclaration d' doFirst en 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()
}

Si votre application dépend /raw de l'actif aussi, la méthode décrite ci-dessous devrait vous aider:

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

37voto

MOSTRO Points 391

Supprimez les fichiers que vous pourriez avoir sur:

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

Exécutez à nouveau la compilation, cela a résolu le problème pour moi.

20voto

Josh Pinter Points 3814

Ne pas exécuter react-native bundle avant ./gradlew assembleRelease.

Pour moi, je courais react-native bundle avant l'exécution de l' ./gradlew assembleRelease.

J'ai été faire un semblable double message d'erreur avec un de mes actifs.

En regardant l' ./gradlew assembleRelease de sortie, je pourrais dire qu'il s'inspire de la JS bundle par lui-même (grâce à l' apply from: "../node_modules/react-native/react.gradle" votre build.gradle le fichier) de sorte qu'il n'était pas nécessaire d'exécuter manuellement react-native bundle avant de la main.

Si je n'avais tout simplement pas exécuter react-native bundle avant l'exécution d' ./gradlew assembleRelease tout fonctionnait très bien.

J'ai testé la Version de l'APK et le JS bundle charge très bien, y compris toutes les images.

Ma seule préoccupation est de savoir si la source maps --sourcemap-output (pour Bugsnag) sera créé. Si non, je suis sûr qu'il y a un moyen d'avoir ./gradlew assembleRelease générer de ceux aussi bien. J'ai juste pas encore testé.

6voto

WadeStar Points 59

Afin d'obtenir mon build de travail pour Réagir Natif 0.57.5, j'ai utilisé Mapsy's réponse avec une mineure d'amélioration. J'avais besoin d'être en mesure de construire pour de multiples saveurs et en général j'essaie d'éviter de coder en dur les choses. Lors de la recherche par le biais de mon react.gradle le fichier, je l'ai trouvé a la suite de variable défini:

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

Ainsi, au lieu de coder en dur le type de build/saveur dans le chemin comme ceci:

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

J'ai plutôt utilisé l' resourcesDir variable pour définir le originalDir chemin comme ceci:

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

Comme un résultat, mon doLast ressemble à ceci:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X