React Native ํ๊ฒฝ ์ ๋ณด :
System:
OS: macOS 10.14
CPU: (4) x64 Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz
Memory: 103.10 MB / 8.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 8.12.0 - /usr/local/bin/node
Yarn: 1.0.1 - /usr/local/bin/yarn
npm: 6.4.1 - /usr/local/bin/npm
Watchman: 4.7.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.1, macOS 10.14, tvOS 12.1, watchOS 5.1
Android SDK:
API Levels: 16, 17, 19, 21, 23, 24, 25, 26, 27, 28
Build Tools: 19.1.0, 20.0.0, 23.0.1, 23.0.2, 23.0.3, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.0, 26.0.1, 26.0.2, 26.0.3, 27.0.0, 27.0.1, 27.0.3, 28.0.0, 28.0.0, 28.0.2, 28.0.3
System Images: android-16 | ARM EABI v7a, android-16 | MIPS, android-16 | Intel x86 Atom, android-16 | Google APIs Intel x86 Atom, android-19 | Google APIs Intel x86 Atom, android-24 | Google Play Intel x86 Atom, android-26 | Google APIs Intel x86 Atom, android-26 | Google APIs Intel x86 Atom_64, android-26 | Google Play Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-P | Google APIs Intel x86 Atom, android-P | Google Play Intel x86 Atom
IDEs:
Android Studio: 3.2 AI-181.5540.7.32.5056338
Xcode: 10.1/10B61 - /usr/bin/xcodebuild
npmPackages:
react: 16.6.0-alpha.8af6728 => 16.6.0-alpha.8af6728
react-native: 0.57.4 => 0.57.4
npmGlobalPackages:
babel-preset-react-native: 4.0.0
react-native-cli: 2.0.1
react-native-create-library: 3.1.2
react-native-git-upgrade: 0.2.7
Android์์ PNG ์ด๋ฏธ์ง๋ก ๋ฆด๋ฆฌ์ค APK๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ PNG ์ด๋ฏธ์ง๊ฐ์๋ ๊ฒฝ์ฐ ๋ฆด๋ฆฌ์ค 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
react-native init demo
assets
ํด๋๋ฅผ ๋ง๋ญ๋๋ค.image
๊ตฌ์ฑ ์์๋ฅผ ๊ตฌํํฉ๋๋ค.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
์ฌ์ฉํ์ฌ ๋ฆด๋ฆฌ์ค APK๋ฅผ ์์ฑํฉ๋๋ค.https://github.com/facebook/react-native/issues/19239#issuecomment -414564404๋ฅผ ํ์ธ
๋๋ก์ด ๋ธ ํด๋ ์ด๋ฏธ์ง๊ฐ์๋ ๊ฒฝ์ฐ ์ ๊ฑฐํด์ผํฉ๋๊น?
@ ZeroCool00 ์ Android์ ์ด๋ฏธ์ง์ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๊น?
Mapsy์ ๋ต๋ณ์ https://stackoverflow.com/a/52750886์ ๋์์ด ๋ ๊ฒ์
๋๋ค.
๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก /node_modules/react-native/react.gradle ํ์ผ์ ํธ์งํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋์ผ๋ก doFirst ๋ธ๋ก ํ doLast์ ๊ถ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
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()
}
@ ZeroCool00 @mkchx ๋ ๊ฐ์ง ๋ต๋ณ์ ๋ชจ๋ ํ์ธํ์ต๋๋ค. ๋ง์ ์ฌ๋๋ค์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค :)
์๋ ํ์ญ๋๊น, ์ ํจ์ค ์์ ์ผ๋ก ์ด๋ป๊ฒ์ด ์์ ์ ์ํ ํ ์ ์์ต๋๊น? npm ์ค์น๋ฅผ ํญ์ ์ํํ๋ฏ๋ก react.gradle ํ์ผ์์ด ๋ณ๊ฒฝ ์ฌํญ์ ๋ฌด์ํฉ๋๋ค. ์๋๋ก์ด๋ ์ฉ ์๋๋ก์ด๋ ์คํ๋์ค์์ ๋น๋๋ฅผ ๋ง๋ค ์ ์์ง๋ง ์ ํจ์ค์์๋ ๊ฐ๋ฅํ์ง ์์ต๋๋ค.
์๋ ํ์ธ์ @ vivek-walecha-657 ๋๋ ์ด๊ฒ์ ์๋ํ์ง ์์์ง๋ง ์คํ๋ผ์ธ ๋ฒ๋ค๋ง์ ๋ง๋ค๊ธฐ ์ํด์ด ๋ช ๋ น์ ์๋ ํ ์ ์์ต๋๋ค.
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle
@jeffreyrajanofficial ์์ฑ์ ์ํด Thanx, ๋น์ ์ด ์ ๊ณต ํ ์๋ฃจ์ ์ ์ฐ๋ฆฌ๊ฐ ๊ฐ์ react.gradle ํ์ผ์ ๋ณ๊ฒฝํ๋ฉด ๋์์ด ๋ ๊ฒ์ ๋๋ค. ํ์ง๋ง npm์ ์ด๋์๋ ์ค์นํ ๋๋ง๋ค react.gradle ํ์ผ์ ๋ณ๊ฒฝํ์ฌ ๋ฆด๋ฆฌ์ค๋ฅผ ๋ง๋ค๊ณ ์ถ์ง ์์ต๋๋ค.
@jeffreyrajanofficial ์ด ๋ฌธ์ ์์ด ์ด๋ค ๋ฒ์ (์ด๋ณด๋ค ๋ฎ๊ฑฐ๋ ์ด๋ณด๋ค ๋์ ์ต์ ๋ฒ์ )์ด ์ ๋๋ก ์๋ํ๋์ง ์๋ ค์ฃผ์ธ์. ๋ฆด๋ฆฌ์ค ์ ๋ณด๋์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์์ ์๋ฆฌ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด์ RN> 57์์ ์ ๋ ฌ๋ฉ๋๋ค. react.gradle ํ์ผ์ ์๋์ผ๋ก ๋ฒ๋ค์ ์์ฑํฉ๋๋ค.
๋ฆด๋ฆฌ์ค ๋น๋๋ฅผ ๋ง๋ค๊ธฐ ์ํด npm run build : android : release ๋ฅผ ์คํํ ํ์๊ฐ ์์ต๋๋ค
์ฌ๊ธฐ์ 55.4 ๋ฐ์ ๋ค์ดํฐ๋ธ ๋ฒ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ์์ ์ฌํญ์ด์๋ build.gradle package.json์ ๋ํ ์ํ ํ๋ก์ ํธ ์์ ์ ๋๋ค.
https://gist.github.com/Abhishekgarg727/daf031fb9f94fdfd985e84db57dedbe1
macOS 10.14.3 + RN 0.57.8 + Android Studio 3.3 + Gradle 4.10.3์ ์ฌ์ฉํ์ฌ ์ฌ์ ํ ์ด๊ฒ์๋ณด๊ณ ์์์ต๋๋ค. ๋ด๊ฐ ์ ์ผํ ์ฌ๋์ด ์๋๊น์? ์๋๋ฉด ์ฌ๊ธฐ ๋๊ตฐ๊ฐ๊ฐ ์๋ํ๋์ง ํ์ธํ ์ ์์ผ๋ฏ๋ก ๋ ๋ง์ด ํ๊ณ ์ค์ ๋ก ์์ ํ๊ฒ ์ต๋๋ค.
์ ๋ ํ์ฌ @mkchx ( .txt
์ ๋ฏธ์ฌ๊ฐ ์ถ๊ฐ๋์ด github์์ ์ฒจ๋ถ ํ์ผ์ ํ์ฉ ํจ) ์ ์ ์ฃผ์ ์ ๊ธฐ๋ฐ์ผ๋ก ์ฒจ๋ถ ๋ ํจ์น์ ํจ๊ป "patch-package"ํจํค์ง ๋ฅผ ์ฌ์ฉํ์ฌ ์๋์ผ๋ก ์์
ํ๊ณ ์์ต๋๋ค. ๋ด package.json ์คํฌ๋ฆฝํธ์ postinstall: patch-package
์ ์ถ๊ฐ ํ ํ 'npm install'์์ ์์ ํ์ญ์์ค.
๋๊ตฐ๊ฐ์๊ฒ ์ ์ฉ ํ ์๋ ์์ต๋๋ค ...
react-native + 0.57.8.patch.txt
๊ฐ์ง๊ณ ์์ ์์๋ ํ์ผ์ ์ ๊ฑฐํ์ญ์์ค.
์๋๋ก์ด๋ / ์ฑ / src / main / res / drawable-mdpi /
์๋๋ก์ด๋ / ์ฑ / src / main / res / drawable-xhdpi /
์๋๋ก์ด๋ / ์ฑ / src / main / res / drawable-xxhdpi /
๋น๋๋ฅผ ๋ค์ ์คํํ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๋ค.
๋๋ ์ฌ์ ํ RN0.58.x์์ ์ด๊ฒ์ ๋ณด์๊ณ RN0.59.x์์ ๊ณ์๋ฉ๋๋ค-์ฐ๋ฆฌ๊ฐ ์ฌ๊ธฐ์ ๋ญ๊ฐ ์๋ชปํ๊ณ ์์ต๋๊น ์๋๋ฉด ์ด๊ฒ์ด ์ ๋ง๋ก ๋ฒ๊ทธ์ ๋๊น?
ํจ์น ํจํค์ง ๋ชจ๋ ๋ฐ์ด ํจ์น (RN0.59.1 ์ฉ์ผ๋ก ์ ๋ฐ์ดํธ ๋จ)์ ํจ๊ป ์ฌ์ฉํ๊ธฐ ์ํด ํจ์น ๋๋ ํ ๋ฆฌ์ ํจ์น ํ์์ผ๋ก ์ธ์ฝ๋ฉ ๋ @mkchx ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ์ ์ฑ๊ณตํ์ต๋๋ค.
์ฌ์ฉ์ ์ง์ ํด๋์ ์ถ๊ฐ ๋ฆฌ์์ค๊ฐ์๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ์๋ํด ๋ณผ ์ ์์ต๋๋ค.
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()
}
๊ทธ๋ฌ๋ ์์ฒด ์์ฐ์ ํจํนํ๋ ์ข
์์ฑ์ด์๋ ๊ฒฝ์ฐ ์๋ํ์ง ์๊ณ ์ฌ์ ํ ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค (๋ช
ํ์ฑ์ ์ํด ํธ์ง ๋จ).
Execution failed for task ':app:mergeReleaseResources'.
> [drawable-xxxhdpi-v4/node_modules_reactnavigationstack_dist_views_assets_backicon]
/[...]/android/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigationstack_dist_views_assets_backicon.png
[drawable-xxxhdpi-v4/node_modules_reactnavigationstack_dist_views_assets_backicon]
/[...]/android/app/build/generated/res/react/release/drawable-xxxhdpi/node_modules_reactnavigationstack_dist_views_assets_backicon.png:
Error: Duplicate resources
์ด๊ฒ์ ์ ๊ทน์ ์ผ๋ก ํ๊ฐ๋๊ณ ์์ต๋๊น, ์๋๋ฉด ์์ฒด ํจ์น๋ฅผ ์งํํด์ผํฉ๋๊น?
@dragosroua xxxhdpi ์นด๋ ์ ๋๋ฝ ๋ ํ์ดํ์ด ์์ต๋๋ค. ์ฐ์ฐํ ๋ฌธ์ ๊ฐ์๋ ๋์ผํ ์ ๋ ๊ฒฝ๋ก์ ๋๊น?
๋น์ ์ ๋๋ฅผ 2 ๋ถ์ผ๋ก ์ด๊ฒผ๊ณ , ๋๋ ๊ทธ ๋ถ๋ถ์ ํธ์งํ๋ ค๊ณ ํ์ต๋๋ค. ์, ์ด์ ๋ชจ๋ ๊ฒ์ด ๋ฒ๋ค๋ก ์ ๊ณต๋์ง๋ง ์ฌ์ฉ์ ์ง์ ๋ฆฌ์์ค์ ๋ํ "์์"๊ฒฝ๋ก๊ฐ์๋ ๋นํธ๋ ๋๊ตฐ๊ฐ์๊ฒ ์ ์ฉ ํ ์ ์์ต๋๋ค.
@dragosroua ๋น์ ์ด ์ง๊ธ ์ปดํ์ผํ๊ณ
macOS 10.14.3 + RN 0.57.8 + Android Studio 3.3 + Gradle 4.10.3์ ์ฌ์ฉํ์ฌ ์ฌ์ ํ ์ด๊ฒ์๋ณด๊ณ ์์์ต๋๋ค. ๋ด๊ฐ ์ ์ผํ ์ฌ๋์ด ์๋๊น์? ์๋๋ฉด ์ฌ๊ธฐ ๋๊ตฐ๊ฐ๊ฐ ์๋ํ๋์ง ํ์ธํ ์ ์์ผ๋ฏ๋ก ๋ ๋ง์ด ํ๊ณ ์ค์ ๋ก ์์ ํ๊ฒ ์ต๋๋ค.
์ ๋ ํ์ฌ @mkchx (
.txt
์ ๋ฏธ์ฌ๊ฐ ์ถ๊ฐ๋์ด github์์ ์ฒจ๋ถ ํ์ผ์ ํ์ฉ ํจ) ์ ์ ์ฃผ์ ์ ๊ธฐ๋ฐ์ผ๋ก ์ฒจ๋ถ ๋ ํจ์น์ ํจ๊ป "patch-package"ํจํค์ง ๋ฅผ ์ฌ์ฉํ์ฌ ์๋์ผ๋ก ์์ ํ๊ณ ์์ต๋๋ค. ๋ด package.json ์คํฌ๋ฆฝํธ์postinstall: patch-package
์ ์ถ๊ฐ ํ ํ 'npm install'์์ ์์ ํ์ญ์์ค.๋๊ตฐ๊ฐ์๊ฒ ์ ์ฉ ํ ์๋ ์์ต๋๋ค ...
react-native + 0.57.8.patch.txt
Pls๋ ๋ด ๋ฐ์ ๋ค์ดํฐ๋ธ 0.57.5์์ ์๋ํ์ง ์๋ ์ด์ ๋ฅผ ์ค๋ช
ํฉ๋๋ค.
pacth ํ์ผ์ ๋ง๋ค์์ต๋๋ค. package.json์ ์ถ๊ฐ๋์์ต๋๋ค. npm install์ ์คํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ
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()
}
// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir jsBundleDir
outputs.dir resourcesDir
ํ์ํ ๋ณ๊ฒฝ์์ด.
@zakabluk ๋ npm ์ค์น์ ์ถ๋ ฅ์ ๊ฒ์ํด์ผํ์ง๋ง, ์ถ์ธก์ผ๋ก๋ ํจ์น ํจํค์ง ํจํค์ง๊ฐ ๋ฒ์ ๋ฒํธ์ ๋ํด ๋งค์ฐ ์ ์คํ๊ธฐ ๋๋ฌธ์ ๋๋ค. 57.5์์ ์๋ํ๊ณ ์์ง๋ง ํจ์น๋ 57.8์ ๋ํ ๊ฒ์ ๋๊น?
์ ๋ ๋ณดํต node_modules ํจ์น๋ฅผ์ํ ํ์ด์ฌ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ญ๋๋ค.
์ด๊ฒ์ postinstall.py
๋ก ์ถ๊ฐํ๊ณ ์ค์น ํ ์คํฌ๋ฆฝํธ์ ์ถ๊ฐํ๊ฑฐ๋ ./postinstall.py
#!/usr/bin/env python3
import os
import textwrap
def file_dir():
return os.path.dirname(os.path.realpath(__file__))
def read_file(filename):
'''
Reads the specified file.
:param filename: The file to read
:return: The content of the specified file
'''
if os.path.exists(filename):
with open(filename, "r") as file:
return file.read()
else:
raise IOError("file {} not found.".format(filename))
def write_file(filename, text):
'''
Writes the specified text to the specified file.
:param filename: The file to write to
:param text: The text to write
'''
with open(filename, "w") as file:
file.write(text)
def fix_android_assets():
print("Fixing android error with duplicate assets: https://github.com/facebook/react-native/issues/22234")
gradle_file_path = "{}/node_modules/react-native/react.gradle".format(file_dir())
code_snippet = textwrap.indent("""\
// Added by post_install
// Fix for: https://github.com/facebook/react-native/issues/22234
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()
}
""", "")
text = read_file(gradle_file_path)
start = text.find("doFirst", 0)
end = text.find("}", start)
end = text.find("\n", end) + 1
text = text[:end] + code_snippet + text[end:]
write_file(gradle_file_path, text)
def main():
fix_android_assets()
if __name__ == "__main__":
main()
ํ์ํ ๊ฒฝ์ฐ ์ฌ๊ธฐ์์ ์์ ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐ ํ ์ ์์ต๋๋ค.
npm install patch-package
์ป์ ๊ฒ์ ๋ค์ ๊ตฌํ ํ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ํ์ด์ฌ์ด ๋น์ ์ ๊ฒ์ด๊ณ ๋ ๋ง์ ์ฝ๋๋ฅผ ์ง์ ์ ์งํ๊ณ ์ถ๋ค๋ฉด ์คํ ๊ฐ๋ฅํด ๋ณด์
๋๋ค. ๋๋ ์ฌ์ ํ 0.59.3๊ณผ ๊ฐ์ด ๊ฐ์น์๋ ํจ์น ํจํค์ง๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
react-native + 0.59.3.patch.txt
@hramos- # 19239๋ ๋น์ทํ๊ณ (๋ด ์๊ฐ์) ์ด๊ฒ์ ์ค๋๋์์ง๋ง ์์ ๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค. ๊ถ๊ทน์ ์ธ ์์ ์ ์ํด PR์ด ํ์ํฉ๋๊น? ์๋๋ฉด ์ฌ๊ธฐ์ ์ฌ์ฉ ๋ ํจ์น๊ฐ ์คํ ๋ถ๊ฐ๋ฅํ ์ด์ ๋ฅผ ๋์น๊ณ ์์ต๋๊น? (์๋ง๋). PR ๋ง ํ์ํ๋ฉด ๋ณด๋ด๋๋ฆด ์ ์์ต๋๋ค ...
npm install patch-package
์ป์ ๊ฒ์ ๋ค์ ๊ตฌํ ํ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ํ์ด์ฌ์ด ๋น์ ์ ๊ฒ์ด๊ณ ๋ ๋ง์ ์ฝ๋๋ฅผ ์ง์ ์ ์งํ๊ณ ์ถ๋ค๋ฉด ์คํ ๊ฐ๋ฅํด ๋ณด์ ๋๋ค. ๋๋ ์ฌ์ ํ 0.59.3๊ณผ ๊ฐ์ด ๊ฐ์น์๋ ํจ์น ํจํค์ง๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
react-native + 0.59.3.patch.txt@hramos- # 19239๋ ๋น์ทํ๊ณ (๋ด ์๊ฐ์) ์ด๊ฒ์ ์ค๋๋์์ง๋ง ์์ ๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค. ๊ถ๊ทน์ ์ธ ์์ ์ ์ํด PR์ด ํ์ํฉ๋๊น? ์๋๋ฉด ์ฌ๊ธฐ์ ์ฌ์ฉ ๋ ํจ์น๊ฐ ์คํ ๋ถ๊ฐ๋ฅํ ์ด์ ๋ฅผ ๋์น๊ณ ์์ต๋๊น? (์๋ง๋). PR ๋ง ํ์ํ๋ฉด ๋ณด๋ด๋๋ฆด ์ ์์ต๋๋ค ...
์ด ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ, ๊ฐ์ฌํฉ๋๋ค
@ZhanRu - https: //github.com/ds300/patch-package#set -up- ํจ์น๋ฅผ ์ค์นํ๊ณ ์ค์ ํ ํ ํด๋น ํจ์น (.patch ํ์ฅ์ ํฌํจ)๋ฅผ ํ๋ก์ ํธ์ 'patches'๋๋ ํ ๋ฆฌ์ ๋ฃ์ผ๋ฉด๋ฉ๋๋ค. ๊พธ๋ฌ๋ฏธ
@ZhanRu - https: //github.com/ds300/patch-package#set -up- ํจ์น๋ฅผ ์ค์นํ๊ณ ์ค์ ํ ํ ํด๋น ํจ์น (.patch ํ์ฅ์ ํฌํจ)๋ฅผ ํ๋ก์ ํธ์ 'patches'๋๋ ํ ๋ฆฌ์ ๋ฃ์ผ๋ฉด๋ฉ๋๋ค. ๊พธ๋ฌ๋ฏธ
๊ฐ์ฌํฉ๋๋ค
๊ณ์ ๋ฐ๋ผ๊ฐ๋ ์ฌ๋์ ์ํด ์ต๊ทผ์ ์ธ๋ถ ์์คํ
์ ํตํฉํ๊ณ ํ
์คํธ๋ฅผ ํ๋ก๋์
์ธ๋ถ ๋ฐ์ดํฐ์ ๋ถ๋ฆฌํด์ผํ๊ธฐ ๋๋ฌธ์ gradle์์ "flavors"๋ฅผ ์ฌ์ฉํ์ฌ qaDebug, stagingRelease ๋ฑ์ด ๋ค๋ฅธ ์ธ๋ถ ์์คํ
์ ๊ฐ๋ฆฌ ํค๋๋ก ํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ฌ๊ธฐ์ ํจ์น๋ ๊ทธ๊ฒ์ ์ง์ํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ ํ๋ ์ด๋ฒ ์ง์์ ์ถ๊ฐํ๊ณ , ๋ด ํจ์น๋ ์ง๊ธ ์ด๋ ๊ฒ ๋ณด์
๋๋ค. patches/react-native+0.59.5.patch
๊ฑฐ์ฃผํ๋ฉฐ npm install patch-package
ํ npm i
์คํ ์ค์ ์ ์ฉ๋ฉ๋๋ค.
diff --git a/node_modules/react-native/react.gradle b/node_modules/react-native/react.gradle
index 4ead2b6..e0f92b7 100644
--- a/node_modules/react-native/react.gradle
+++ b/node_modules/react-native/react.gradle
@@ -48,6 +48,33 @@ afterEvaluate {
resourcesDir.mkdirs()
}
+ // From https://stackoverflow.com/questions/53239705/react-native-error-duplicate-resources-android
+ // Currently has no solution?
+
+ // IF you are using flavors, add flavor name to the path you move from
+ def flavorPathSegment = ""
+ android.productFlavors.all { flavor ->
+ if (targetName.toLowerCase().contains(flavor.name)) {
+ flavorPathSegment = flavor.name + "/"
+ }
+ }
+
+ doLast {
+ def moveFunc = { resSuffix ->
+ File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}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)
์ ๊ฒฝ์ฐ์๋ raw
๋๋ ํ ๋ฆฌ์์ ๋ฌธ์ ๊ฐ ์ง์๋ฉ๋๋ค.
๋ฒ์ : react-native 0.59.5
๋ด ์๋ฃจ์ :
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);
}
}
def moveRawFunc = { dir ->
File originalDir = file("$buildDir/generated/res/react/release/${dir}");
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/${dir}");
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()
moveRawFunc.curry("raw").call()
}
๋ฌธ์ ์ธ์ฌ
@Dbroqua ๊ทํ์ ์๋ฃจ์
์ด ์ ์๊ฒ react-native 0.59.5
). ๊ฐ์ฌํฉ๋๋ค.
๋งค์ฐ ํฅ๋ฏธ ๋กญ์ต๋๋ค. ์ ๋ raw์ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ์ต์ ๋ฒ์ ์ ํจ์น์ ํ๋ ์ด๋ฒ์ ๋ํ ์ง์์ด ์ถ๊ฐ๋์์ต๋๋ค. ํ๋ ์ด๋ฒ๋ฅผ ์์ํ๋ฉด ๋ ๊ธฐ๋ฅ ๋ชจ๋์์ ํ๋ ์ด๋ฒ ์ง์์ ์ํ ๊ฒ์ ๋๋ค. ์ด์ฉ๋ฉด ๊ทธ๊ฒ์ ๋งค๊ฐ ๋ณ์ํ ๋ ์์์ด์ 2 ๊ฐ์ ๊ธฐ๋ฅ์ด ๋ฐ๋ณต์ ์ด์ง๋ ์์ง๋ง ๊ทธ๊ฒ์ ๊ณ ๋ คํ ๋งํผ ๊ทธ๋ฃจ๋น๋ฅผ ์ํ์ง ๋ชปํฉ๋๋ค.
๋๋ ์ด๊ฒ์ด ํ์ด์ค ๋ถ๊ณผ ๋ฐ์ ๋ค์ดํฐ๋ธ CI์์ ๋ฌธ์ ๊ฐ๋์ง ์๋๋ค๊ณ ์์ํ ์ ์์ต๋๋ค. ์๋ํ๋ฉด ๊ทธ๋ค์ด BUCK๋ฅผ ์ฌ์ฉํ๊ณ ์๊ณ ๊ทธ๋ค์ CI๋ ๋งค๋ฒ ๊นจ๋ํ๊ฒ ๋น๋๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋๊ตฌ๋ ์ง ์ด๊ฒ์ ๊นจ๋ํ๊ฒ ์ฌํํ์ฌ ์ ์คํธ๋ฆผ์์ ์์ ํ ์ ์์ต๋๊น?
์ ๊ฒฝ์ฐ์๋ ์์ ๋๋ ํ ๋ฆฌ์ ๋ด ์์ฉ ํ๋ก๊ทธ๋จ์์ ์ฌ์ฉ๋๋ ์ผ๋ถ mp3๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
๊ทธ๋ฌ๋ฉด ๋น ๋ฅด๊ณ ์ฌ์ด ์ฌํ์ ๊ธฐ์ด๊ฐ ๋ ์ ์์ต๋๋ค. ๋๋ (์์ง) ๊ทธ๋ฐ ์ ์ ์ด ์์ง๋ง repo์ ๋ํ ๋ค์ดํฐ๋ธ ์ด๊ธฐํ์ ๋ฐ์ ํ ์์์๋งํผ ์ฝ์ต๋๋ค. ์ ์ ์ ๋ช ๊ฐ ๋ฃ์ ๋ค์ ๋ ๋ฒ์งธ ๋ฆด๋ฆฌ์ค ๋น๋ (์๋ง๋ ์ฒซ ๋ฒ์งธ ๋น๋์ผ๊น์?)์ ๋ํด ์๊ฐํฉ๋๋ค.
@Dbroqua ๋์ฃผ์ ํ ์ ์ ๋๋ค. ์ ํจ์น๋ ๋ณํฉ๋์์ง๋ง ์์ ๋๋ ํ ๋ฆฌ๊ฐ ๋งค์ฐ ๋ฐ์ ํ๊ฒ ๊ด๋ จ๋์ด ์์ง๋ง ์ ํจ์น์ ํฌํจ๋์ง ์์๋ค๋ ์ธ๊ธ๋ ๋ณํฉ์ ๋ฐ์๋์์ต๋๋ค. ๋ด ํจ์น๊ฐ ์ ์ฉ๋์์ผ๋ฏ๋ก ์์ ๋๋ ํ ๋ฆฌ์ ํ์ํ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ธํ๊ณ ์์ ์ฌํญ์ ๊ณ์ํ์ฌ PR์ ์ ์ํ์ฌ ์ฌ๋ก๋ฅผ ํ์ฅ ํ ์ ์์ต๋๊น?
ํ์ธ,
๋๋ ํ์ํ ์ต๋ํ ๋นจ๋ฆฌ ํ ๊ฒ์ ๋๋ค.
๋ฌธ์ ์ธ์ฌ,
๋ฐ๋ฏธ์
๊ฒฐ์ ๋!
์ ๊ฒฝ์ฐ์๋ ๋๋ก์ด ๋ธ res/drawable-*
๋๋ ํฐ๋ฆฌ์ ๋ด ํ ์ปค๋ฐ์ ๋ค๋ฅธ ๊ฐ๋ฐ์์์ ๋จ์์๋ ํ์ผ์ด์์์ต๋๋ค.-ํด๋น ํ์ผ ์ด๋ฆ์ ๊ฐ๋ฆฌํค๋ "์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค"๊ฐ ํ์๋์์ต๋๋ค. ๋๋ก์ด ๋ธ์์ ํ์ผ์ ์ญ์ ํ์ต๋๋ค. ๋ชจ๋ ๊ฒ์ด ์ ์๋ํฉ๋๋ค ๐
Mapsy์ ๋ต๋ณ์ https://stackoverflow.com/a/52750886์ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก /node_modules/react-native/react.gradle ํ์ผ์ ํธ์งํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋์ผ๋ก doFirst ๋ธ๋ก ํ doLast์ ๊ถ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค.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() }
๋๋ฅผ ์ํด ์ผํ์ง ์์ต๋๋ค.
@ Nextt1 ๋น์ ์ ๊ฐ๋ฅํ๋ค๋ฉด ๊ณต๊ฐ
๋ชจ๋ ์๋ - ํ๋ณด ๋๋์ด ํฉ๋ณ ํด๊ฒฐํ๊ธฐ ์ํด ์ ์ํ์ง๋ง ๋ถ๋ช ํ ํ๊ท์ ์์ธ - https://github.com/facebook/react-native/issues/25325 - ๋ด๊ฐ ์กฐ์ฌ ๋งํ๊ณ ์์ด ์ฌ๊ธฐ์ ์ง๊ธ ์ด๋ค Gradle์ ์ ๋ฌธ๊ฐ๊ฐ์๋ ๊ฒฝ์ฐ ํ๊ท๋ฅผ ์ผ์ผํค์ง ์๊ณ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ, ๋์์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค-๊ฐ์ฌํฉ๋๋ค!
์ข์์, ์ฌ๊ธฐ์ ๊ด๋ จ๋ PR์ "revert PR"์ ๊ฐ์ง ๊ฒ์ ๋๋ค-๊ทธ๊ฒ์ ํ๊ท๋ฅผ ์ผ์ผ ํต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๋ฌธ์ ๋ฅผ ์ผ์ผํจ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ ๋ ์ ๋ง๋ก ๋์ ๋ฌธ์์์ต๋๋ค.
์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ค์ ๋ก ๋น๋ํ๋ ๋์ src ๋๋ ํ ๋ฆฌ์ ํญ๋ชฉ์ ๋ณต์ฌํด์๋ ์๋ฉ๋๋ค. ๋ฌด์ธ๊ฐ๋ฅผ ์ค๊ฐ์ ๋ณต์ฌํ๊ณ ์์ฑํด์ผํฉ๋๋ค. ์ด๋ฏธ src์ ๋ณต์ฌ ํ ๊ฒฝ์ฐ (์ด ํจ์น๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋น๋์์ ๋๋ react-native bundle ๋ช ๋ น์์) : src / main / res๋ฅผ ์ ๊ฑฐํด์ผํฉ๋๋ค. ๋๋ ํ ๋ฆฌ๊ฐ ๊นจ๋ํฉ๋๋ค-ํ๋ก์ ํธ์ ์ค์ ์์ฐ ๋ง
์ด์ ์คํ๋ผ์ธ ๋ฒ๋ค๋ก APK๋ฅผ ๋น๋ํ๋ ค๋ฉด ๊ฐ๋ฐ์์์๋ API <17์์ ์คํํ ์ ์๋๋ก ์น์ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ๊ถ์ฅํ๋ ๊ฒ๊ณผ ๋ค๋ฅด๊ฒ ์์ ํด์ผํฉ๋๋ค (๋๋์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค).
์ํ๋ ๊ฒ์ android/app/build.gradle
.
project.ext.react = [
// This is what most people will need
bundleInDebug: project.hasProperty("bundleInDebug") ? project.getProperty("bundleInDebug") : false,
// If you use build variants it has to be like this - put your own names in there
bundleInDevDebug: project.hasProperty("bundleInDevDebug") ? project.getProperty("bundleInDevDebug") : false,
bundleInQaDebug: project.hasProperty("bundleInQaDebug") ? project.getProperty("bundleInQaDebug") : false,
bundleInStagingDebug: project.hasProperty("bundleInStagingDebug") ? project.getProperty("bundleInStagingDebug") : false,
bundleInProdDebug: project.hasProperty("bundleInProdDebug") ? project.getProperty("bundleInProdDebug") : false
]
๊ทธ๋ฐ ๋ค์ react-native
๋ค์๊ณผ ๊ฐ์ด ํธ์ถํฉ๋๋ค-ํ๊ฒฝ ๋ณ์๋ฅผ ํตํด gradle ํ๋ก์ ํธ ์์ฑ์ ๋ณด๋
๋๋ค.
ORG_GRADLE_PROJECT_bundleInDebug=true npx react-native run-android
(๋๋ ORG_GRADLE_PROJECT_bundleInDevDebug=true npx react-native run-android --variant devDebug
์ ๊ฐ์ ๋ณํ์ ๊ฒฝ์ฐ)
macOS 10.14.3 + RN 0.57.8 + Android Studio 3.3 + Gradle 4.10.3์ ์ฌ์ฉํ์ฌ ์ฌ์ ํ ์ด๊ฒ์๋ณด๊ณ ์์์ต๋๋ค. ๋ด๊ฐ ์ ์ผํ ์ฌ๋์ด ์๋๊น์? ์๋๋ฉด ์ฌ๊ธฐ ๋๊ตฐ๊ฐ๊ฐ ์๋ํ๋์ง ํ์ธํ ์ ์์ผ๋ฏ๋ก ๋ ๋ง์ด ํ๊ณ ์ค์ ๋ก ์์ ํ๊ฒ ์ต๋๋ค.
์ ๋ ํ์ฌ @mkchx (
.txt
์ ๋ฏธ์ฌ๊ฐ ์ถ๊ฐ๋์ด github์์ ์ฒจ๋ถ ํ์ผ์ ํ์ฉ ํจ) ์ ์ ์ฃผ์ ์ ๊ธฐ๋ฐ์ผ๋ก ์ฒจ๋ถ ๋ ํจ์น์ ํจ๊ป "patch-package"ํจํค์ง ๋ฅผ ์ฌ์ฉํ์ฌ ์๋์ผ๋ก ์์ ํ๊ณ ์์ต๋๋ค. ๋ด package.json ์คํฌ๋ฆฝํธ์postinstall: patch-package
์ ์ถ๊ฐ ํ ํ 'npm install'์์ ์์ ํ์ญ์์ค.๋๊ตฐ๊ฐ์๊ฒ ์ ์ฉ ํ ์๋ ์์ต๋๋ค ...
react-native + 0.57.8.patch.txt
๋๋ฐ! ์ง๊ธ์ ์ต๊ณ ์ ๋ต๋ณ์ ๋๋ค!
0.59.9์์ ์ฌ์ ํ ์ด๊ฒ์๋ณด๊ณ ์์ต๋๋ค. @mkchx ์ ๋๋ต์ ๋๋ฅผ ์ํด ๋ฌธ์ ๋ฅผ ๋ถ๋ฅํ์ต๋๋ค.
@juliancorrea @scgough ๊ทธ๋ฅ ์กฐ์ฌํ์ธ์. PR๋ ๋ฐ์ ๋ค์ฌ ์๋ฃจ์ ์คํ์ผ์ ๋๊น์ง ๋ฐ๋์ง๋ง ํ์ ๋ฌธ์ ํ์๋ ๋๋๋ฆด ํ์๊ฐ์์์ต๋๋ค. ๋ง ๋ค๋ฅธ ํด๊ฒฐ์ฑ ์ ๋๋ค. ์์ ๋ช ๊ฐ์ง ์๊ฒฌ์ ํ์ฌ ๊ถ์ฅ๋๋ ์๋ฃจ์ ์ ๋ํ ์์ธํ ๋ด์ฉ์ ๊ฒ์ํ์ผ๋ฉฐ ์๋ก์ด ์คํ์ผ ๋ง ์ถ์ฒ ํ ์ ์์ต๋๋ค. @mkchx ๋ต๋ณ์ ๊ธฐ๋ฐ์ผ๋ก ํ ์ด์ ์ฒจ๋ถ ํจ์น๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ์ฌ๋ก์๋ ์๋ํ์ง๋ง ํน์ ์กฐ๊ฑด์์๋ง ์๋ํฉ๋๋ค. ํ๋ก์ ํธ์ ํฅํ ํ์ํ ์์๋ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ์๋๋ฆฌ์ค์์๋ ์คํจํฉ๋๋ค.
@mikehardy OK- ์ด์ ํด๊ฒฐ์ฑ
์ ์ดํด ๋ณด๊ฒ ์ต๋๋ค.
๋ด๊ฐ ์ค์ ๋ก ์ํ๋ ๊ฒ์ Android Studio์ ์๋ช
๋ APK ๋น๋๊ฐ ๋ฒ๋ค์ ๊ฑด๋ ๋ฐ๋ ๊ฒ์
๋๋ค (ํฐ๋ฏธ๋์ ํตํด ์๋์ผ๋ก ์ํ).
์ ๊ณต ํ ์ค์ ์ ์ดํด๋ณด๊ณ ๋์์ด๋๋์ง ํ์ธํ๊ฒ ์ต๋๋ค.
์์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค ...
๋ฆด๋ฆฌ์ค APK ํ์ผ์ ๋ง๋ค ์์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋ชจ๋ ์์ฐ ํ์ผ์ ๋ํด ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
[drawable-mdpi-v4/filename] /Users/me/React/myapp/android/app/src/main/res/drawable-mdpi/filename.png
[drawable-mdpi-v4/filename] /Users/me/React/myapp/android/app/build/generated/res/react/release/drawable-mdpi/filename.png
: ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
drawable-mdpi
ํด๋์ ๋ ์ธ์คํด์ค๋ฅผ ๋ชจ๋ ์ญ์ ํ์ง๋ง APK ์์ฑ์ผ๋ก ์ธํด ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋ฒ๋ค์ ์์ฑํ๊ธฐ ์ํด ๋ค์์ ์๋์ผ๋ก ์คํํ๊ณ ์์ต๋๋ค.
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
๋ด ์ฑ gradle์๋ ๋ค์์ด ์์ต๋๋ค.
project.ext.react = [
entryFile: "index.android.js",
bundleInRelease: true //I've tried true and false here
]
apply from: "../../node_modules/react-native/react.gradle"
์ถ๊ฐ ์ ๋ณด์ ๋ง์ฐฌ๊ฐ์ง๋ก-๋ด ์ฑ์ด ๋๋ฒ๊ทธ์์ ์ ๋น๋๋ฉ๋๋ค ( react-native run-android
).
ํ์ฌ ๋ฆด๋ฆฌ์ค APK๋ฅผ ๋น๋ ํ ์์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ์์ doLast
๋๋๋ฆฌ๊ธฐ PR ์์ ์ ํตํด์์
๋๋ค.
์ ์ด๋ ๋ด ๋ฌธ์ ์ ๋ํ ์ด์ / ํด๊ฒฐ์ฑ ์ด์์ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ด ์ด์ ๋ฒ๋ค ๋ช
๋ น (RN 0.2.x๋ถํฐ ์ฌ์ฉ ํ์ต๋๊น?!)์ด ์์ฐ์ ๋์ ํด๋ android/app/src/main/res/
ํธ์ํ์ต๋๋ค.
์๋ ๋งํฌ์์> RN 57์๋ ์ค์ ๋ก ์์ฐ์ ๋ค์ ํด๋๋ก ํธ์ํด์ผํ๋ค๋ ๊ฒ์๋ฌผ์ด ์์ต๋๋ค.
android/app/build/intermediates/res/merged/release/
์ถ์ฒ : https://github.com/facebook/react-native/issues/19211#issuecomment -448301870
๋ค์์ ์ํํ์ต๋๋ค.
drawable-mdpi
์ ๋ณต์ฌํ๋ค ์์ฐ android/app/src/main/res/
์ต์ ์ ๋ณด
APK๊ฐ ์ค์น๋์์ง๋ง ๋ค์ ์์ธ์ ํจ๊ป ์ฑ์ด ์ถฉ๋ํฉ๋๋ค.
com.facebook.react.bridge.JSApplicationIllegalArgumentException: Error while updating property 'defaultSrc' of a view managed by: RCTImageView
... ์ด๋ฏธ์ง๋ฅผ ์ฐพ์ ์์๋ ๊ฒ ๊ฐ์ต๋๋ค ๐
์
๋ฐ์ดํธ 2
์ง๊ธ๊น์ง APK๊ฐ ์๋ํ๋๋ก ํ ์ ์์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ๋ค์์ ์ํํ๋ ๊ฒ์
๋๋ค.
android/app/src/main/res/
android/app/src/main/res/drawable-mdpi
์ android/app/src/main/res/drawable-hdpi
๋ฐ๊ฟ๋๋ค.๋ด ๋น๋ gradle์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
project.ext.react = [
entryFile: "index.android.js"
]
๊ทธ๋ฌ๋ฉด APK๊ฐ ๋น๋๋๊ณ ์คํ๋ฉ๋๋ค.
์ฐธ๊ณ :
์ด๋ฏธ์ง ์ฌ๋ผ์ด๋ ๊ตฌ์ฑ ์์์์ createBitmap
OutOfMemory ์์ธ๊ฐ ๋ฐ์ํ๋ ์๊ธฐ์น ์์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๋ค์์ ๋งค๋ํ์คํธ์ ์ถ๊ฐํ๊ณ ์ฑ์ด ๋ค์ ์คํ๋ฉ๋๋ค. android:largeHeap="true"
์ถ๊ฐ๊ฐ ๋์ / ๊ตฌ์ฑ ์์ ๋ฌธ์ ๋ฅผ ์ฐํํ๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ง๊ธ๊น์ง ์ฑ์ ๋ฌธ์ ์์ด ๋ค์ ์คํ๋ฉ๋๋ค.
React Native 0.60.0์์ ๋ค์ดํฐ๋ธ ๊ธฐ๋ฐ๋ ์ค๋ณต ๋ฆฌ์์ค๋ฅผ ์์ฑํ์ง๋ง ์์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์์ ํด๋๋ฅผ ๋์์ผ๋กํ๊ธฐ ๋๋ฌธ์ ์๋ํ์ง ์์ต๋๋ค.
[raw / node_modules_nativebase_dist_src_basic_icon_nbicons] C : Projectssome-appCLIENTandroidappsrcmainresrawnode_modules_nativebase_dist_src_basic_icon_nbicons.json
[raw / node_modules_nativebase_dist_src_basic_icon_nbicons] C : Projectssome-appCLIENTandroidappbuildgeneratedresreactreleaserawnode_modules_nativebase_dist_src_basic_icon_nbicons.json : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
์ด ๋ฌธ์ ๊ฐ์๋ ๋ค๋ฅธ ์ฌ์ฉ์์ ๊ฒฝ์ฐ :
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()
File originalDir = file("$buildDir/generated/res/react/release/raw");
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/raw");
ant.move(file: originalDir, tofile: destDir);
}
}
CI๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์ต๋๊น?
์ ๊ฒฝ์ฐ์๋
raw
๋๋ ํ ๋ฆฌ์์ ๋ฌธ์ ๊ฐ ์ง์๋ฉ๋๋ค.๋ฒ์ :
react-native 0.59.5
๋ด ์๋ฃจ์ :
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); } } def moveRawFunc = { dir -> File originalDir = file("$buildDir/generated/res/react/release/${dir}"); if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/${dir}"); 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() moveRawFunc.curry("raw").call() }
๋ฌธ์ ์ธ์ฌ
์๋ํฉ๋๋ค!
[drawable-mdpi-v4/node_modules_reactnativemaplink_src_images_uber] /Users/umair/my-app/android/app/src/main/res/drawable-mdpi/node_modules_reactnativemaplink_src_images_uber.png [drawable-mdpi-v4/node_modules_reactnativemaplink_src_images_uber] /Users/umair/my-app/android/app/build/generated/res/react/debug/drawable-mdpi/node_modules_reactnativemaplink_src_images_uber.png: Error: Duplicate resources
react-native run-android
์คํํ ๋์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง๋ง ๋ฆด๋ฆฌ์ค ๋น๋๋ฅผ ๋น๋ํ๊ณ ์คํํ ๋๋ ๋ฐ์ํ์ง ์์ต๋๋ค. ์์ ์๋ฃจ์
์ค ์ด๋ ๊ฒ๋ ๋๋ฅผ ์ํด ์๋ํ์ง ์์ต๋๋ค.
RN 0.60.5
์
๋ฐ์ดํธ : ๋๋ release
๋๋ ํ ๋ฆฌ ๋์ debug
์ ์ธ์ฉํ๊ธฐ ์ํด ์์ "ํจ์น"๋ฉ์๋๋ฅผ ์์ ํด์ผํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์๊ณ ๊ทธ๊ฒ์ ๊ณ ์ณค์ต๋๋ค. ์ ๋ raw
๋๋ ํ ๋ฆฌ๋ฅผ ์์ ํด์ผํ์ต๋๋ค.
๋๋ ๋ํ ๋์ผํ ๋ฌธ์ ๊ฐ ์์ผ๋ฉฐ react.gradle ํจ์น๋ก ํด๊ฒฐ๋์ง ์์ต๋๋ค. ์ ๊ฒฝ์ฐ ์ค๋ณต ๋ ๋ฆฌ์์ค๋ .OBJ ๋ฐ .MTL ํ์ผ์ด๋ฉฐ ์ด๋ฏธ์ง ๋ฆฌ์์ค์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
[raw / assets_res_salad_salad] /Users/sercanov/Projects/ARt/diner/DinerApp/android/app/src/main/res/raw/assets_res_salad_salad.mtl [raw / assets_res_salad_salad] / Users / sercanov / Projects / ARt / diner / DinerApp /android/app/src/main/res/raw/assets_res_salad_salad.obj : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
[raw / assets_res_steak_steak] /Users/sercanov/Projects/ARt/diner/DinerApp/android/app/src/main/res/raw/assets_res_steak_steak.mtl [raw / assets_res_steak_steak] / Users / sercanov / Projects / ARt / diner / DinerApp /android/app/src/main/res/raw/assets_res_steak_steak.obj : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
[raw / assets_res_salmon_salmon] /Users/sercanov/Projects/ARt/diner/DinerApp/android/app/src/main/res/raw/assets_res_salmon_salmon.mtl [raw / assets_res_salmon_salmon] / Users / sercanov / Projects / ARt / diner / DinerApp /android/app/src/main/res/raw/assets_res_salmon_salmon.obj : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
@sercanov ์ฌ์ ํ src์ ๋ํ ์ฌ๋ณธ์ ์ฌ์ฉํ๋ ค๊ณ ํฉ๋๊น? ์ด ์คํ์ผ์ ์กฐ์ฌ๋์๊ณ ์๋ ค์ง ์ด์ ๋ก ์คํจํ์ต๋๋ค. src์ ๋ฌผ๊ฑด์ ๋ฐฐ์นํ์ง ์๋ ์ง์๋๋ ๋น๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์๋๋ฉด non-src ๋ฐฉ์์ ์๋ํ์ง๋ง ์ฌ์ ํ ์คํจํ๊ณ ์์ต๋๊น? https://github.com/facebook/react-native/issues/22234#issuecomment -504721069
@mikehardy๋ ์ค์ ๋ก ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ ๋ชจ๋ ์๋ํ์ง๋ง ๋ ๋ค ๋ฆด๋ฆฌ์ค ๋น๋์์ ์๋ํ์ง ์์์ต๋๋ค. ๋๋ฒ๊ทธ ๋ชจ๋ btw์์ ์ ์์ ์ผ๋ก ์๋ํฉ๋๋ค.
not-copy-to-src ๋ฐฉ์์ ์ฌ์ฉํ ๋ ORG_GRADLE_PROJECT_bundleInArRelease=true npx react-native run-android --variant arRelease
๋๋ ์ด๊ฒ์ ์ป์ต๋๋ค;
': app : mergeArReleaseResources '์์ ์ ์คํํ์ง ๋ชปํ์ต๋๋ค.
[raw / assets_res_salad_salad] /Users/sercanov/Projects/ARt/diner/DinerApp/android/app/build/generated/res/react/ar/release/raw/assets_res_salad_salad.mtl [raw / assets_res_salad_salad] / Users / sercanov / Projects /ARt/diner/DinerApp/android/app/build/generated/res/react/ar/release/raw/assets_res_salad_salad.obj : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
[raw / assets_res_steak_steak] /Users/sercanov/Projects/ARt/diner/DinerApp/android/app/build/generated/res/react/ar/release/raw/assets_res_steak_steak.mtl [raw / assets_res_steak_steak] / Users / sercanov / Projects /ARt/diner/DinerApp/android/app/build/generated/res/react/ar/release/raw/assets_res_steak_steak.obj : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
[raw / assets_res_salmon_salmon] /Users/sercanov/Projects/ARt/diner/DinerApp/android/app/build/generated/res/react/ar/release/raw/assets_res_salmon_salmon.mtl [raw / assets_res_salmon_salmon] / Users / sercanov / Projects /ARt/diner/DinerApp/android/app/build/generated/res/react/ar/release/raw/assets_res_salmon_salmon.obj : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
์ฌ์ฉ์ src๋ก ๋ณต์ฌ doLast ๋ฐฉ๋ฒ; ์ฑ๊ณตํ๊ธฐ ์ํด ๋น๋ ํ ๋๋ง๋ค android / build ํด๋๋ฅผ ์ง์์ผํ์ง๋ง ์ด๋ป๊ฒ ๋ ์ฑ์์ ์์ฐ์ ์ฌ์ฉํ ์ ์์์ต๋๋ค. ์ด๊ฒ์ ํ์ฌ ์กฐ์ฌ์ค์ธ ๋ด ์ฝ๋์ ๊ด๋ จ์ด์์ ์ ์์ต๋๋ค.
not-copy-to-src ๋ฐฉ์์ผ๋ก ์ ํ ํ ๋ ๋จผ์ ๋ชจ๋ ๊ฒ์ ์ ๋ฆฌํ์ฌ ์ ํํด์ผํฉ๋๋ค. ๋ด ํ๋ก์ ํธ์๋ ์ด์ ์ copy-to-src ์คํ์ผ์ ๋ฒ๋ค๋ง ๊ด์ ์์ ๋ง์ "์ฐ๋ ๊ธฐ"๊ฐ ์์๋๋ฐ, ์์ ์ ์ ์ ๋ฆฌํด์ผํ์ง๋ง ๋งค๋ฒ ์๋ํ์ต๋๋ค.
@ rahulkumar1409 ์ด๊ฒ์์ด ์ค๋ฅ์์ ๋๋ฅผ ๋์์ง๋ง ๋ค๋ฅธ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์์ : react-native-simple-download- manager : verifyReleaseResources FAILED
์ ์ด๋ฐ ์ผ์ด ๋ฐ์ํ๋์ง ์์ญ๋๊น?
์ด ์๋ฃจ์
์ ์ ์๊ฒ ํจ๊ณผ์ ์ด์์ต๋๋ค.
๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก /node_modules/react-native/react.gradle ํ์ผ์ ํธ์งํฉ๋๋ค.
doFirst ๋ธ๋ก ๋ฐ๋ก ๋ค์ doLast๋ฅผ ์๋์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
doFirst {...}
doLast {
def moveFunc = {resSuffix->
ํ์ผ originalDir = file ( "$ buildDir / generated / res / react / release / drawable-$ {resSuffix}");
if (originalDir.exists ()) {
ํ์ผ destDir = file ( "$ buildDir /../ src / main / res / drawable-$ {resSuffix}");
ant.move (ํ์ผ : 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.60.5์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ @mikehardy๊ฐ ์ธ๊ธ ํ ๊ฒ๊ณผ ๊ฐ์ ์ ํ ๋ง์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ @Dbroqua๊ฐ ๊ฒฝํ ํ ๊ฒ์ฒ๋ผ 'raw'ํด๋์ ๋ฌธ์ ๊ฐ์์์ต๋๋ค.
๊ฒฐ๊ตญ ๋ ์๋ฃจ์ ์ ํผํฉํ๊ณ ๋ค์ ์ฝ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
doLast {
def moveFunc = { resSuffix ->
File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}")
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}")
ant.move(file: originalDir, tofile: destDir)
}
}
def moveRawFunc = { dir ->
File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}")
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/${dir}")
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()
moveRawFunc.curry("raw").call()
}
์ด ์ค๋ ๋๋ ๊ธฐ์ฌํด ์ฃผ์ ๋ชจ๋ ๋ถ๋ค๊ป ์ ๋ง ๋์์ด๋์์ต๋๋ค. ๐
๋ฆด๋ฆฌ์ค ๋น๋์์๋ง ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. react-native 60.5๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
/release/drawable-xhdpi/node_modules_reactnavigationstack_lib_module_views_assets_backicon.png : ์ค๋ฅ : ์ค๋ณต ๋ฆฌ์์ค
bundleInDebug๋ฅผ true ๋ฐ false๋ก ์ค์ ํ์ง๋ง ์๋ฌด๋ฐ ์ํฅ์ ๋ฏธ์น์ง ์์์ต๋๋ค.
์ฑ ์ผํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ถ ์ค์ด๋ฉฐ src / main / assets / appcenter-config.json ํ์ผ์ด ํ์ํฉ๋๋ค. ์ฌ์ฉ์ ์ง์ ๊ธ๊ผด์ ์ฌ์ฉํ๋ฉด์ src / main / assets / fonts ๋๋ ํ ๋ฆฌ๋ ์์ต๋๋ค. ์ด๊ฒ์ด ๋ฌธ์ ์ ์์ธ ์ผ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๊น?
@ARichIVC ๋ฌธ์ ๋ ์ค๋ฅ ๋ฉ์์ง์ ์ฐธ์กฐ ๋ ํ์ผ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ด ์๋ ์๋ฃจ์ ์ ํ์ค "๋ด src / ๋๋ ํ ๋ฆฌ๊ฐ ์ด์ ๋ณต์ฌ ์คํ์ผ์ ๋ฒ๋ค ํจํค์ง ์๋๋ก ์ธํด ์ค์ผ๋์์ต๋๋ค"๋ฌธ์ ๊ฐ ๋ง ๋ค๋ฅธ ์๋ฃจ์ ์ด๋ผ๋ ๊ฒ์ ๋ชจ๋ ์ธ์ํ๊ธฐ ์ ์ ๋ณต์ฌ ๋ ๊ฒ์์ src /๋ฅผ ์ง์์ผํฉ๋๋ค. bundleInDebug ์์ ์ ์ํํ๋ ํ์ ์๋ฃจ์ ์ ์๋ํ๊ธฐ ์ ์ ์ผ. ์ํ๊น๊ฒ๋ ๋ค๋ฃจ๊ธฐ ์ด๋ ต๊ณ ๊ธด ๋ชจ๋ ๊ฒ์ด์ด ์ค๋ ๋์ ์์ง๋ง ์ ๋ณด๋ ๊ฑฐ๊ธฐ์ ์์ต๋๋ค.
๋์์ ์ฃผ์ @mikehardy ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์์ฐ ๋๋ ํ ๋ฆฌ์ ๊ธ๊ผด ๋ฑ์ ๊ทธ๋๋ก ๋๋ ๊ฒ์ด ์ข์ง๋ง ์ฃผ์์ ๋งค๋ฌ๋ ค์๋ ๋ค๋ฅธ ๋นํธ์ ์กฐ๊ฐ์ ์ญ์ ํด์ผํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค. ์ฆ androidappsrcmainresdrawable-hdpi์ ๋ชจ๋ ๊ฒ
๊ธ๊ผด์ ๊ฒฝ์ฐ์๋ ์ฌ๋ฐ๋ฅธ ๋๋ ํ ๋ฆฌ์ ์์ด์ผํฉ๋๋ค. ์ : https://github.com/oblador/react-native-vector-icons#android ์ด ํ์ผ์ ํธ์ถํ์ฌ ๋น src๋ก ์ ์คํ๊ฒ ๋ณต์ฌํ๋๋ก ์ง์ํฉ๋๋ค. ๋๋ ํ ๋ฆฌ https://github.com/oblador/react-native-vector-icons/blob/master/fonts.gradle#L16- ๋ชจ๋ ์ฌ๋์ ํ๋ก์ ํธ๋ ๋ฌผ๋ก ๋ค๋ฅด์ง๋ง ์ธ๊ธ ํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ฐ์ ๋ค์ดํฐ๋ธ 0.60.5์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ @mikehardy๊ฐ ์ธ๊ธ ํ ๊ฒ๊ณผ ๊ฐ์ ์ ํ ๋ง์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ @Dbroqua๊ฐ ๊ฒฝํ ํ ๊ฒ์ฒ๋ผ 'raw'ํด๋์ ๋ฌธ์ ๊ฐ์์์ต๋๋ค.
๊ฒฐ๊ตญ ๋ ์๋ฃจ์ ์ ํผํฉํ๊ณ ๋ค์ ์ฝ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
doLast { def moveFunc = { resSuffix -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}") ant.move(file: originalDir, tofile: destDir) } } def moveRawFunc = { dir -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/${dir}") 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() moveRawFunc.curry("raw").call() }
์ด ์ค๋ ๋๋ ๊ธฐ์ฌํด ์ฃผ์ ๋ชจ๋ ๋ถ๋ค๊ป ์ ๋ง ๋์์ด๋์์ต๋๋ค. ๐
ํจ๊ณผ๊ฐ์๋ค! ๋ง์ ๊ฐ์ฌํฉ๋๋ค! ๐
react native 0.59.1 ์ด์์ ๊ฒฝ์ฐ node_modules / react-native์ react.gradle์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ผํฉ๋๋ค.
def flavorPathSegment = ""
android.productFlavors.all { flavor ->
if (targetName.toLowerCase().contains(flavor.name)) {
flavorPathSegment = flavor.name
}
}
doLast {
def moveFunc = { resSuffix ->
File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}/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()
}
@ dayachand-systematix์ด ๋์ ์กฐ์ธ. ๊ทธ ์คํ์ผ ์๋ฃจ์ ์ PR์ด ์๊ณ ์ฌ์ง์ด ๋ณํฉ๋๋ ์ง์ ๊น์ง ์ถ๊ตฌ๋์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์๋ชป๋ ๋ฐฉํฅ์์ ๋ฐ๊ฒฌํ๊ณ PR์ ๋๋ ๋ ธ์ต๋๋ค. ์ฌ๋๋ค์๊ฒ PR ๋ณํฉ์ ์ค์ ๋ก ๋ ๋๋ฆฐ ์๋ฃจ์ ์ ์ฌ์ฉํ๋๋ก ์กฐ์ธ ํ์๊ฒ ์ต๋๊น? ๋ด๊ฐ ์์ ๊ฒ. https://github.com/facebook/react-native/issues/22234#issuecomment -504721069
@mikehardy ์, ์ด๊ฒ์ด ์๊ตฌ์ ์ธ ํด๊ฒฐ์ฑ ์ ์๋์ง๋ง ์ ์๋ res ๋๋ ํ ๋ฆฌ์ ์คํ๋์ ํ๋ฉด ๋ฐ DB์ ๊ฐ์ ๋ค๋ฅธ ํ์ผ์ด ์๊ธฐ ๋๋ฌธ์ ์๋ฃจ์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ @ dayachand-systematix ์ ๋ :
mike<strong i="6">@isabela</strong>:~/work/Kullki/ksocialscore/packages/public-app/android/app (lerna-import) % find . -type f |grep res
./src/main/res/drawable-xhdpi/minilogo_bw.png
./src/main/res/mipmap-xxhdpi/ic_launcher.png
./src/main/res/values-v21/styles.xml
./src/main/res/drawable-xxhdpi/minilogo_bw.png
./src/main/res/drawable-xxhdpi/kscore_splash.png
./src/main/res/drawable-hdpi/minilogo_bw.png
./src/main/res/mipmap-xxxhdpi/ic_launcher.png
./src/main/res/mipmap-hdpi/ic_launcher.png
./src/main/res/layout/launch_screen.xml
./src/main/res/drawable/background_launch.xml
./src/main/res/values/colors.xml
./src/main/res/values/styles.xml
./src/main/res/values/strings.xml
./src/main/res/mipmap-xhdpi/ic_launcher.png
./src/main/res/xml/filepaths.xml
./src/main/res/xml/react_native_config.xml
./src/main/res/drawable-mdpi/minilogo_bw.png
./src/main/res/drawable-xxxhdpi/minilogo_bw.png
./src/main/res/mipmap-mdpi/ic_launcher.png
./src/qa/res/mipmap-xxhdpi/ic_launcher.png
./src/qa/res/mipmap-xxxhdpi/ic_launcher.png
./src/qa/res/mipmap-hdpi/ic_launcher.png
./src/qa/res/values/strings.xml
./src/qa/res/mipmap-xhdpi/ic_launcher.png
./src/qa/res/mipmap-mdpi/ic_launcher.png
./src/debug/res/xml/react_native_config.xml
./src/staging/res/mipmap-xxhdpi/ic_launcher.png
./src/staging/res/mipmap-xxxhdpi/ic_launcher.png
./src/staging/res/mipmap-hdpi/ic_launcher.png
./src/staging/res/values/strings.xml
./src/staging/res/mipmap-xhdpi/ic_launcher.png
./src/staging/res/mipmap-mdpi/ic_launcher.png
./src/dev/res/mipmap-xxhdpi/ic_launcher.png
./src/dev/res/mipmap-xxxhdpi/ic_launcher.png
./src/dev/res/mipmap-hdpi/ic_launcher.png
./src/dev/res/values/strings.xml
./src/dev/res/mipmap-xhdpi/ic_launcher.png
./src/dev/res/mipmap-mdpi/ic_launcher.png
๊ทธ๋ฆฌ๊ณ ์ฌ์ ํ ์ ์ ๋ / ๋น PR ๋ ๋๋ฆฐ ์๋ฃจ์ ์ด ๋๋ฅผ ์ํด ์๋ํฉ๋๋ค. : man_shrugging :
Heya, --asset-dest
๋งค๊ฐ ๋ณ์๋ฅผ ์ ๊ฑฐํ์ฌ ์์ ํ์ต๋๋ค.
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle
@ hery-finimize hi- --asset-dest
๋งค๊ฐ ๋ณ์๋ฅผ ์ ๊ฑฐํ์ง ์์ผ๋ฉด ์ต์ ์์ฐ์ด ์ฌ๋ฐ๋ฅธ ์์น์ ๋ฒ๋ค๋ก ์ ๊ณต๋์ง ์์ผ๋ฏ๋ก APK๋ฅผ ๋ง๋ค ๋ ๋๋ฝ๋๊ฑฐ๋ ๋๋ฝ ๋ ์ํ์ด ์์ต๋๋ค. ์ฑ์ ๋ ์ง ์์ฐ ํ์ผ?
@scgough ๋๋ ๊ทธ๋ด ์๋ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด Android Studio๋ก ๋น๋ํ๊ธฐ ์ ์ ํ์ํ ๋ก์ปฌ ์์ฐ์ ์ ์ธํ ๋ชจ๋ ์ค๋ณต ์์ฐ์ ์ ํ์ ์ผ๋ก ์ ๊ฑฐ ํ ์ ์์ต๋๋ค.
find android/app/src/main/res/drawable-* \( -name launch_screen.png -o -name ic_stat_onesignal_default.png -prune \) -o -type f -exec rm {} +
์ด์์ ์ด์ง๋ ์์ง๋ง ๋ฌธ์ ๊ฐ ํด๊ฒฐ ๋ ๋๊น์ง ์๋ํฉ๋๋ค.
์ด ๋ฌธ์ ๋ ์์ฐ ํด๋์ ๊ฐ์ ์ด๋ฆ๊ณผ ๋ค๋ฅธ ํ์ฅ์ ํ์ผ์ด์๋ ๊ฒฝ์ฐ ๋ฐ์ํ์ต๋๋ค.
back.png
back.jpg
์๋๋ก์ด๋์์๋ ๋ ๋ค ๊ทธ๋ ๊ฒ ๋ถ๋ฅด๊ธฐ ๋๋ฌธ์ ๋๋ค.
R.drawable.back
R.drawable.back
ํ์ผ ์ค ํ๋๋ฅผ ์ ๊ฑฐํ๊ฑฐ๋ ์ด๋ฆ์ ๋ฐ๊ฟ๋๋ค.
์๋
ํ์ธ์,
react.gradle ์์ ์ ์๋ํ์ต๋๋ค. ๋น๋๊ฐ ํ ๋จ๊ณ ๋ ์งํ๋ฉ๋๋ค (app.aab๋ ๋น๋์ด์ง๋ง APK๋ฅผ ๋น๋ ํ ์ ์์ต๋๋ค.
Android Studio๋ก APK๋ฅผ ๋น๋ํ๋ ค๊ณ ํ์ง๋ง ๋ฌธ์ ๊ฐ ์์์ต๋๋ค (react.gradle ํจ์น ํฌํจ).
๋ ๊ฒฝ์ฐ ๋ชจ๋ APK๋ฅผ ๋น๋ํ๋ ํ๋ก์ธ์ค๊ฐ ๋์ผํด์ผํ๊ธฐ ๋๋ฌธ์ ๋์๊ฒ๋ ๋งค์ฐ ์ด์ํฉ๋๋ค. ๋ด๊ฐ ์๋ชป ?
์ด ์ฃผ์์ 0.59.10์์ ์๋ํ์ต๋๋ค. ์ด ์์ ๊ณผ ํผํฉ.
๊ฐ์ฌํฉ๋๋ค, @ dayachand-systematix!
๋๋ฅผ ์ํด ์ผํ ๊ฒ์ ๋ ๊ฐ์ง ์๊ฒฌ์ ์กฐํฉ์ด์์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋์ด ํ์ํ ์ ์๋๋ก ์ฌ๊ธฐ์ ๋ถ์ฌ ๋ฃ์ต๋๋ค.
```
def flavorPathSegment = ""
android.productFlavors.all {๋ง->
if (targetName.toLowerCase (). contains (flavor.name)) {
flavorPathSegment = flavor.name
}
}
doLast {
def moveFunc = { resSuffix ->
File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}")
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}")
ant.move(file: originalDir, tofile: destDir)
}
}
def moveRawFunc = { dir ->
File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}")
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/${dir}")
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()
moveRawFunc.curry("raw").call()
}
@AbhishekNairOfficial ๋น์ ์ ์ด๊ฒ์ ์ด๋์ ๋ฃ์ต๋๊น?
@AbhishekNairOfficial ๋น์ ์ ์ด๊ฒ์ ์ด๋์ ๋ฃ์ต๋๊น?
node_modules / react-native / react.gradle.
์ด๊ฒ์ doFirst () ๋ธ๋ก ๋ค์ ๋ฃ์ผ์ญ์์ค.
@AbhishekNairOfficial ๋น์ ์ ์ด๊ฒ์ ์ด๋์ ๋ฃ์ต๋๊น?
node_modules / react-native / react.gradle.
์ด๊ฒ์ doFirst () ๋ธ๋ก ๋ค์ ๋ฃ์ผ์ญ์์ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด ๋ณ๊ฒฝ ์ฌํญ์ ๋ค์ npm install
์ ์ฌ์ ์๋๊ธฐ ๋๋ฌธ์
๋๋ค. ์ฌ์ง์ด CI๊ฐ ์๋ํ์ง ์์ต๋๋ค.
๋๊ตฐ๊ฐ ์๋ ๋ช ๋ น์ ์๋ ํ์ต๋๊น?
cd android
./gradlew clean
cd ..
๊ทธ๊ฒ์ ๋๋ฅผ ์ํด ์ผํ์ต๋๋ค
๋๋ฅผ ์ํด ์ผํ ๊ฒ์ ๋ ๊ฐ์ง ์๊ฒฌ์ ์กฐํฉ์ด์์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋์ด ํ์ํ ์ ์๋๋ก ์ฌ๊ธฐ์ ๋ถ์ฌ ๋ฃ์ต๋๋ค.
def flavorPathSegment = "" android.productFlavors.all { flavor -> if (targetName.toLowerCase().contains(flavor.name)) { flavorPathSegment = flavor.name } } doLast { def moveFunc = { resSuffix -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}") ant.move(file: originalDir, tofile: destDir) } } def moveRawFunc = { dir -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/${dir}") 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() moveRawFunc.curry("raw").call() }
์ค ๋ ๋ด ํ๋ฃจ๋ฅผ ๊ตฌํด ์คฌ์ด <3
๋๋ฅผ ์ํด ์ผํ ๊ฒ์ ๋ ๊ฐ์ง ์๊ฒฌ์ ์กฐํฉ์ด์์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋์ด ํ์ํ ์ ์๋๋ก ์ฌ๊ธฐ์ ๋ถ์ฌ ๋ฃ์ต๋๋ค.def flavorPathSegment = "" android.productFlavors.all { flavor -> if (targetName.toLowerCase().contains(flavor.name)) { flavorPathSegment = flavor.name } } doLast { def moveFunc = { resSuffix -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}") ant.move(file: originalDir, tofile: destDir) } } def moveRawFunc = { dir -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/${dir}") 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() moveRawFunc.curry("raw").call() }
์ค ๋ ๋ด ํ๋ฃจ๋ฅผ ๊ตฌํด ์คฌ์ด <3
ํํ ๊ฐ์ฌํฉ๋๋ค. ๋๋ ๊ฑฐ์ ๋งค์ผ์ด ์ค๋ ๋์ ๊ณ์ ์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ๋ ์ถ์ ๋ ์ฝ๊ฒ ๋ง๋ค๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
android/app/build
ํด๋๋ฅผ ์ ๊ฑฐํ๊ณ ๋ค์ ๋น๋ํ๋ ๊ฒ์ด ์ ์๊ฒ ํจ๊ณผ์ ์ด์์ต๋๋ค.
๋ด ์๋ฃจ์
:
/ your_project / android / app / src / main / raw / res์ ๋ชจ๋ ํ์ผ ์ ์ญ์
๊ทธ๊ฒ์ ๋๋ฅผ์ํ ์ผ์
๋๋ค!
๋๋ฅผ ์ํด ์ผํ ๊ฒ์ ๋ ๊ฐ์ง ์๊ฒฌ์ ์กฐํฉ์ด์์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋์ด ํ์ํ ์ ์๋๋ก ์ฌ๊ธฐ์ ๋ถ์ฌ ๋ฃ์ต๋๋ค.
def flavorPathSegment = "" android.productFlavors.all { flavor -> if (targetName.toLowerCase().contains(flavor.name)) { flavorPathSegment = flavor.name } } doLast { def moveFunc = { resSuffix -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}") ant.move(file: originalDir, tofile: destDir) } } def moveRawFunc = { dir -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/${dir}") 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() moveRawFunc.curry("raw").call() }
๊ฐ์ฌํฉ๋๋ค @AbhishekNairOfficial. ๊ทธ๊ฒ์ ๋๋ฅผ ์ํด ๋ง์ ์๊ฐ์ ์ ์ฝํ์ต๋๋ค.
rm -rf ./android/app/src/main/res/drawable-*
rm -rf ./android/app/src/main/res/raw
๋ฐ๋ผ์ ์ด๊ฒ์ ์๋ํ์ง๋ง ์ด๋ฏธ์ง๊ฐ ๋๋ฝ๋์์ผ๋ฏ๋ก ์ฑ์ ๋ค์ ๋ฒ๋ค๋ก ๋ง๋ค๋ฉด ๋์ผํ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์๋ฌด๋ ์ด๊ฒ์ ๋ํ ํฉ๋ฒ์ ์ธ ์์ ์ด ์์ต๋๊น?
v0.61.5์ @ wincod75 ๊ฐ ๋งํ๋ฏ์ด ๋ชจ๋ ์ด๋ฏธ์ง๊ฐ ์ ๊ฑฐ๋๋ฏ๋ก raw ๋ฐ drawable ํด๋๋ฅผ ์ญ์ ํ๋ ๊ฒ์ ์ค์ ๋ก ํด๊ฒฐ์ฑ ์ด ์๋๋๋ค.
๋ฆด๋ฆฌ์ค ๋น๋๋ฅผ ์ํด ๋ค์ ์์ฑ๋์์ง๋ง react-native run-android --variant = release๋ฅผ ์คํํ ๋๋ ์๋ํ๋ฉด ์ข์ ๊ฒ์ ๋๋ค. .
๋๊ตฌ๋ ์ง v0.61.5์์ ํด๊ฒฐํ ์ ์์์ต๋๊น?
@ gudbrand3 ๊ฒฐ๊ตญ ์์์ ์ธ๊ธ ํ ์์ ์ฌํญ์ "node_modules / react-native / react.gradle"ํ์ผ์ ๊ตฌํํ์ฌ ์ฑ ์คํ ์ด์ ์ ๋น๋๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์์ง๋ง์ด ์์ ์ ํฐ๋ฌด๋ ์์ต๋๋ค. ์์ง ์์ ๋์ง ์์์ต๋๋ค ...
@ wincod75 ๋ฃ๊ณ ๋ค์ด! ๋๋ ๋๊ฐ์ด .. ์ด์ฉ๊ตฌ. ์ฌ๋๋ค์ด ์ด์จ๋ ์๋์ผ๋ก ๋๋ด๊ธฐ ๋๋ฌธ์ ๋ ๋์ ์ ๊ทผ ๋ฐฉ์์ ์ฐพ์ ๋๊น์ง ํจํค์ง์ ํฌํจ๋์ง ์์ ์ด์ ๋ฅผ ์ ์ ์์ต๋๋ค. ์ด์ node_modules ๋ฐ re npm ์ค์น๋ฅผ ์ญ์ ํ ๋๋ง๋ค ๋ค์ ์ํํด์ผํฉ๋๋ค. # ์ ๋ง
์ ์งํด์ผํ๋ ๋๋ก์ด ๋ธ ๋ฆฌ์์ค๊ฐ ์์๊ธฐ ๋๋ฌธ์ ๋๋ก์ด ๋ธ ํด๋๋ฅผ ์ ๊ฑฐํ๋ฉด ์๋ํ์ง ์์ต๋๋ค. ๋ด ๋ฌธ์ ๋ android/app/src/main/res/raw
ํด๋์ ๋ชจ๋ ํญ๋ชฉ๊ณผ android/app/src/main/res/drawable
ํด๋์ nodemodules...
๋ก ์์ํ๋ ํ์ผ์ ๋ํ duplicate resources
๋ฌธ์ ์์ต๋๋ค. ์ด๊ฒ์ ๋๋ฅผ ์ํด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
android/app/build.gradle
:
...
project.ext.react = [
...
bundleInRelease : true,
resourcesDirRelease : "src/release/res",
...
]
...
node
์์ android/app/src/main/drawable*
node
๋ก ์์ํ๋ ๋ชจ๋ ํญ๋ชฉ ์ ๊ฑฐ :
rm android/app/src/main/drawable*/node*
rm -rf android/app/src/main/raw
ํ๋ก์ ํธ๋ฅผ ์ ๋ฆฌํ๊ณ ๋ฐ์ ํ ๊ธฐ๋ณธ ๋ฒ๋ค ๋ช ๋ น์ ์คํํ์ง ๋ง๊ณ ๋ค์ ๋น๋ํ์ญ์์ค.
์ด๊ฒ์ด ๋๊ตฐ๊ฐ๋ฅผ ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
์ค ์๋ . ๊ณต์์ ์ธ ์์ ์ด ์งํ ์ค์ผ๊น์?
v.0.61.4์์ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋์ ๊ฒฝ์ฐ์๋
์ฒซ์งธ : 'doFirst'๋ค์ 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()
}
๋ ๋ฒ์งธ : android / app / src / main / res / raw ํด๋์ ๋ชจ๋ ๋ด์ฉ์ ์ญ์ ํ์ต๋๋ค.
๋๊ตฐ๊ฐ์๊ฒ ์ ์ฉ ํ ์ ์์ต๋๋ค
์ค ์๋ . ๊ณต์์ ์ธ ์์ ์ด ์งํ ์ค์ผ๊น์?
๋๋ RN 0.62.1์ ์ฌ์ฉ ํ๊ณ
doLast ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ๋๋ก์ด ๋ธ ํด๋ ๋ฅผ
๊ณต์ ์ถ์ฒ์ด ๋ฌด์์ธ์ง ๊ถ๊ธํฉ๋๋ค.
๊ฐ์ฌํฉ๋๋ค
์ ์งํด์ผํ๋ ๋๋ก์ด ๋ธ ๋ฆฌ์์ค๊ฐ ์์๊ธฐ ๋๋ฌธ์ ๋๋ก์ด ๋ธ ํด๋๋ฅผ ์ ๊ฑฐํ๋ฉด ์๋ํ์ง ์์ต๋๋ค. ๋ด ๋ฌธ์ ๋
android/app/src/main/res/raw
ํด๋์ ๋ชจ๋ ํญ๋ชฉ๊ณผandroid/app/src/main/res/drawable
ํด๋์nodemodules...
๋ก ์์ํ๋ ํ์ผ์ ๋ํduplicate resources
๋ฌธ์ ์์ต๋๋ค. ์ด๊ฒ์ ๋๋ฅผ ์ํด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
android/app/build.gradle
:... project.ext.react = [ ... bundleInRelease : true, resourcesDirRelease : "src/release/res", ... ] ...
node
์์android/app/src/main/drawable*
node
๋ก ์์ํ๋ ๋ชจ๋ ํญ๋ชฉ ์ ๊ฑฐ :rm android/app/src/main/drawable*/node* rm -rf android/app/src/main/raw
ํ๋ก์ ํธ๋ฅผ ์ ๋ฆฌํ๊ณ ๋ฐ์ ํ ๊ธฐ๋ณธ ๋ฒ๋ค ๋ช ๋ น์ ์คํํ์ง ๋ง๊ณ ๋ค์ ๋น๋ํ์ญ์์ค.
์ด๊ฒ์ด ๋๊ตฐ๊ฐ๋ฅผ ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
์์ ์๋ฃจ์ ์ ์ ์ ํ ๋๋ต์ ์ฐพ๋ ๋ฐ ๋์์ด๋์์ต๋๋ค.
android/app/build.gradle
:
...
project.ext.react = [
...
bundleInRelease : true,
resourcesDirRelease : "src/release/res",
...
]
...
๋ค์ ๋ช ๋ น์ ์คํํ์ฌ ๋ชจ๋ node_module ํ์ผ์ ์ญ์ ํฉ๋๋ค.
rm -rf drawable*/node*
์ด ๋ช ๋ น์ด๋ฅผ ์คํํ์ฌ ๋น๋ํ๊ณ APK๋ฅผ ๋ง๋์ธ์.
./gradlew assembleRelease
๋ด package.json์์ ์ฌ์ฉํ ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์์ต๋๋ค.
"release-apk": "cd android && yarn remove-duplicate-files && ./gradlew assembleRelease"
๋์์ด ๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
๊ทธ๋ฆฌ๊ณ ํด๊ฒฐ์ฑ
์ ์ ์ํด ์ฃผ์ ๋ชจ๋ ๋ถ๋ค๊ป ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์ด๋ฏธ์ง๊ฐ ์๋ ์์ ๋ฆฌ์์ค์ ๋ฌธ์ ๊ฐ์๋ ์ฌ๋ ์ด๋ฆ์ ๊ฐ์ง๋ง ํ์ฅ์๊ฐ ๋ค๋ฅธ ํ์ผ์ ์ด๋ฆ ์ .
object.obj
๋ฐ object.mtl
ํ์ผ์ด ์์ต๋๋ค. ํ์ฅ์๊ฐ ๋ค๋ฅด๋๋ผ๋ ์ค๋ณต ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์๋๋ก์ด๋๋ ํ์ผ ์ด๋ฆ์ผ๋ก ๊ทธ๋ค์ ์ ํํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋์, ์ด๋ฆ ๋ณ๊ฒฝ object.mtl
์ object_material.mtl
๊ฒฐ๊ตญ ๋๋ฅผ ์ํด ๊ทธ๊ฒ์ ํด๊ฒฐํ๋ค.
์ด๋ฏธ์ง ๋ฆฌ์์ค์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง ์ผ ์ ์์ต๋๋ค. ๋์ผํ ์ด๋ฆ์ ์ด๋ฏธ์ง๊ฐ์๋ ๊ฒฝ์ฐ ์ด๋ฆ์ ๋ณ๊ฒฝํด๋ณด์ธ์.
๋๋ฅผ ์ํด ์ผํ ๊ฒ์ ๋ ๊ฐ์ง ์๊ฒฌ์ ์กฐํฉ์ด์์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋์ด ํ์ํ ์ ์๋๋ก ์ฌ๊ธฐ์ ๋ถ์ฌ ๋ฃ์ต๋๋ค.
def flavorPathSegment = "" android.productFlavors.all { flavor -> if (targetName.toLowerCase().contains(flavor.name)) { flavorPathSegment = flavor.name } } doLast { def moveFunc = { resSuffix -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/drawable-${resSuffix}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/drawable-${resSuffix}") ant.move(file: originalDir, tofile: destDir) } } def moveRawFunc = { dir -> File originalDir = file("$buildDir/generated/res/react/${flavorPathSegment}release/${dir}") if (originalDir.exists()) { File destDir = file("$buildDir/../src/main/res/${dir}") 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() moveRawFunc.curry("raw").call() }
targetName.toLowerCase().contains(flavor.name.toLowerCase())
์ผํฉ๋๋ค.
๋ด flavor.name
๋ xxXX์ฒ๋ผ ๋ณด์
๋๋ค.
๋ชจ๋ dolast ํญ๋ชฉ์ PR # 24518 ๋ฐ # 24778์ ์ถ๊ฐ ๋ ๋ค์ # 25363์์ ๋ค์ ์ ๊ฑฐ๋์์ต๋๋ค. ์ ๊ฑฐ ๋ ์ด์ ๋ฅผ ์๋ ์ฌ๋์ด ์์ต๋๊น? ์ด๊ฒ์ ์ค๋ซ๋์ ์ง์๋๋ ๋ฌธ์ ์์ผ๋ฉฐ ๊ทธ๋ค์ด ํด๊ฒฐํ๋ค๊ณ ์๊ฐํ์ต๋๋ค.
์ ๊ฒฝ ์ฐ์ง ๋ง์ธ์.
https://github.com/facebook/react-native/issues/22234#issuecomment -504721069
๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ : https://github.com/facebook/react-native/issues/25325
๋์์ด๋๋ ๊ฒฝ์ฐ ๋ค์์ ๋ด ์คํฌ๋ฆฝํธ์์ ํ ์ค๋ก ๋ ๋ช ๊ฐ์ง์ ๋๋ค (Android X ๋ฌธ์ ๋ ํด๋น).
echo "Fixing java error: package android.support.v4.widget does not exist issue with Android X"
npm install jetifier
npx jetify
echo "Fixing duplicate resources issue"
rm -rf .../android/app/src/main/res/raw
cd .../node_modules/react-native
cat <<EOT >> react_gradle.patch
121a122,137
> 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()
> }
>
EOT
ls -l react_gradle.patch
patch react.gradle react_gradle.patch
์ด ์๋ฃจ์ ์ ๋ฆด๋ฆฌ์ค ๋น๋๋ฅผ ๋ง๋๋ ๋ฐ ๋์์ด๋์์ต๋๋ค : https://github.com/facebook/react-native/issues/26245#issuecomment -631382817
๋ค์ ๋จ๊ณ๋ ๋๋ฅผ ์ํด ๊ทธ๊ฒ์ํ์ต๋๋ค.
1. gradlew clean
2. npm install
3. gradlew bundleRelease
System:
OS: macOS 10.15.3
CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
Memory: 221.64 MB / 8.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.13.1 - ~/.nvm/versions/node/v12.13.1/bin/node
Yarn: 1.22.4 - ~/Documents/youpendo-app-bareworkflow/node_modules/.bin/yarn
npm: 6.12.1 - ~/.nvm/versions/node/v12.13.1/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 28, 29
Build Tools: 28.0.3, 29.0.2
System Images: android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 3.6 AI-192.7142.36.36.6392135
Xcode: 11.3.1/11C504 - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_232 - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPackages:
@react-native-community/cli: ^4.8.0 => 4.10.0
react: 16.11.0 => 16.11.0
react-native: 0.62.2 => 0.62.2
npmGlobalPackages:
*react-native*: Not Found
๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด๋ค ํด๊ฒฐ์ฑ ?
๋๊ตฐ๊ฐ ๋ฐ์ ๋ค์ดํฐ๋ธ 0.62.2์ ๋ํ ํจ์น ํ์ผ์ ๊ณต์ ํด ์ฃผ์๊ฒ ์ต๋๊น?
React Native 0.63.2 ์ฉ์ผ๋ก์ด ํจ์น๋ฅผ ๋ง๋ค์์ต๋๋ค. 'drawable- ' ํด๋๊ฐ์๋ ๊ฒฝ์ฐ 'mipmap-'์ผ๋ก ์ด๋ฆ์ ๋ฐ๊พธ๊ณ android / app / src / main / AndroidManifest.xml ์์ ์ฐธ์กฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
ํ๋ก์ ํธ์ ๋ฃจํธ์์ ์ด๊ฒ์ ์คํํ์ฌ ํจ์น ํ์ผ์ ๋ง๋ญ๋๋ค.
cat <<EOT >> react-native-0.63.2-react.gradle.patch
@@ -147,6 +147,23 @@
jsSourceMapsDir.mkdirs()
}
+ doLast {
+ def moveFunc = { resFolder ->
+ File originalDir = file("\${buildDir}/generated/res/react/release/\${resFolder}");
+ if (originalDir.exists()) {
+ File destDir = file("\${buildDir}/../src/main/res/\${resFolder}");
+ 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()
+ }
+
// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir(jsBundleDir)
EOT
๊ทธ๋ฐ ๋ค์ ํจ์น๋ฅผ
patch node_modules/react-native/react.gradle < react-native-0.63.2-react.gradle.patch
๋ํ ์ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค
rm -Rf android/.gradle
cd android && gradlew clean
node_ modules/react-native/react.gradle
์ android/app/react.gradle
๋ณต์ฌ ํ ๋ค์ android/app/build.gradle
๋ฐ android/app/react.gradle
:
android/app/build.gradle
- apply from: "../../node_modules/react-native/react.gradle"
+ apply from: "./react.gradle"
android/app/react.gradle
doFirst {
jsBundleDir.deleteDir()
jsBundleDir.mkdirs()
resourcesDir.deleteDir()
resourcesDir.mkdirs()
jsIntermediateSourceMapsDir.deleteDir()
jsIntermediateSourceMapsDir.mkdirs()
jsSourceMapsDir.deleteDir()
jsSourceMapsDir.mkdirs()
}
+
+ 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)
+ }
+ }
+ def moveRawFunc = { dir ->
+ File originalDir = file("${resourcesDir}/${dir}")
+ if (originalDir.exists()) {
+ File destDir = file("$buildDir/../src/main/res/${dir}")
+ 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()
+ moveRawFunc.curry("raw").call()
+ }
์ด๊ฒ์ react-native 0.63.2
์์ ์ ์๊ฒ ํจ๊ณผ์ ์
๋๋ค.
doLast {
def flavorPathSegment = ""
println targetName.toLowerCase();
android.productFlavors.all { flavor ->
if (targetName.toLowerCase().contains(flavor.name.toLowerCase())) {
flavorPathSegment = flavor.name
}
}
def moveFunc = { resFolder ->
File originalDir = file("${buildDir}/generated/res/react/${flavorPathSegment}/release/${resFolder}");
if (originalDir.exists()) {
File destDir = file("${buildDir}/../src/main/res/${resFolder}");
ant.move(file: originalDir, tofile: destDir);
}
}
moveFunc.curry("drawable").call()
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+0.63.2.patch
diff --git a/node_modules/react-native/react.gradle b/node_modules/react-native/react.gradle
index 6441d93..1eb4645 100644
--- a/node_modules/react-native/react.gradle
+++ b/node_modules/react-native/react.gradle
@@ -147,6 +147,33 @@ afterEvaluate {
jsSourceMapsDir.mkdirs()
}
+ doLast {
+ def flavorPathSegment = ""
+ println targetName.toLowerCase();
+ android.productFlavors.all { flavor ->
+ if (targetName.toLowerCase().contains(flavor.name.toLowerCase())) {
+ flavorPathSegment = flavor.name
+ }
+ }
+ def moveFunc = { resFolder ->
+ File originalDir = file("${buildDir}/generated/res/react/${flavorPathSegment}/release/${resFolder}");
+ if (originalDir.exists()) {
+ File destDir = file("${buildDir}/../src/main/res/${resFolder}");
+ ant.move(file: originalDir, tofile: destDir);
+ }
+ }
+
+ moveFunc.curry("drawable").call()
+ 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()
+ }
+
+
// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir(jsBundleDir)
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..21a13cf
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
@@ -0,0 +1 @@
+export RCT_METRO_PORT=8081
\ No newline at end of file
์๋ ํ์ธ์! ๋๊ตฐ๊ฐ ์ด๋ฌํ ๋ณ๊ฒฝ ์ฌํญ์ ๋ํด PR์ ํ ์ ์์ต๋๊น? node_modules ํธ์ง์ ์ด์์ ์ด์ง ์์ต๋๋ค.
์๋ ํ์ธ์,
๋ฐ์ ๋ค์ดํฐ๋ธ 0.63.2๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋๋ ๋ํ์ด ๋ฌธ์ ์ ์ง๋ฉดํ๊ณ react.gradle ํธ์ง, ๋ฆฌ์์ค / ๋๋ก์ด ๋ธ ์ญ์ ๋ฑ์ ์๋ํ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ง์นจ๋ด gradlew assembleRelease
๋ช
๋ น์ ์คํํ๋ฉด ์ ์๊ฒ ํจ๊ณผ์ ์ด์์ต๋๋ค.
react-native bundle ๋ช
๋ น์ ์คํํ์ง ์์์ต๋๋ค. gradlew assembleRelease
๋ react-native ๋ฒ๋ค์ ์คํํ๊ณ apk ์์ฒด๋ฅผ ๋น๋ํฉ๋๋ค.
์ด๊ฒ์
react-native 0.63.2
์์ ์ ์๊ฒ ํจ๊ณผ์ ์ ๋๋ค.doLast { def flavorPathSegment = "" println targetName.toLowerCase(); android.productFlavors.all { flavor -> if (targetName.toLowerCase().contains(flavor.name.toLowerCase())) { flavorPathSegment = flavor.name } } def moveFunc = { resFolder -> File originalDir = file("${buildDir}/generated/res/react/${flavorPathSegment}/release/${resFolder}"); if (originalDir.exists()) { File destDir = file("${buildDir}/../src/main/res/${resFolder}"); ant.move(file: originalDir, tofile: destDir); } } moveFunc.curry("drawable").call() 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+0.63.2.patch
diff --git a/node_modules/react-native/react.gradle b/node_modules/react-native/react.gradle index 6441d93..1eb4645 100644 --- a/node_modules/react-native/react.gradle +++ b/node_modules/react-native/react.gradle @@ -147,6 +147,33 @@ afterEvaluate { jsSourceMapsDir.mkdirs() } + doLast { + def flavorPathSegment = "" + println targetName.toLowerCase(); + android.productFlavors.all { flavor -> + if (targetName.toLowerCase().contains(flavor.name.toLowerCase())) { + flavorPathSegment = flavor.name + } + } + def moveFunc = { resFolder -> + File originalDir = file("${buildDir}/generated/res/react/${flavorPathSegment}/release/${resFolder}"); + if (originalDir.exists()) { + File destDir = file("${buildDir}/../src/main/res/${resFolder}"); + ant.move(file: originalDir, tofile: destDir); + } + } + + moveFunc.curry("drawable").call() + 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() + } + + // Set up inputs and outputs so gradle can cache the result inputs.files fileTree(dir: reactRoot, excludes: inputExcludes) outputs.dir(jsBundleDir) diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env new file mode 100644 index 0000000..21a13cf --- /dev/null +++ b/node_modules/react-native/scripts/.packager.env @@ -0,0 +1 @@ +export RCT_METRO_PORT=8081 \ No newline at end of file
๊ฐ์ฌํฉ๋๋ค
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
Mapsy์ ๋ต๋ณ์ https://stackoverflow.com/a/52750886์ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก /node_modules/react-native/react.gradle ํ์ผ์ ํธ์งํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋์ผ๋ก doFirst ๋ธ๋ก ํ doLast์ ๊ถ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค.