Android=からリリースapkファイルを作成しようとしましたが、PNG画像でリリースapkを作成するとDuplicate Resource
エラーが発生します。最初にこれは、既存のプロジェクトの間違いですが、単一のImage
コンポーネント自体で新しいプロジェクトを作成したときに、Duplicate Resource
エラーが発生します。
react-native init demo
PNG
画像を追加します。Image
イメージを使用してPNG
コンポーネントを実装します。次に、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/
次に、Generate Signed APK
からAndroid Studio
を使用してリリースAPKを生成します。
これにより、次のエラーがスローされます。
[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
注:PNG画像なしでrelease apk
を生成しても、エラーは発生せず、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
で試しました
多くの解決策を試した後、2つの解決策のみが機能していることがわかりました。どうぞ
ソリューション1:
バンドルした後、drawable
フォルダをAndroid Studio
から削除します。これはAndroid/app/src/main/res/drawable
で見つけることができます
ソリューション2:
元の作成者の提案に従って、ソリューション#2を使用しないでください!
node_modules
の下のすべてのパッケージが生成されます。react-native
パッケージを再インストール/アップグレードすると失われます。
このソリューションでは、ドローアブルフォルダーを削除する必要はありません。 react.gradleファイルにnode_modules/react-native/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()
}
参考のために、ここに完全なreact.gradleファイルコードを追加します
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)
}
}
このソリューションは私のために働きます
rm -rf ./Android/app/src/main/res/drawable-*
rm -rf ./Android/app/src/main/res/raw
デバッグapkを生成する場合
"debug-build": "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/ && cd Android && ./gradlew assembleDebug && cd .."
リリースAPKを生成する場合
"release-build": "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/build/intermediates/res/merged/release/ && rm -rf Android/app/src/main/res/drawable-* && rm -rf Android/app/src/main/res/raw/* && cd Android && ./gradlew assembleRelease && cd .."
私のreact-native> = 0.61.2プロジェクトでうまく機能します(scriptsセクションの上記のコードを使用してpackage.jsonファイル
受け入れられた回答は機能しますが、ノードパッケージを変更すると、変更を更新すると変更が失われることを考慮に入れていません(ベストプラクティスに反している場合は、モジュールを拡張する必要があります)。
これは元々 React-native Androidリリースエラー:リソースの重複 からのものです
プロジェクトの「Android」フォルダー({project-root}/Android/fixAndroid)に「fixAndroid」フォルダーを作成します。
プロジェクトの「fixAndroid」フォルダーにファイルAndroid-gradle-fixを作成します({project-root}/Android/fixAndroid/Android-gradle-fix)。
doLast {
def moveFunc = { resSuffix ->
File originalDir = file("${resourcesDir}/drawable-${resSuffix}")
if (originalDir.exists()) {
File destDir = file("${resourcesDir}/drawable-${resSuffix}-v4")
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
作成した「fixAndroid」フォルダーにファイルAndroid-release-fix.jsを作成します。
const fs = require('fs')
try {
var curDir = __dirname
var rootDir = process.cwd()
var file = `${rootDir}/node_modules/react-native/react.gradle`
var dataFix = fs.readFileSync(`${curDir}/Android-gradle-fix`, 'utf8')
var data = fs.readFileSync(file, 'utf8')
var doLast = "doLast \{"
if (data.indexOf(doLast) !== -1) {
throw "Already fixed."
}
var result = data.replace(/\/\/ Set up inputs and outputs so gradle can cache the result/g, dataFix);
fs.writeFileSync(file, result, 'utf8')
console.log('Android Gradle Fixed!')
} catch (error) {
console.error(error)
}
スクリプトをpackage.jsonスクリプトセクションに追加します。
"postinstall": "node ./Android/fixAndroid/Android-release-fix.js"
これにより、「Android-gradle-fix」ファイルのコンテンツが検出され、node_modules/react-native/react.gradleに挿入されます。
これで、リリースをReactコンソールまたはAndroid Studio:のいずれかにバンドルできます。
React Nativeコマンドライン
cd {project-root}/Android
./gradlew/bundleRelease
Android Studio
rNで同じ問題に直面している人!この問題が長い間ここに存在していることは非常に恐ろしいことだと思いますが、さまざまな解決策を調査した後、その解決方法を共有したいと思います。
ジェフリー・ラジャンはここで考えられる解決策について完全に正しいです https://stackoverflow.com/a/53260522/1611414
変更するのはとても悪いと思いますreact.gradle
ファイルnode_modules
そして、それはこのRNプロジェクトのメンテナンスで多くの多くの異なる問題につながります。だから私は最初のオプションを選択することをお勧めします-ビルドを実行する前にbashコマンドを使用してそのフォルダーを削除します。
私のプロジェクトで行ったことを共有したいと思います。おそらく同じアプローチを再利用できます。
// ./package.json
...
scripts: {
"build": "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/
&& rm -rf ./Android/app/src/main/res/drawable-mdpi/
&& rm -rf ./Android/app/src/main/res/raw/",
"release": "yarn build && cd ./Android && ./gradlew bundleRelease"
}
...
そして、リリースはyarn release
。
これらの行は非常に重要です:
...
&& rm -rf ./Android/app/src/main/res/drawable-mdpi/
&& rm -rf ./Android/app/src/main/res/raw/
...
build
が実行される前に、重複するリソースをbundleRelease
ステップから削除します。ソリューションはRN 0.57、0.58、0.59、0.60でテストされています
楽しい!
Com.Android.tools.build:gradle:3.1.4を使用してください。 RN 0.57は3.2でのビルドに問題があります
この質問は、次の重複の可能性があります。
React Native Error:重複するリソース、アセットが一部の画面に表示され、他の画面には表示されないAndroid release APK
それでも動作しない場合は、RN 0.57.2を使用してみてください。私はそれを使用しており、リリースの作成はこれらの依存関係で非常にうまく機能します。
"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",
.....
}
Gradle deps:
classpath 'com.Android.tools.build:gradle:3.1.4'
classpath "io.realm:realm-gradle-plugin:4.0.0"
アプリグラドル
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "de.burda.buntede"
minSdkVersion 17
targetSdkVersion 27
Gradleラッパーの小道具:
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.Zip
私にとってはキャッシュの問題でした。次のコマンドは私のために働きました
cd into Androidフォルダ
./gradlew cleanを実行します
tolotrasmileの答えは私のために働いた。
Androidをビルドしてインストールしたいときに実行する小さなbashスクリプトにそれを含めました
cd $PROJECT_DIRECTORY && 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
rm -rf $PROJECT_DIRECTORY/Android/app/src/main/res/drawable-*
rm -rf $PROJECT_DIRECTORY/Android/app/src/main/res/raw
cd $PROJECT_DIRECTORY/Android/
./gradlew clean
./gradlew assembleRelease
adb install -r $PROJECT_DIRECTORY/Android/app/build/outputs/apk/release/app-release.apk
存在する可能性のあるファイルを削除します。
Android/app/src/main/res/drawable-mdpi/Android/app/src/main/res/drawable-xhdpi/Android/app/src/main/res/drawable-xxhdpi /ビルドを再実行して、問題を修正しました私のために。