简介
Chrome V8 引擎是 Google 自己开发的 javascript 脚本引擎。开发语言为 C++。
在 Android 平台上的浏览器框架如下图,是基于 WebKit 实现的。其中 JS Engine 部分,在 Android 2.2 版本以前使用的是 JavaScriptEngine, 在 Android 2.2 及以后版本使用了 V8 引擎。
关于 WebKit 的更多资料:
在 Android 上如果要运行 JavaScript。有三种方式:
- 通过 WebView API 来执行 JS 代码。
这种方式通过直接调用 Android 控件来实现,开发难度最低,限制性较大,性能较低。
使用方法 Google 一下 - 通过调用系统的 V8 库来执行。
这块我目前还没调研,可以借鉴这篇 StackOverflow 的回答 - 自己编译 V8 作为应用程序自带的库来调用。
由于 V8 是开源的,可以通过自己编译 V8 引擎来使用。这样可定制性最好。
本文重点介绍如何自己编译 V8 引擎作为应用程序自带的库来调用。
编译 V8 源码
自己编译
自己尝试编译 V8 引擎,需要根据 官方提供的编译流程进行编译环境准备和工具安装。下面是官方的集成流程。也可以通过官方 github wiki 页面查看完整的最新文档。
其中可以看出不是用git 命令直接 clone 或者 pull V8 的代码,是需要使用 depot_tools 中的 gclient 获取 V8 代码。
关于 D8 on Android 这篇文章:
我一开始看到这篇文章,以为是介绍如何把 V8 引擎移植到 Android 的干货,但是其实不是的。
D8 是 V8 引擎的命令行工具,所以 D8 on Android 这篇文章是叫你如何在 Android 命令行 「adb tool 」中集成 D8 从而支持运行 JS 脚本的。
所以要集成 V8 引擎,并不是看这篇文章。
目前自己编译 V8 源码遇到的问题:
- make android_arm.release 遇到错误
- 编译产物过大(800M),而例如 NativeScript 项目中 使用的 V8 引擎包只有几十M。
基于以上问题,目前暂时没有用自己编译的V8 引擎。
借鉴 V8Android 项目源码
V8Android 是 GitHub 上的一个开源项目,它实现了在 Android 端调用 V8 引擎的简单 DEMO。
通过这个Android 工程可以完成简单的调用 V8 引擎的实践。
不过这个工程有两个问题:
- 使用的 Eclipse 工程结构开发,目前要在 AndroidStudio 上使用的话需要进行相关调整。
- 使用的 V8引擎较久。由于 V8 引擎已经经过了多版本的迭代,API 也有较大的更改。所以如果基于这个工程的 V8引擎进行开发,后续做V8 引擎的版本更新很麻烦。
使用 NativeScript 项目源码
NativeScript 是 GitHub 上的一个开源项目,它实现了在 IOS 和 Android 上使用 JS 进行应用开发的框架。AndroidRuntime 是 NativeScript 在 Android 上实现其 JS 运行能力的一个开源项目,这个项目也是基于 V8 开发的。
由于NativeScript 的更新比较频发,他的AndroidRuntime 使用的 V8 版本也是较新的版本。所以我们可以使用 AndroidRuntime 中集成的 V8 库来进行我们的应用开发。
更极端的,可以直接基于 AndroidRuntime 项目进行你的应用开发。AndroidRuntime 提供了更加便利的面向应用层的框架。
本文采取的集成方案是使用 AndroidRuntime 中引用的V8 库和对应NDK-build 配置文件进行我的 V8 引擎的封装。后续章节会有详细介绍。
集成 V8 引擎
在上述章节说了本文采取的集成方案,是使用 AndroidRuntime中引用的 V8 引擎库和对应的 NDK-BUILD 配置文件进行我的 V8引擎的封装。
之所以这么做,是因为在 Android 中进行 C++ 库的构建,需要编写 Android.mk 和 Application.mk 两个配置文件,而 V8 引擎的编译对所依赖的一些 静态库文件,以及依赖的 Android NDK 库,还有一些编译选项有特定的要求。所以如果要编译成功,对 Android.mk 和 Application.mk 两个文件的编写有一定的难度。所以这里索性直接使用 AndoridRuntime 中的配置文件来进行集成。
具体集成步骤:
- 正确配置 Android NDK-BUIlD 环境。具体步骤查看Android NDK 官网
- 将 AndroidRuntime 「/src/jni 」目录的 Android.mk 和 Application.mk 文件拷贝到你的 「/src/jni 」目录。
- 将 V8 的静态库文件拷贝到「 /src/jni/libs」目录。
Android.mk 文件中对静态库文件的路径都有配置,在做完这部的时候,注意查看 Android.mk 文件中的静态文件路径是否指向了你实际方式静态文件的位置。如果错误,会导致 ndk-build 编译失败。
- 将 V8 的头文件拷贝到 「 /src/jni/include」目录。
一般直接把 Android-Runtime 项目中的 include 目录整个拷贝过来就行。你也可以在其使用的 V8 版本的源码中的 include 目录找到这些头文件。
- 添加你的应用的 JNI 接口头文件,并实现。这一步在下个章节重点说明。
- 使用 ndk-build 工具编译出 so 包。
应用层 JNI API 开发
在 Android 中必须通过 JNI 接口来使用 C++ 的库。所以如果要在 Android 中使用 V8 引擎,必须根据我们应用层需要,开发JNI 接口,并在JNI 接口的 C++ 实现中调用 V8 引擎。
具体步骤:
- 在 JAVA 类中声明 native 方法。
- 使用 javah 工具生成包含对应的 JNI 接口的头文件
- 将头文件移动到 /src/jni 目录下,并创建对应的cpp 文件,实现对应的接口。
下面详细介绍 JNI 接口实现。
实现 JNI 接口
在实现 JNI 的过程中,可以参考的资料:
- Chrome V8 官方说明文档。可以通过它知道 V8 的一些特性。
- V8 源码 Sample 目录。可以知道基本的使用
请注意不同版本的 Sample 可能不一样。请查看自己版本对应的 git 中的 Sample 目录。
- AndroidRuntime 中对应的实现。通过他可以了解很多 V8 API 的用法。
关于这里实现 JNI 的小提示:
- JNIEnv 提供的API 要区分 C 和 C++,请确认清楚。