React native is stuck at old version app - react-native

When I run react-native run-android it only installs the old version of the app in simulator and changes are not shown.
Any suggestion is appreciated.

Seems like we have to re-bundle assets every time we compile it to android app. This worked for me:
First run this:
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
Then this:
react-native run-android

Have you tried react-native start --reset-cache ?
Or maybe you can try to reset the MAX_WAIT_TIME (I found it here).
in file \node_modules\node-haste\lib\FileWatcher\index.js
you should increase MAX_WAIT_TIME variable (example : 360000) and change function _createWatcher.
From:
key: '_createWatcher',
value: function _createWatcher(rootConfig) {
var watcher = new WatcherClass(rootConfig.dir, {
glob: rootConfig.globs,
dot: false
});
return new Promise(function (resolve, reject) {
var rejectTimeout = setTimeout(function () {
return reject(new Error(timeoutMessage(WatcherClass)));
}, MAX_WAIT_TIME);
watcher.once('ready', function () {
clearTimeout(rejectTimeout);
resolve(watcher);
});
});
}
To:
key: '_createWatcher',
value: function _createWatcher(rootConfig) {
var watcher = new WatcherClass(rootConfig.dir, {
glob: rootConfig.globs,
dot: false
});
return new Promise(function (resolve, reject) {
const rejectTimeout = setTimeout(function() {
reject(new Error([
'Watcher took too long to load',
'Try running `watchman version` from your terminal',
'https://facebook.github.io/watchman/docs/troubleshooting.html',
].join('\n')));
}, MAX_WAIT_TIME);
watcher.once('ready', function () {
clearTimeout(rejectTimeout);
resolve(watcher);
});
});
}
May it help you! :D

Tried with the solutions above, not sure if they helped for the final version, but what worked at the end was running ./gradlew clean assembleRelease in the /android folder.

Check for any syntax errors that might not be highlighted by VS code.
After three hours of pulling my hairout turns out it hadnt alerted my to an = instead of a : in an object.

I had this happen while working with iOS, and here are the steps I took to get back to working order:
$ react-native start --reset-cache
$ rm -rf ios/build
Doing this much on its own will force RN to rebuild the iOS version from scratch when you run yarn ios, so this could be answer for most anyone else running with iOS.
In my latest encounter of this issue, I found that after forcing a new build, metro-bundler would throw the following error: Metro Bundler has encountered an error: SHA-1 for file < some file in node_modules >
With this, I had to refresh my node_modules in order to resolve the issue completely.
$ rm -r node_modules
$ yarn

For me I simply restarted my system. Or simply stop the react-native server, then re-run your app.

Use reload option from expo, by dragging from icon bar

Another way to fix this problem is to run this command in your web browser console. I had this problem with React Native for Windows and none of the above solutions worked for me.
localStorage.clear()

The problem is that projectroot > ios > main.jsbundle is not updating as it is supposed to with code changes/builds. To get current, delete that file. Then in Terminal ( only here, do not rely on automatic creation ), put:
react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios/assets
This will create a current main.jsbundle which is used to create the app and also what is used for creating an archive. Problem is, if you update your code, you have to do it again.
You can edit main.jsbundle by hand if you need to. I had to tweak it so some of my images showed up when I had multi-layer folders/pages. Not hard, just search for your image name and look at/edit the link.

This is my solution for debug / release
N.B. - if you're using expo - this is probably not applicable.
yarn android:bundle:debug should get latest debug version...
assumes you're using index.js as main entry point.
Add these to your package.json
"scripts": {
"android": "npx react-native run-android",
"android:bundle:debug": "react-native bundle --platform android --dev true --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/",
"android:bundle:release": "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/",
}
release.sh
yarn android:bundle:release
cd android
./gradlew bundleRelease
cd app/build/outputs/bundle/release
open .

I was creating a staging buildType in my react native project too, the build was fine (after dealing with some problems), but for some reason it was loading an old version of the app too.
After changing the buildType from staging to releaseStaging, it started to build as expected and to load the correct version.
I've answered in another topic too with more specific instructions.

Related

Source map can't be applied due to react-native-reanimated babel plugin

What I am seeing is adding the react-native-reanimated babel plugin (react-native-reanimated/plugin) is causing source maps to be invalid when bundling. I am using Bugsnag and it is saying my source map does not match my code.
Is anyone else using reanimated 2 and experiencing this? Does anyone have any suggestions for workarounds for this? I cannot solve some bugs reported on Bugsnag because of this.
Thanks for the help!
I validated the source map using the npm package sourcemap-validator and it indeed throws an error saying the source map doesn't match the bundle.
I have reproduced this with a new react-native init project. This error occurs in my project using react-native 0.66.4 and in the sample app with react-native 0.70.6
Sample App
https://github.com/MorganTrudeau/rn-sample
There is a README in the repo with steps to reproduce the invalid source map.
Short explanation of what I have done to verify map sourcemap and why I think it is the reanimated babel plugin.
Steps to verify sourcemap
All this code is in the repo provided above to test yourself.
// babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'],
};
// Create the bundle and sourcemap
npx react-native bundle --platform android --dev false --entry-file index.js --reset-cache --bundle-output index.android.bundle --sourcemap-output index.android.bundle.map --minify false
// validate_sourcemap.js
// Sourcemap validation code using sourcemap-validator library
var validate = require('sourcemap-validator'),
fs = require('fs'),
assert = require('assert'),
min = fs.readFileSync('index.android.bundle', 'utf-8'),
map = fs.readFileSync('index.android.bundle.map', 'utf-8');
assert.doesNotThrow(function () {
validate(min, map);
}, 'The sourcemap is not valid');
console.log('Valid source map');
The verification above fails with react-native-reanimated/plugin. If you remove the react-native-reanimated/plugin and re-bundle and run the verification again it passes.
I have tested on a fresh react-native init project. I am assuming this is why my sourcemaps are not working on Bugsnag.
Thanks.

Can't link assets (fonts) in react native >= 0.60

react-native: 0.60.4,
react: 16.8.6,
npm: 6.10.1
XCode: 10.2.1
AndroidStudio: 3.4.1
I created a project using
npx react-native init awesomeApp --template typescript
I have put my assets in the
assets/fonts/<Bunch of .ttf files>
My Directory Structure
awesomeApp
|
+--android
+--ios
+--assets
| |
| +---fonts
| |
| +-- ProximaNova-Bold.ttf
+--react-native-config.js
then I ran
react-native link
Nothing happends, XCode not showing any added Resource neither the android, and when I'm running react-native run-ios showing error that the font is not found.
My react-native-config.js
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./assets/fonts']
};
I have also tried
yarn react-native link and npx react-native link
Well,
finally, I linked my fonts,
I just renamed my file react-native-config.js to react-native.config.js and it worked.
I don't know if this is the right way, I just tried and it worked, for me at least.
Here is the complete walkthrough for linking custom fonts.
my react-native.config.js
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./assets/fonts/'],
};
and logs:
info Linking assets to ios project
info Linking assets to android project
success Assets have been successfully linked to your project
but My mistake was:
Wrong way:
fontFamily: BYekan
Right way:
fontFamily: 'BYekan'
just put font name in ''
For React-native > 0.69, npx react-native link is no longer working
Use npx react-native-asset instead
Just to complement keyserfaty's answer, here is my react-native.config.js working using react-native link:
module.exports = {
dependencies: {
"react-native-gesture-handler": { platforms: { android: null, ios: null } }
},
assets: ['./src/assets/fonts']
};
Create a file in your react native project called react-native.config.js:
In it, paste
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./src/assets/fonts/'],
};
assets: ['./src/assets/fonts/'], should be the path to wherever you stored your custom fonts in your project folder.
When you run the link command, it should work then.
Using RN 0.60.8 with a react-native-config.js file should allow you to link your fonts using react-native link.
My logs:
react-native link
info Linking assets to ios project
info Linking assets to android project
success Assets have been successfully linked to your project
Since you installed React Native using npx I'm guessing you maybe don't have react-native installed globally? Is running react-native link giving you any errors?
None of the above solutions work for me. The issue with what I was having is my Xcode project already had Resources group with a backed folder in it. The way react-native link is working as my understanding is it's creating a group without a folder and add it to your project and link to all your fonts from there. This approach doesn't work when you already have a Resources folder. The solution I could come up with was just renaming the Resources folder to something else and run react-native link again.
If you don't have such a setup, create react-native.config.js file and running react-native link works fine.
react-native.config.js
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./src/assets/fonts/']
};
change assets: ['./src/assets/fonts/'] to assets: ['/src/assets/fonts/']
or use
assets: ['./src/assets/fonts/'] but nameProject/assets
some times you have writed react-native.config.js correctlly
in such cases ; if you do this tasks
it helps you
1- delete react-native.config.js file
2- create this file with same code again
3- write react-native link in console
then you can see resources folder in Xcode
and you can see your fonts in info.plist and copy bundle resources
The "adding the font" should be done in your package.json. Add:
"rnpm": {
"assets": ["./assets/fonts/"]
}
Then run
react-native link
Source
EDIT: The above only works for react-native below 0.60.0

I get a running error with the idex bundle or metro what to do?

Unable to load script. Make sure you're either running a Metro server ('run react-native start') or that your bundle 'index.android.bundle' is packaged correctly for release
I could have posted this as a comment, but it requires few elaboration hence...
I tried adding assets folder in projects -> android/app/src/main/
folder
checked if my index.js is fine and has all entry fine
import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
AppRegistry.registerComponent(appName, () => App);
ran this 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
Now i am able to run the application. All this I tried searching SO, and the reference questions are
1) stack overflow reference 1
2) Stack overflow reference 2

React Native bundle in release APK is not working

I'm newbie in RN. I have a problem with building release APK. I'm doing following steps:
rm -rf node_modules & npm install
Generating bundle:
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 assembleRelease
app/build.gradle:
project.ext.react = [
entryFile: "index.js",
bundleInDebug: true,
bundleInRelease: true,
]
apply from: "../../node_modules/react-native/react.gradle"
....
It seems bundleInRelease option is not working properly. However ./gradlew assembleDebug works perfect! Please help!
Solved!
I used 'react-native-bitcoinjs-lib' library and the thing is the library was not fully configured. By documentation, for generating release APK, additionally, I had to create file in project named metro.config.js. And wrote following code in it:
module.exports = {
transformer: {
minifierConfig: {
mangle: {
keep_fnames: true
}
}
}
}
Now, everything works fine.

React Native : Error: Duplicate resources - Android

I was trying to create a release apk file from Android but when I create a release apk with PNG image I'm getting Duplicate Resource error. Initially I thought this is happening because I made a mistake in the existing project but when I created a new project with a single Image component itself I'm getting the Duplicate Resource error. Here are the steps I followed
Create a app - react-native init demo
Create a assets folder in the project root folder.
Add a PNG image inside the assets folder.
Now implement the Image component with the above PNG image.
Now bundle it using the 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/
Then generate release apk using Generate Signed APK from Android Studio.
This will throw the following error:
[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
Note: When you generate a release apk without any PNG image you will not get any error, it will create you the release apk.
Here are the other files code.
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"
}
}
Any solution for this?
Update:
Here are the other details
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
Tried with Android Studio 3.0, 3.0.1, 3.1, 3.1.4 & 3.2
(UPDATED)
This solution works for me
rm -rf ./android/app/src/main/res/drawable-*
rm -rf ./android/app/src/main/res/raw
In my case, the build failed because there are duplicated resources in my Android project (in Android folder), these two lines are necessary to remove duplicated resources, that's all.
After trying a lot of solutions I found only Three solution is working. Here they are
Solution 1:
Clean the drawable folder from the terminal using Gradle. cd into the android folder, then run cmd ./gradlew clean
Solution 2:
After bundling delete the drawable folder from Android Studio. You could find this in android/app/src/main/res/drawable
Solution 3:
PLEASE DO NOT USE SOLUTION #2, AS PROPOSED BY THE ORIGINAL AUTHOR! All packages under node_modules are generated, and any changes you make will be lost when the react-native package is reinstalled / upgraded.
In this solution you no need to delete any drawable folder. Just add the following code in the react.gradle file which you could find under 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()
}
For reference I will add the full react.gradle file code here
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)
}
}
Credit:
ZeroCool00
mkchx
For generating debug 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 .."
For generating release 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 .."
Works fine for my react-native >= 0.61.2 project by using the above code on my scripts section of package.json file.
The accepted answer will work, however it does not take into account that modifying a node package means that if you update your change will be lost (as well as being against best-practices, you should extend the module somehow).
This is originally from React-native android release error: duplicate resource
Create folder fixAndroid in the android folder of your project ({project-root}/android/fixAndroid).
Create file android-gradle-fix in the fixAndroid folder of your project ({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
Create file android-release-fix.js in the fixAndroid folder you created:
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)
}
Add script to package.json scripts section:
"postinstall": "node ./android/fixAndroid/android-release-fix.js"
This will find and insert content of “android-gradle-fix” file into node_modules/react-native/react.gradle.
Run npm install from the root of your project.
Run rm -rf android/app/src/main/res/drawable-* from the root of your project.
Now you can bundle the release with either React Native at the console or Android Studio:
React Native command line
cd {project-root}/android
./gradlew/bundleRelease
Android Studio
Open folder android in Android Studio and build project.
Select Build/Generate signed APK to build release.
Delete drawable-xxx folders
Delete raw
inside src -> main -> res folder then
run this command in terminal:
react-native bundle --dev false --platform android --entry-file index.js --bundle-output ./android/app/src/main/assets/index.android.bundle --assets-dest ./android/app/src/main/res_temp
then generate signed apk using keystore, alias and passwords using terminal or android studio
who are facing the same issue in RN!
I think it's absolutely awful that this issue stands here for so long time already, but I want to share the way to solve it after investigation of different solutions.
Jeffrey Rajan is absolutely right about the possible solutions here https://stackoverflow.com/a/53260522/1611414
I think it's super bad to change react.gradle file in node_modules and it leads to many many different issues with the maintenance of this RN project. So I would recommend to chose the first option - to use bash command to remove that folder before running build.
I want to share what I've done in my project and maybe you can reuse the same approach:
In ./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"
}
and the release is running by doing yarn release.
These lines are important:
&& rm -rf ./android/app/src/main/res/drawable-mdpi/
&& rm -rf ./android/app/src/main/res/raw/
they remove duplicated resources from the build step before bundleRelease is running. The solution is tested with RN 0.57, 0.58, 0.59 and 0.60
Enjoy!
for latest version of React-Native and gradle, you don't need to bundle your assets. Once you are done with the code, just cd into the android folder and run:
./gradlew assembleRelease
The assets are automatically bundled while the above command is been executed. The duplicate resources error shows up because you have explicitly bundled before and running the above command bundles again hence the error.
In my case, it worked after adding a few lines to Jaffrey's Answer
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);
}
}
tolotrasmile's answer worked for me.
I included it in my little bash script that I run whenever I want to build & install Android
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
cd ..
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
cd ../../
adb install -r "$PROJECT_DIRECTORY"/android/app/build/outputs/apk/release/app-release.apk
Try to use another directory for assets destination (for example res_temp).
react-native bundle --dev false --platform android --entry-file index.js --bundle-output ./android/app/src/main/assets/index.android.bundle --assets-dest ./android/app/src/main/res_temp
I am also adding res_temp in gitignore.
Tested in Gradle 6.0.1 and RN 0.62.2
was error with release build /android/app/src/main/res/raw/app.json:
[raw/app]
/android/app/build/generated/res/react/release/raw/app.json: Error: Duplicate resources
deleted /android/app/src/main/res/raw/app.json
then ran ./gradlew clean in android folder
and then ran ./gradlew bundleRelease
For me it was a cache issue. The following command worked for me
cd into android folder
Run ./gradlew clean
Solution.
I just clean gradlew and starts working no need to change anything in.
/node_modules/react-native/react.gradle
Steps
1) cd android && ./gradlew clean && cd ..
2) react-native run-android
"dependencies": {
"react": "16.11.0",
"react-native": "0.62.2",
}
Spent ages on this! None of the proposed solutions were an immediate fix for me.
So I moved out all the dirs that were getting mentioned in the "duplicate resource" error message:
mv ./android/app/src/main/res/drawabl* /tmp
mv ./android/app/src/main/res/raw /tmp
then I ran a
./gradlew clean
then I ran a build:
/gradlew bundleRelease
the build was giving me a couple of errors along the lines of 'could not find a specific file in a specific place', so for each of these files I found them in the tmp/drawable folders and copied them to the exact path that the error message said it expected them to be e.g (you'll have to customise this according to the error message you get):
cp /tmp/drawable-mdpi/launch_screen.png app/src/main/res/drawable/
then:
./gradlew clean
/gradlew bundleRelease
And it finally buily successfully
for me go to dir:
android/app/src/main/assets/fonts
check .ttf files you expect, delete .ttf of vector icons
I had also this problem and to solve it, I have deleted resource folders and used gradlew clean.
I ended up with this Windows cmd script for compiling my app:
#echo off
call 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
rmdir android\app\src\main\res\drawable-hdpi /s/q
rmdir android\app\src\main\res\drawable-mdpi /s/q
rmdir android\app\src\main\res\drawable-xhdpi /s/q
rmdir android\app\src\main\res\drawable-xxhdpi /s/q
rmdir android\app\src\main\res\drawable-xxxhdpi /s/q
rmdir android\app\src\main\res\raw /s/q
cd android
call gradlew clean
REM call gradlew assembleRelease
call gradlew bundle
cd ..
dir /o:d android\app\build\outputs\apk\release
dir /o:d android\app\build\outputs\bundle
My version react native is: 0.66.3 , I had fix trought commands:
rm -rf ./android/app/src/main/res/drawable-*
rm -rf ./android/app/src/main/res/raw
Then run :
./gradlew clean
Finally: Generate Signed Bundle from Android Studio and works.
Use com.android.tools.build:gradle:3.1.4 It should work. RN 0.57 has problem with building in 3.2
This question is a possible duplicate of:
React Native Error: Duplicate resources, assets coming in some screens and not coming in others in android release APK
If it still doesn't work try to use RN 0.57.2, I am using it and creating releases works very well with these 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",
.....
}
Gradle deps:
classpath 'com.android.tools.build:gradle:3.1.4'
classpath "io.realm:realm-gradle-plugin:4.0.0"
App gradle
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "de.burda.buntede"
minSdkVersion 17
targetSdkVersion 27
Gradle wrapper props:
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
Remove the files you might have on:
android/app/src/main/res/drawable-mdpi/
android/app/src/main/res/drawable-xhdpi/
android/app/src/main/res/drawable-xxhdpi/
Run Build again, This fixed the issue for me.
So basically edit the /node_modules/react-native/react.gradle file
and add the doLast right after the doFirst block, manually.
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()
}
I am using react-native 0.63.2. I also faced this issue and tried editing react.gradle, deleted resources/drawable and all. But at last cleaning gradle and running the command gradlew assembleRelease worked.
I didn't run the react-native bundle command separately. gradlew assembleRelease is running the react-native bundle and building apk itself.
The solutions like patching the react.gradle file may work but they are just workarounds. The real solution lies in figuring out the problem.
If its only happening while creating release build then chances are you're bundling separately. If you're upgrading from older versions of react native which didn't have a react.gradle file you'd have to bundle separately and then do 'cd android && ./gradlew assembleRelease' but with the introduction of react.gradle the bundling process has now been taken care by the react.gradle file, so don't bundle separately just run 'cd android && ./gradlew clean && ./gradlew assembleRelease' to build the release apk.
If this happens in debug also then chances are some generated assets or all of the generated assets have been pushed and currently reside in your directory. So i would suggest just delete all of them from the respective directory and if they are tracked by git try adding them back one by one. We had some assets starting with src_assets_blahblah which we had to delete since they were already getting generated during the build process.
None of the suggested solutions works for me
In my case it was related to .gradle folder. Before getting this error i have moved the folder to another disk, but some files failed to copy to the destination folder.
I just cut the old folder and merge it with the destination folder.
In my case, raw directory was containing some duplicates. So, I have to add a different function for that as well, name of added function is moveFuncRaw below worked perfectly for me.
doLast {
// Address issue #22234 by moving generated resources into build dir so they are in one spot, not duplicated
def moveFuncRaw = { dirName ->
File originalDir = file("$buildDir/generated/res/react/release/${dirName}");
if (originalDir.exists()) {
File destDir = file("$buildDir/../src/main/res/${dirName}");
ant.move(file: originalDir, tofile: destDir);
}
}
// Address issue #22234 by moving generated resources into build dir so they are in one spot, not duplicated
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()
moveFuncRaw.curry("raw").call()
}
One more thing to realize that doLast do not gets called every time as there could be some conditions on it like in my case there were, so you have to call separately to get it executed.
If the above answers are not working and if the issue is similar to the below error
> Task :app:mergeReleaseResources FAILED
ERROR: [drawable-mdpi-v4/node_modules_reactnative_libraries_newappscreen_components_logofgdsfsdfsdfds]
/Users/emmsdan/Repo/untitledApp/android/app/src/main/res/drawable-mdpi/node_modules_reactnative_libraries_newappscreen_components_logofgdsfsdfsdfds.png
[drawable-mdpi-v4/node_modules_reactnative_libraries_newappscreen_components_logofgdsfsdfsdfds]
/Users/emmsdan/Repo/untitledApp/android/app/build/generated/res/react/release/drawable-mdpi/
node_modules_reactnative_libraries_newappscreen_components_logofgdsfsdfsdfds.png: Resource and asset merger: Duplicate resources
Not the most elegant solution but this worked for me.
Delete this
rm -rf rmnode_modules/react-native/Libraries/NewAppScreen
I had similar issues, even on a newly created react-native app.
Deleting NewAppScreen and everywhere it was called fixed it for me.
It's not needed to add any code in the react-native module.
By default, the app/build.gradle set the property bundleInRelease as true. This means that if you run the react native bundle before the build, you will get this error.
To fix this issue, make sure that your app/build.gradle has the following code:
project.ext.react = [
bundleInRelease: false
]
You can find more details in: https://github.com/react-native-community/cli/blob/master/docs/commands.md
Accepted answer's solution 1 will work but it will add some more things to your assets.
Solution 1:
Clean the drawable folder from the terminal using Gradle. cd into the android folder, then run cmd ./gradlew clean
This will solve the initial problem of old code rendering but will create another issue usually: the issue of duplicate resources.
Check your androids res folder there will be added additional assets in your mipmap filders and res folder, delete all the additional added assets from the folders and run the release version of app ad you will be good to go.
This issue comes after you run 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
So only thing you want to do is remove the resources files which builds with it.
If you use git,
stage index.android.bundle and discard other new resource files.
A slight addition: sometimes you end up with a "raw" in the resources folder. That has to go too.
So a slight modification to the existing react.gradle script:
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()
}
By adding this is in /node_modules/react-native/react.gradle
After DoFirst Paste This Code
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()
}