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

IT技术 javascript java android node.js react-native
2021-02-06 06:56:00

有一堆旧的 SO 线程处理在 Android 上运行 NodeJS。其中大多数不再可行 (JXCore) 和/或提供混乱、过时、不完整或错误的信息。

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

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

  • 这些方法之间的主要区别
  • 每种方法的具体优点和缺点
  • 可能的障碍、挑战和缺点
  • 你知道其他可行的选择吗?

可行的方法是

  1. 运行包含NodeJS ( J2V8 ) 的V8 javascript 引擎
  2. 直接使用 NodeJS,作为原生库嵌入(node-on-android
  3. 将 React Native 与 NodeJS 应用即服务(react-native-node)相结合

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

5个回答

调查可行的选择

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

我对各种选项进行了更多的调查,这里有一些初步的发现。

0.编译NodeJS

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

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

总结一下:

  • 共享库构建全部失败(除非在您的 android 上进行物理构建,请参见下文)
  • 带有 NodeJS ( libnode.a) 的J2V8静态链接在libj2v8.so7.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 代码之间强制使用更静态的类型系统,但它也提高了性能,因为没有创建中间对象。[...]

构建 J2V8 需要构建原生部分和 Java 库(.jar/.aar 文件)。为了构建原生部分,我们首先将 node.js 构建为一个库,然后将 J2V8 静态链接到它。[...]

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

参见幻灯片:在 Java 世界中运行NodeJS (或参见InfoQ 视频,32 分钟。)

特点

  • 用更强大的 v8 替换 JavaScriptCore 引擎(使用 NodeJS)
  • 通过添加的 J2V8 JNI / Java 层支持多线程(线程/工人)
    • 每个线程都可以拥有自己的独立 V8 实例
  • 2-way js-to-java 桥(从脚本调用 java,反之亦然)
  • 2路集成错误/异常处理
  • 漂亮的交叉编译交互式构建系统(正在开发中
  • 铬调试支持
  • 其他,类型化数组,ES6 支持,...

特点

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

    [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构建步骤无法构建节点共享库(错误),创建静态libnode.a链接libj2v8.so
  • 有一个 JNI 层,使 Java 可以访问 v8 的大部分内容
  • 在 Java 中实现的附加功能(例如 JS <--> Java 桥)
  • 最终构建输出是一个 Gradle .aar,作为项目依赖项包含在内

优点

  • 比较活跃的项目
  • 高质量的代码,包括 Java 单元测试
  • 将 Java 的全部功能添加到您的应用程序设计工具包中
  • 出色、直观的构建系统(完成后)

缺点

  • 很少,大多是过时的使用文档
    • 特别未记录的是在大型(r)规模的 JS 项目中的使用
  • 很多必须维护的JNI胶水代码
  • 项目维护不善(许多旧的未解决问题,未合并的 PR)
    • 一些 PR 挂了 2 年甚至没有得到回应。不好
  • 比其他选项更难理解 J2V8 项目设置(许多文件)
  • 许可问题(EPL 1.0 许可中的“保留所有权利”)

2. 直接使用NodeJS,作为原生库嵌入(node-on-android

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

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

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

特点

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

特点

  • gradleapp项目中的相关目录/文件
    • app/src/main/include/node带节.h点头
    • app/src/main/jniLibs/arm64-v8alibc++_shared.solibnode.so
    • app/src/main/cppnative-lib.cpp(包括node.h
    • Java 代码,只是启动一个Service在单独线程中运行的节点
  • 没有 JNI for libnode.so,因此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 构建)
  • 没有可能的原生 UI(除非在 Gradle/Java/XML 中编码)
  • Node 应用程序没有调试支持(AFAIK,但也许您可以以某种方式附加到 WebView)

3. 结合 React Native 和 NodeJS 应用即服务(react-native-node

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

使用这个包,你可以:在 Android 中运行 http 服务器,使用 Node 流,与文件系统接口,从 React Native 中的 JS 线程卸载一些繁重的处理,等等!在 Android 中运行真正的 Node.js,您可以完成桌面上 Node.js 所能做的一切。

特点

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

特点

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

优点

  • 简单的项目,没有太多的管道代码
  • 显而易见:在 Android 上使用 NodeJS 支持 React Native!
  • Node-as-executable 可能适用于64 位设备 + react-native

缺点

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

现状 (2017-08-17)

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

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

我决定合并react-native-nodeJ2V8因为:

React Native 0.46.4+ NodeJS7.9.0现在可以工作了!看:


我的用例:具有 P2P 去中心化网络的胖客户端

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

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

详细信息:Realm.io 在 Android 胖客户端应用程序中桥接原生 NodeJS + React Native(CQRS 风格)


结论

即使多年来人们试图将 NodeJS 移植到 Android 上,仍然没有真正好的解决方案,它是开创性的。

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

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

该项目的核心是提供一个原生库,用于将 Node.js 嵌入到原生 Android 和 iOS 应用程序中;但它也带有React NativeCordova 的插件

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

核心库是一个叉的NodeJS /节点chakracore,这又是叉的NodeJS /节点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 的公司工作。)

谢谢,效果很好!完全满足我的需求npm和多文件支持(最终没有使用,但很高兴知道它可用)。几乎设法使canvas工作,但我需要在 Linux(目前使用 Windows)中采取一些额外的步骤,我找到了一个不需要它的替代库。
2021-03-29 06:56:00

我是LiquidCore的作者LiquidCore 允许您在 Android 和 iOS 上使用 Node.js 的完整实现(iOS 支持刚刚在 0.5.0 版 - 2018 年 9 月发布)。

LiquidCore 旨在使 Node 的多个实例能够在本机移动应用程序内同时运行。每个实例都有自己的虚拟文件系统和对 MySQL 的本机支持。该项目的目标是使用 JavaScript/WebAssembly 构建完整的“微应用程序”,然后将其嵌入到其他应用程序中,我仍在朝着这个目标努力。但截至今天,如果您只想要一个 Node.js 游乐场,它会非常有效。

如果你想看看它可以做什么,有一个简单的节点控制台应用程序包含在AndroidiOS 中

谢谢!我已经创建了一个 GH 问题来正式发布:github.com/LiquidPlayer/LiquidCore/issues/62
2021-03-13 06:56:00
@ArnoldSchrijver。它是在 MIT 许可下获得许可的,或者类似的许可。用它做你想做的事!
2021-03-17 06:56:00
@SahilSingh LiquidCore 实例在应用程序中自己的后台线程上运行。我还没有将它实现为一项服务,但这是一个有趣的想法。
2021-03-18 06:56:00
非常酷@EricLange!我只是想知道“保留所有权利”许可。您是否计划重新授权为知名的 OSS 许可证?
2021-04-01 06:56:00
我可以在 React Native 应用程序中使用 LiquidCore 吗?
2021-04-08 06:56:00

我收到的答案来自@ dna2github,创作者NodeBase(非常感谢!),我会在这里包括(许可):


你好,

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

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

优点:

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

缺点:

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

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

优点:

  • 专注于 js 开发,无需考虑 android 端。
  • 学习时间少;类似于 Cordova phonegap ....

缺点:

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

3. 使用 Termux 在 Android 上运行 NodeJS

优点:

  • 灵活的

缺点:

  • 没有gui

4. 其他有趣的方法

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

对于 NodeBase:

优点:

  • 类似于3;不同之处在于它有自己的 gui 来启动/停止应用程序。
  • 它可以是一切的模板;例如,如果想运行 django,你只需要将 node 替换为 python;导轨,红宝石...

缺点:

  • 本机进程访问问题;该进程不能从 Android 应用程序继承访问权限。
  • 快乐玩具快乐开源不像商业应用程序;如果要分发给客户,则需要更多设计

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

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

对你来说,如果想在短时间内移植你的应用程序,我推荐 2;如果你有时间和其他资源,1更好。3 如果你只是做一个玩具/演示。4 其他总是可能的,只是发挥你的想象力来创作作品。

最好的祝福,七

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

java.lang.UnsupportedOperationException:不支持 StartNodeJS。

J2V8 的回应是:

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

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

谢谢,

亚历克斯·唐尼尼

嗨,亚历克斯!从我上次的回复中可以看出,我现在有点不高兴了。仍在继续发展,并可能在未来回升。我在 2017 年 8 月版本的 J2V8 中工作正常,但有时会出现问题(崩溃)。最新状态是:github.com/eclipsesource/J2V8/issues/332
2021-03-30 06:56:00