I'm trying to run my react native android app in debug mode on our devices, without the need for a dev server running on a dev box. I'm using the debug variant/scheme on both platforms to facilitate the "staging" version of our app, since I've read that react native is not super friendly with build modes other than release and debug.
On the iOS side, I was able to modify the AppDelegate.m as follows... basically, if it's a debug build and it was built by buddybuild, don't look for a dev machine for the js bundle, look to the device:
#ifdef DEBUG
NSDictionary *infoPlistDict = [[NSBundle mainBundle] infoDictionary];
if (infoPlistDict[#"BUDDYBUILD_BUILD_ID"]) {
// deployed via buddybuild, don't use localhost
jsCodeLocation = [[NSBundle mainBundle] URLForResource:#"main" withExtension:#"jsbundle"];
} else {
jsCodeLocation = [NSURL URLWithString:#"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
}
#else
jsCodeLocation = [[NSBundle mainBundle] URLForResource:#"main" withExtension:#"jsbundle"];
#endif
... I'm looking for a way to do this on android. I have the buddybuild bit of code I need, so no worries there, I just want to know how to programmatically change the location of the js bundle on android as I do above for iOS in AppDelegate.m. Right now, all code related to the location of the js bundle on android seems to be in the react-native package itself and I'd rather not hack that to get it to work.
If I can provide any more information, please let me know.
I would like to summarize the solution to bundle everything within a debug build. Especially the hint in point two did the trick for me. Thanks #Tspoon.
1. Android Studio
go to Preferences -> Build, Execution, Deployment -> Compiler
uncheck "Configure on Demand"
2. build.gradle
within your app/build.gradle file do the following:
project.ext.react = [
// whether to bundle JS and assets in debug mode
bundleInDebug: true,
// whether to bundle JS and assets in release mode
bundleInRelease: true,
]
apply from: "../../node_modules/react-native/react.gradle"
NOTE that it is important to define the react settings above the apply from ... statement, otherwise it will not work
3. Create APK
create your dev apk as usual with ./gradlew assembleDebug within your android folder
On Android, you'll want to modify android/app/build.gradle.
Before the apply from: "../../node_modules/react-native/react.gradle" line, you'll want to tell the packager to bundle the js assets and include them when deploying your APK.
For example:
project.ext.react = [
bundleInBuddybuild: true,
]
Where the syntax is bundleIn${productFlavor}${buildType}
Or if you just want to do it for for debug builds:
project.ext.react = [
bundleInDebug: true,
]
Related
Recently, we added to our native app a small module of React Native code.
When I follow the instructions in:
https://reactnative.dev/docs/integration-with-existing-apps
It's working fine, the RN module is working as expected.
The problem is that I need to place the RN directory inside the Android directory and not the other way around...
For example, this is how it's currently working:
Projects/ReactNativeProject/Android/
And this is how we need it to work:
Projects/Android/ReactNativeProject
The problem - AutoLinking won't work when I Changed the directories order...
With this CLI error:
Calling `[node, /Users/odedfunt/node_modules/#react-native-community/cli/build/bin.js, config]` finished with an exception. Error message: groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object
When I add this line to gradle it's not helping:
project.ext.react = [
enableHermes: false, // clean and rebuild if changing
cliPath: ["node", "-e", "console.log(require('react-native/cli').bin);"].execute([], projectDir).text.trim(),
cliPath: "$rootDir/react-native-project/node_modules/react-native/cli.js"
]
this is my settings.gradle
rootProject.name = "ReactTest200"
include ':app'
include ':react-native-svg'
def linkReactSVG = "$rootDir/react-native-project/node_modules/react-native-svg/android"
println("========================= link reactSVG: ${file(linkReactSVG)}")
project(':react-native-svg').projectDir = new File(rootProject.projectDir, linkReactSVG)
def linkSettings = "$rootDir/react-native-project/node_modules/#react-native-community/cli-platform-android/native_modules.gradle"
println("========================= linkSettings: ${file(linkSettings)}")
apply from: file(linkSettings); applyNativeModulesSettingsGradle(settings)
Does anyone knows what's the problem? I've been working on the for days and still couldn't figure it out...
I have properly working in development environment react-native application. I wanted to test it's performance and released a build, which crashes after the launch.
01-09 20:16:13.644 23215 23251 E ReactNativeJS: Object type 't' not found in schema.
01-09 20:16:13.648 23215 23251 E ReactNativeJS: Module AppRegistry is not a registered callable module (calling runApplication)
I couldn't determine the cause of crashing because of minification and uglify of the sources. Could you, please, help me with disabling it, because I already spent plenty of hours on it.
react-native version: 0.49.5
putting --minify=false in extraPackagerArgs in android/app/build.gradle should do the job.
project.ext.react = [
entryFile: "index.js",
extraPackagerArgs: [ '--minify=false' ],
];
You can accomplish this with the use of the CLI tool, Haul
Haul bundle --minify false should do the trick, if not, Haul provides other commands as well.
I think you should first test your app by unchecking dev mode on your in app developer menu.
i had the same problem and it took me some time to figure out.
i disabled the dev mode so it generates the JS bundle same like release bundle and i found the problem and fixed it.
If anyone got to here this might help:
node_modules/.bin/haul bundle --dev=false --config=node_modules/react-native-bundle-visualizer/src/webpack.haul.js
you can know more doing:
node_modules/.bin/haul bundle --help
I'm using haul as my development server/bundler for a React Native app I am building because I need access to sym links and the standard React Native bundler doesn't give access to them.
I followed the documentation and added:
project.ext.react = [
cliPath: "node_modules/haul/bin/cli.js"
]
to my android/app/build.gradle file and generated the following wepack.haul.js file.
const path = require("path");
module.exports = ({ platform, root }, defaults) => {
return {
entry: `./index.${platform}.js`,
resolve: {
...defaults.resolve,
alias: {
...defaults.resolve.alias,
config: path.join(root, 'config.js')
}
}
}
};
When I run ./gradlew assembleRelease in the android folder of my project directory to generate the .apk file, I get the following error that it couldn't follow the symbolic link.
* What went wrong:
Could not list contents of '/Users/brendan/Projects/<project-name>/node_modules/<team-name>/mart-redux/node_modules/node-pre-gyp/node_modules/.bin/nopt'. Couldn't follow symbolic link.
I'm also getting error messages that my config alias in my webpack.haul file isn't resolving but I believe both of these issues are related.
I believe that the ./gradlew assembleRelease call is using the standard RN packager rather than haul which is why the sym links and alias resolve aren't working properly.
How can I get ./gradlew assembleRelease to use haul?
I'm not sure if this is the proper way to solve the issue but I got haul working in both my local environment and building the .apk file by commenting out the line below in the android/app/build.gradle.
project.ext.react = [
cliPath: "node_modules/haul/bin/cli.js"
]
// apply from: "../../node_modules/react-native/react.gradle"
ALL the documentation seems to consider one is either in development mode and seeking to switch ports for a developer device or the are doing a production build! I just want to create an appDebug.apk that anyone can use to run the app without seeing errors about bridges, event emitters, or AppRegistry etc. I can't tell others who want to see the React Native app to switch ports etc, and I don't want to do a full release every time I share the app. Any suggestions?
UPDATE: I do not want to debug the app. I just want to release a test build that works on anyone's device so I can share the build for testing.
UPDATE: HERE IS MY PROJECT STRUCTURE:under
main-project
-> index.android.js
->gridlew
-> build.properties
->build.gradle
->package.json
-> my-app (App project folder)
-> build->output->apk->release.apk
->src->main->assets
->src->main->res
->src->main->java
https://stackoverflow.com/a/36961021/6832877
For testing the Apps on devices I use this comment from another question
You need to manually create the bundle for a debug build.
Bundle debug build:
react-native bundle --dev false --platform android --entry-file index.android.js --bundle-output ./android/app/build/intermediates/assets/debug/index.android.bundle --assets-dest ./android/app/build/intermediates/res/merged/debug
Create debug build:
cd android
./gradlew assembleDebug
The .apk will be in:
"APP"/android/app/build/outputs/apk
P.S. Another approach might be to modify gradle scripts.
For bridge problems:
react-native run-android
react-native start --reset-cache
or:
cd myproject
react-native start > /dev/null 2>&1 &
curl "http://localhost:8081/index.android.bundle?platform=android" -o
> "android/app/src/main/assets/index.android.bundle
or:
adb reverse tcp:8081 tcp:8081
Here are the steps needed to make this work taken from the build.grade generated from creating a react-native app:
This is your app build file:
import com.android.build.OutputFile
// These properties must be declared above the apply below!
project.ext.react = [
// whether to bundle JS and assets in debug mode
bundleInDebug: true,
// whether to bundle JS and assets in release mode
bundleInRelease: true,
bundleIn$releaseDebug: true // For custom release type
]
apply from: "../node_modules/react-native/react.gradle" // adjust depending on where your node_modules directory is located.
Also check that you have ext properties defined with app package name etc in the build.gradle a level up.
This works and the bundle is created successfully for all build types.
Maybe use Expo or create-react-native-app?
Install Expo app on their iOS or Android phone.
Run your project, you will get a link or QRCode.
Then send this link or qrcode to share your app to anyone.
In my project I've achieved this by creating a build variant that bundles the generated RN code within the APK.
Generating the bundle.js
Using wget I grab the RN code from the Node.JS local server and save it as bundle.js:
wget "http://127.0.0.1:8081/index.android.bundle?platform=android&dev=false" -O bundle.js
Adding bundle.js to the project
I add the bundle.js file to assets/ dir.
Creating a build variant that points RN to the file
I don;t wanna manually change my code whenever I wanna switch between local (bundle.js) and live versions. So I've created a build variant for this case.
There is an extensive tutorial on build variants here, so I'll just go over the cruicial details only.
In my build.gradle, under the android node, I've added:
productFlavors {
bundled {
buildConfigField 'boolean', 'BUNDLED', 'true'
buildConfigField 'String', 'DEV_HOST', "null"
}
}
This automatically generates BuildConfig.java (more about this here):
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "....";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "bundled";
public static final int VERSION_CODE = ...;
public static final String VERSION_NAME = ...;
// Fields from product flavor: bundled
public static final boolean BUNDLED = true;
}
Pointing RN to bundle.js
So now I fire up RN based on my build variant:
boolean bundled = BuildConfig.BUNDLED;
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("bundle.js")
.setJSMainModuleName("index.android")
.setJSBundleFile(bundled ? "assets://bundle.js" : null)
.addPackage(new MainReactPackage(false))
.addPackage(mInnerItemReactPackage)
.setUseDeveloperSupport(bundled ? false : ConfigSupplier.isDebuggable())
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
Generating the APK
I choose the correct build variant from the Build Variants screen:
And then proceed as usual by clicking Build -> Build APK.
I might add a more detailed blog post later.
I have a React Native project and it runs successfully on both simulators and devices for iOS.
However, for Android, it runs successfully on simulators without any problems, but when run on devices as a Release build, it gives me this error:
Requiring unknown module "react-native-safari-view".
I tried npm cache clean and npm install several times, but it does not work.
The module exists in node_modules folder and it is also under dependencies in package.json.
What could be the cause of this? Why does it happen only in Release builds?
Update: If this is difficult to fix, is it possible to generate a signed apk with the js bundle included in dev mode?
It is because react-native-safari-view module is not designed for Android.
Check this out: (inside index.android.js file in GitHub)
var SafariViewManager = {
test: function() {
warning('Not yet implemented for Android.');
},
isAvailable: function() {
...
}
};
Maybe you are initiating a SafariViewManager object and calling other functions like show() in index.ios.js without checking it isAvailable()?