Exploring Viable Options
[ NOTE This answer contains the results that were in the original question]
I have studied various options several times and here are some preliminary conclusions.
0. Compilation of NodeJS
Each option uses some form of NodeJS compiled for Android. But to use any option, you probably want to compile different versions of Node, Android and architecture (x86, ARM, ARM64, etc.).
This is problematic. NodeJS has an android-configure script, but this leads to errors in most combinations that I tried. I created a number of github issues for a working build script. This issue contains the results:
Summarizing:
- the shared library builds everything crashes (except when you physically create your android, see below).
- J2V8 with NodeJS (
libnode.a ), statically linked in libj2v8.so , works for 7.x to 7.9.0 - build-as- node -executable works for 7.x (using dna2oslab build script)
One interesting workaround was used by @mafintosh : transfer Node to the device using Termux and compile there (it takes a lot of space and time, but it works).
1. Launch V8 javascript engine, which includes NodeJS ( J2V8 )
J2V8 is a set of Java bindings for V8. J2V8 focuses on performance and tight integration with V8. [...] [which] creates a more static type system between JS and Java code, but also improves performance since intermediate objects are not created. [...]
To build J2V8, you need to create both your own parts and the Java library (.jar / .aar file). To build our own parts, we first create node.js as a library, and then statically link J2V8 to this. [...]
For cross-compiling, J2V8 uses Docker (android, linux, windows) and Vagrant (macos).
Watch the slide show: Launching NodeJS in the Java World (or see InfoQ video , 32 min.)
Functions
- replace JavaScriptCore mechanism with more powerful v8 (using NodeJS)
- multithreading support (threads / workers) through the added J2V8 JNI / Java level
- each thread can have its own isolated instance of V8
- 2-way js-to-java bridge (call java from script and vice versa)
- 2-way integrated error / exception handling
- beautiful cross-compilation of an interactive build system ( in the works )
- chrome debugging support
- other, typed arrays, ES6 support, ...
Characteristics
- Specify the versions to compile in
build_system/build_settings.py Run the assembly simply using python build.py --interactive , select the assembly:
[0] Docker >> android-x86 >> NODE_ENABLED [1] Docker >> android-arm >> NODE_ENABLED [2] Docker >> alpine-linux-x64 >> NODE_ENABLED [3] Docker >> linux-x64 >> NODE_ENABLED [4] Docker >> linux-x86 >> NODE_ENABLED [5] Vagrant >> macosx-x64 >> NODE_ENABLED [6] Vagrant >> macosx-x86 >> NODE_ENABLED [7] Native >> windows-x64 >> NODE_ENABLED [8] Docker >> windows-x64 >> NODE_ENABLED [9] Vagrant >> windows-x64 >> NODE_ENABLED
Select build steps (or all ):
NodeJS --> CMake --> JNI --> Optimize --> Java/Android --> JUnit
Compiles V8 as a shared library libj2v8_{platform}_{abi}.{ext}
- Note :
nodejs build step cannot build Node shared library (errors), creates static libnode.a for communication in libj2v8.so
- Has a JNI level to make large parts of v8 available to Java
- Additional features (e.g. JS ↔ Java bridge) implemented in Java
- The final output of the assembly is Gradle
.aar for inclusion as a project dependency
Pros
- Relatively active project
- Good quality code including Java modulation tests
- Adds all the power of Java to your application development tool.
- Great intuitive build system (once completed)
against
- Small, mostly outdated usage documentation
- Particularly undocumented is the use of JS in large (r) -scale projects.
- Lots of JNI glue code to be supported
- The project is not supported (many old open issues not related to PR)
- Some PR lasts for 2 years, without even receiving an answer. Not good
- It is more difficult to understand the J2V8 project setup (many files) than other parameters.
- Licensing Issue ("All Rights Reserved" in EPL 1.0 License)
2. Use NodeJS directly, built-in as a native library ( node-on-android )
Node on android works by running node.js inside an Android application using a shared library. It then links the WebView that hosts your user interface code. The whole user interface is just classic html / css / js.
In a Node application, you may need node-on-android to access the WebView. You can use this to load an html page in a WebView .
According to node-on-android creator ( @mafintosh ), this is simpler and better than J2V8, as it directly compiles V8 as the real thing.
Functions
- Creation of full-fledged NodeJS applications, including the user interface (through its own WebView)
Characteristics
- Relevant directories / files in the Gradle
app project:app/src/main/include/node with Node .h headersapp/src/main/jniLibs/arm64-v8a with libc++_shared.so and libnode.soapp/src/main/cpp with native-lib.cpp (includes node.h )- Java code just includes
Service with Node running in a separate thread
- It does not have a JNI for
libnode.so , therefore private native void startNode(String... app); shows as an error in the IDE (but compiles) - The NodeJS project is in
android/app/src/main/assets/node - NodeJS code is transferred to temporary storage and executed from there
- NodeJS application defines views for loading in WebView through the open function
loadUrl- Node service available through NPM
node-on-android package
Pros
- A simple project, not much plumbing
- Comes with the latest version of v8.x Node from the finished
- Simple HTML-based application user interface programming (e.g. using choo )
- Works out of the box :)
against
- Very new project, only experimental code
- Only available for
arm64 architecture (full mobile support planned or built DIY)- Note : 64-bit combination cannot be combined with React Native ( without 64-bit support )!
- There is no native user interface (unless encoding in Gradle / Java / XML)
- No debugging support in Node app (AFAIK, but maybe you can somehow connect to WebView)
3. Combining React Native with a NodeJS application ( react-native-node )
Run the real node.js process in the background behind the React Native app.
Using this package, you can: run HTTP servers in Android, use Node streams, an interface with the file system, unload some heavy processing from a JS stream in React Native, and much more! Running real node.js on Android, you can do whatever node.js can do on the desktop.
Functions
- Use React Native for UI, NodeJS as Background Service
Characteristics
- Derived from NodeBase
- Very similar to node -on-android (start
Service with Node in a separate topic)- But
node compiled / used as an application, not a built-in shared lib - NodeJS application code is located in
{projectRoot}/background - The NodeJS executable is located in
/android/src/main/res/raw/bin_node_v710 - At the time of Node build, the application is archived, unpacked in `/ android / src / main / res / raw / {appName}
- NodeJS service is invoked as if executed from the command line, passing args
- Node
RNNode service available in RN by importing react-native-nodereact-native-node also contains a CLI that passes Node code at build time
- Sample project communicates with React Native NodeJS service via REST
- Starting
express server on http://localhost:5000 on Node side
Pros
- A simple project, not much plumbing
- Obvious: Respond to NodeJS support on Android!
- Node -as-executable will probably work with 64-bit devices + adaptive
against
- Very new project, only experimental code
- Comes with the old version of NodeJS
7.1.0 (but DIY build is newer) - There is no easy way to communicate between RN and Node applications (REST-based)
- You need to expand the REST API or minimize your own mechanism.
- No debugging support in Node application. It’s actually hard to understand what’s going on.
Status (2017-08-17)
My goal is React Native + NodeJS. This is the status of my activity:
- Compiling NodeJS v7.x Versions as Executable Files
- Compiling NodeJS v7.4.0 to version v7.9.0 works with the new J2V8 build system.
- Compilation NodeJS v8.1.2 will work soon with J2v8 (compiled against
libc++ ) react-native-node compiles but fails despite many attempts.node-on-android works, but node is only application development and 64-bit incompatible with RN
I decided to combine react-native-node with J2V8 because of:
React Native 0.46.4 + NodeJS 7.9.0 now works! Cm:
My use case: a bold client with a decentralized P2P network
I mean the CQRS design (command-request-responsibility-segregation):
- The response user interface is created from the view requested from the Node service.
- Respond to native Node background UI commands
- the background service processes network messages, incoming commands, trigger events
- events are stored in Realm DB, which forms a bridge between the front and rear
Details: Realm.io for connecting your own NodeJS + React Native in the Android client application for Android (CQRS style)
Conclusion
Even after many years when people try to connect NodeJS to Android, there are still no real good solutions, this is an innovation.
Expect a lot of obstacles and mistakes when setting up your project and build environment, but after installation you can enjoy the full power of Node on your phone.