在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 – 博客提供有用的编译技巧和示例项目

  • React native不支持的major.minor版本52
  • 如何更新反应本机应用程序的版本号
  • 处理Android中的React Native,Navigator中的后退button
  • react-native:找不到命令
  • React本机android应用程序已停止
  • 本机如何禁用android开发模式
  • 让Android RecyclerView更新React Native组件内的视图
  • 如何使用React Native的Espresso UItesting?
  • 调查可行的选择

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

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

    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实现节点包装器。

    谢谢,

    亚历克斯唐尼尼