在Android上运行NodeJS的可行选项(2017年8月)

有许多旧的SO线程处理在Android上运行NodeJS。 其中大多数不再可行(JXCore)和/或提供令人困惑,过时,不完整或错误的信息。

因此,我调查了目前(截至2017年8月)可行的方法,并find了三个可能的候选人。

要在他们之间做出决定,我想知道:

  • 这些方法之间的主要区别
  • 每种方法的特定专业人员和骗局
  • 可能遇到障碍,挑战和缺点
  • 你知道其他可行的替代方案吗?

可行的方法是

  1. 运行包含NodeJS ( J2V8 )的V8 javascript引擎
  2. 直接使用NodeJS,嵌入为本机库( node-on-android
  3. 将React Native与NodeJS app-as-a-service( react-native-node )相结合

除此之外,我还find了许多相关的有趣资源:

  • NPM在没有root的情况下直接使用Termux安装NodeJS(不适用于最终用户)
  • LiquidCore – 原生移动微应用程序devenv(未调查,有趣的概念)
  • dna2oslab – 有一个用于节点可执行文件的工作NodeJS构建脚本
  • 为Android构建NodeJS – 博客提供有用的编译技巧和示例项目

Solutions Collecting From Web of "在Android上运行NodeJS的可行选项(2017年8月)"

调查可行的选择

[ 注意这个答案包含原始问题中的发现]

我已经对各种选项进行了更多调查,这里有一些初步调查结果。

0.编译NodeJS

每个选项都使用为Android编译的某种forms的NodeJS。 但是要使用任何选项,您可能希望编译到不同的Node,Android和体系结构(x86,ARM,ARM64等)版本。

这是有问题的。 NodeJS有一个android-configure脚本,但这会导致我尝试过的大多数组合出错。 我为工作的构建脚本创建了许多github问题。 在此问题中收集结果:

  • 适用于Android ARM节点7.x或8.x共享库的工作构建脚本

总结一下:

  • 共享库构建都失败(除了在你的android上物理构建,见下文)
  • 带有NodeJS( libnode.a )的libnode.alibj2v8.so静态链接,适用于7.x到7.9.0
  • build-as-node-executable适用于7.x(使用dna2oslab构建脚本)

@mafintosh使用了一个有趣的解决方法:使用Termux将Node传输到设备并在那里进行编译 (需要很多空间和时间,但有效)。

1.运行包含NodeJS ( J2V8 )的V8 javascript引擎

J2V8是一组用于V8的Java绑定。 J2V8专注于性能和与V8的紧密集成。 […] [which]强制在JS和Java代码之间建立一个更静态的types系统,但它也提高了性能,因为没有创建中间对象。 […]

构建J2V8需要构建本机部分和Java库(.jar / .aar文件)。 要构建本机部分,我们首先将node.js构建为库,然后将J2V8静态链接到该库。 […]

对于交叉编译,J2V8使用Docker(android,linux,windows)和Vagrant(macos)。

请参阅slideshare: 在Java World中运行 NodeJS(或参见InfoQvideo ,32分钟)

特点

  • 用更强大的v8替换JavaScriptCore引擎(使用NodeJS)
  • 通过添加的J2V8 JNI / Java层支持multithreading(线程/工作者)
    • 每个线程都可以拥有自己的Isolated V8实例
  • 双向js-to-java桥(从脚本调用java,反之亦然)
  • 双向集成错误/exception处理
  • 漂亮的交叉编译交互式构建系统( 正在进行中 )
  • chrome调试支持
  • 其他,types数组,ES6支持,…

特点

  • 指定要在build_system/build_settings.py编译的版本
  • 使用python build.py --interactive开始构建,选择build:

     [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 
  • 选择构建步骤(或all ):

     NodeJS --> CMake --> JNI --> Optimize --> Java/Android --> JUnit 
  • 将V8编译为共享库libj2v8_{platform}_{abi}.{ext}

    • 注意nodejs构建步骤无法构建Node共享库(errors),在libj2v8.so创建要链接的静态libj2v8.so
  • 有一个JNI层,可以通过Java访问v8的大部分内容
  • 使用Java实现的其他function(例如JS < - > Java桥)
  • 最终构建输出是Gradle .aar ,包含为项目依赖项

优点

  • 相对活跃的项目
  • 高质量的代码,包括Javaunit testing
  • 为您的应用设计工具包添加Java的全部function
  • 优秀,直观的构建系统(一旦完成)

缺点

  • 很少,过时的使用文档
    • 特别是未记录的是在大型(r)规模的JS项目中的使用
  • 许多必须维护的JNI胶水代码
  • 项目维护不善(许多旧的未解决的问题,非合并的公关)
    • 有些公关人员连续两年都没有回复。 不好
  • 比其他选项更难理解J2V8项目设置(许多文件)
  • 许可问题 (EPL 1.0许可中的“保留所有权利”)

2.直接使用NodeJS,嵌入为本机库( node-on-android )

Android上的节点通过使用共享库在Android应用程序内运行您的Node.js来工作。 然后它捆绑一个托管您的UI代码的WebView 。 所有UI都只是经典的html / css / js。

在节点应用程序中,您可以要求node-on-android访问WebView。 您可以使用它在WebView加载html页面。

根据node-on-android创建者( @mafintosh ),它比J2V8更容易和更好,因为它直接编译V8 作为真实的东西

特点

  • 构建成熟的NodeJS应用程序,包括UI(通过本机WebView)

特点

  • gradle app项目中的相关目录/文件:
    • 带有节点.h标头的app/src/main/include/node
    • app/src/main/jniLibs/arm64-v8alibc++_shared.solibnode.so
    • app/src/main/cpp with native-lib.cpp (包括node.h
    • Java代码,只是在一个单独的线程中运行节点的情况下旋转一个Service
  • libnode.so没有JNI,所以private native void startNode(String... app); 在IDE中显示为错误(但编译)
  • NodeJS项目驻留在android/app/src/main/assets/node
  • NodeJS代码被转移到临时存储并从那里执行
  • NodeJS应用程序通过公开的loadUrl函数指定要在WebView中加载的视图
    • 节点服务可通过NPM软件包node-on-android

优点

  • 简单的项目,没有太多的管道代码
  • 附带最新的v8.x Node版本开箱即用
  • 简单的基于HTML的应用程序UI编程(例如使用choo )
  • 开箱即用:)

缺点

  • 非常新的项目,只有实验代码
  • 来自arm64架构(计划完全移动支持,或DIY构建)
    • 注意 :64位不能与React Native结合使用( 不支持64位 )!
  • 没有原生UI(除非在Gradle / Java / XML中编码)
  • 节点应用程序没有调试支持(AFAIK,但也许您可以以某种方式附加到WebView)

3.将React Native与NodeJS app-as-a-service( react-native-node )相结合

在React Native应用程序后面的后台运行一个真正的 Node.js进程。

使用此软件包,您可以:在Android中运行http服务器,使用节点流,与文件系统接口,从React Native中的JS线程中卸载一些繁重的处理,等等! 在Android中运行真正的Node.js,您可以执行桌面上Node.js的所有操作。

特点

  • 使用React Native作为UI,NodeJS作为后台服务

特点

  • 源自NodeBase
  • 与node-on-android非常相似(在单独的线程上运行带有Node的Service
    • 但是node被编译/用作应用程序,而不是嵌入式共享库
    • NodeJS应用程序代码位于{projectRoot}/background
    • NodeJS可执行文件位于/android/src/main/res/raw/bin_node_v710
    • 在构建时节点应用程序是tarballed,解压缩在`/ android / src / main / res / raw / {appName}
    • 调用NodeJS服务就像从命令行运行一样,传递args
  • 节点服务RNNode通过导入react-native-node在RN中可用
    • react-native-node还包含在构建时传输节点代码的CLI
  • Example项目通过REST从React Native传递到NodeJS服务
    • 在节点端的http://localhost:5000上运行express服务器

优点

  • 简单的项目,没有太多的管道代码
  • 明显:在Android上用NodeJS反应原生支持!
  • Node-as-executable可能适用于64位设备+ react-native

缺点

  • 非常新的项目,只有实验代码
  • 附带旧的NodeJS 7.1.0版本(但DIY构建新的版本)
  • RN和Node应用程序之间没有简单的通信方式(基于REST)
    • 需要扩展REST API或推出自己的机制
  • Node应用程序没有调试支持。 真的很难知道发生了什么

现状(2017-08-17)

我的目标是React Native + NodeJS。 这是我的活动状态:

  • 将NodeJS v7.x版本编译为可执行文件
  • 编译NodeJS v7.4.0至v7.9.0适用于新的J2V8构建系统
  • 编译NodeJS v8.1.2很快就可以使用J2v8(针对libc++编译)
  • react-native-node确实编译,但尽管尝试了很多次但仍无法运行
  • node-on-android工作,但仅限节点的应用程序开发和64位与RN不兼容

我决定将react-native-nodeJ2V8结合使用,原因如下:

  • 伟大的交叉编译构建PR: https : //github.com/eclipsesource/J2V8/pull/327
  • 构建一个漂亮的J2V8 .aar ,可轻松包含在Gradle中

React Native 0.46.4 + 7.9.0正在运行! 看到:


我的用例: 胖客户端与P2P分散式网络

我正在考虑CQRS(命令查询 – 责任 – 隔离)设计:

  • react-native UI是从节点服务查询的视图构造的
  • react-native UI动作触发节点后台服务上的命令
  • 后台服务处理网络消息,传入命令,触发事件
  • 事件存储在Realm DB中,形成正面和背面之间的桥梁

详细信息: Realm.io将在Android胖客户端应用程序(CQRS样式)中桥接本机NodeJS + React Native


结论

即使经过多年努力将NodeJS移植到Android之后仍然没有真正好的解决方案,它仍然是开创性的。

在设置项目和构建环境时会遇到许多障碍和错误,但一旦设置完毕,您就可以在手机上享受Node的全部function。

截至今天(2018年3月),还有另一个尚未列入当前答案的可行替代方案: Node.js for Mobile Apps 。

该项目的核心是提供了一个本地库,用于将Node.js嵌入到原生Android和iOS应用程序中; 但它还附带了React Native和Cordova的插件。

该库的预构建二进制文件适用于Android armeabi-v7a,x86,arm64-v8a,x86_64和iOS 64位。

核心库是nodejs / node-chakracore的一个分支, 它又是nodejs / node的分支 。 Android版本几乎是常规的Node.js构建为库,具有一些可移植性修复。 iOS版本使用ChakraCore引擎而不是V8(由于nodejs / node-chakracore fork的更改,可以用ChakraCore替换V8)。

React Native和Cordova插件可以更轻松地将Node.js添加到使用这些框架构建的应用程序中。 Node.js代码运行在一个单独的引擎和线程中,而不是框架(React Native / Cordova)。 两个JavaScript世界之间的通信是通过插件提供的消息传递桥实现的。

项目网站上提供了更多信息,包括一些文档。

(完全披露:我为开发移动应用程序的Node.js的公司工作。)

我收到了来自@ dna2github的回复 ,这是NodeBase的创建者(非常感谢!)我将在这里包含(经过许可):


嗨,

谢谢你的问题。 我会在我看来做一个简短的回答。

1.在android上运行包含NodeJS的V8 javascript引擎

优点:

  • 与Java世界集成; 可以完全控制代码。

缺点:

  • 有点难以与第3个软件包集成(需要时间学习如何)。
  • 需要了解NodeJS和V8以及J2V8文档(它耗时很长)。

2.将NodeJS编译为本机库(使用node-on-android)

优点:

  • 专注于js dev而不需要考虑android方面。
  • 减少学习时间; 类似于Cordova phonegap ….

缺点:

  • js app => apk是一个黑盒子。

3.使用Termux在Android上运行NodeJS

优点:

  • 灵活

缺点:

  • 没有gui

4.其他有趣的方法

不熟悉LiquidCore; 我认为,特别是从url构建微服务就是解决iOS上没有直接可用的存储问题。 react-native-node Android部分基于NodeBase方法并使用预构建的二进制文件。

对于NodeBase:

优点:

  • 类似于3; 区别在于它有自己的gui来启动/停止a​​pp。
  • 它可以成为一切的模板; 例如,如果想运行django,你只需要将节点替换为python; 铁轨,ruby……

缺点:

  • 本机进程访问问题; 该流程无法inheritanceAndroid应用的访问权限。
  • 快乐玩具开心源不像商业应用; 如果想要分发给客户,需要更多的设计

首先,我在终端运行节点; 我发现只有dev可以很容易地用它来启动js app。 我的朋友和家人也想要一些工具,例如批量制作水印。 为他们创建NodeBase以便于启动/停止应用程序。 然后他们只需打开浏览器即可使用它。 创建NodeBase的另一个想法是我们可以构建可在同一Wi-Fi中共享的可共享应用程序。 当主持人启动应用程序时,附近的人可以访问它。 然后他们可以一起工作和玩耍。 例如,我们玩狼人,当没有法官时,我们将启动狼人应用程序,让第一轮的法官。 我们还可以通过下载/上传在设备之间共享文件。

对我来说,我可以灵活地构建我想要的东西,例如,我想让我的Android成为机器学习者; 它可以帮助我随时运行机器学习程序(使用node和python,因此在我的另一个回购中: dna2oslab专注于构建二进制文件)以利用手机运行时间。

对于你,如果想在短时间内移植你的应用程序,我建议2; 如果你有时间和其他资源,1更好。 3如果您只是制作玩具/演示。 其他4个总是可能的,只是想象力创造作品。

祝七,祝福

我尝试在我的Android Java应用程序中使用J2V8通过node.js运行JS脚本。 它失败并出现此错误:

java.lang.UnsupportedOperationException:不支持StartNodeJS。

J2V8的回应是:

“节点包装器在Android上不可用,它们仅在桌面平台(windows,mac,linux)上可用。这是预期的行为,直到我们有Android的节点二进制文件。”

据我所知,目前没有计划为Android实现节点包装器。

谢谢,

亚历克斯唐尼尼