如何用网站做招聘,国内erp软件公司排名,手机电脑网站一站式,怎么用阿里云服务器做淘客网站V8 引擎是由 Google 开源的 JavaScript 引擎#xff0c;Chrome 就是基于 V8 开发#xff0c;V8 是跨平台的#xff0c;J2V8 基于 V8 进行开发#xff0c;使得 js 代码能够在 Android 平台上脱离 WebView 运行。目前#xff0c;也有很多关于 Android J2V8 的文章#xff0…V8 引擎是由 Google 开源的 JavaScript 引擎Chrome 就是基于 V8 开发V8 是跨平台的J2V8 基于 V8 进行开发使得 js 代码能够在 Android 平台上脱离 WebView 运行。目前也有很多关于 Android J2V8 的文章不过讲解不是特别细可能也是我太菜了看完了之后依然遇到很多问题自己在调研的过程中遇到很多坑所以这里记录一下本文主要记录整个 J2V8 框架的使用方法以及一些坑。
一、Webpack 打包
通常业务逻辑的 js 文件是有多个的我们需要借助一些打包工具将多个文件打包成一个 js 文件供 J2V8 使用我们可以使用 Gulp、Webpack、Browserify本文主要讲 Webpack 的使用。 主要流程如下
编写基础逻辑并通过 module.exports 对外部提供
编写 index.js 入口文件
...
module.exports {simpleFunc, complexFunc
};
** 编写webpack.config打包配置**
module.exports {entry: ./src/example/index.js,output: {library: libExample, // j2v8 加载该libpath: path.resolve(__dirname, dist),filename: example.js, // 导出指定命名的 js 文件 },...
};执行 webpack 打包命令
./node_modules/.bin/webpack --config webpack.config.js二、运行 JavaScript
到这里我们已经有一份通过 Webpack 打包好的 js 文件了要在 j2v8 中运行 JavaScript 文件使用以下步骤
1、创建一个 V8 实例
V8 v8 V8.createV8Runtime();2、读取 JavaScript 文件
var scriptStr String(Files.readAllBytes(Paths.get(example.js)))3、在 V8 实例中执行 JavaScript 代码
v8.executeScript(scriptStr);这一步已经让整个 js 文件运行起来但我们还不能调用我们的方法
4、读取指定模块
由于是通过 Webpack 打包在 Webpack 的 output.library 配置选项用于将打包后的代码作为一个库(library)暴露出去以便其他应用程序或模块可以使用它。
val rootLib v8.getObject(libName); // 这里的 libName 就是 output.library 配置的名字如果是访问模块的导出对象中的子对象那么继续
val subLib rootLib.getObject(subLibName); // 这里的 subLibName 是 index 文件中 module.exports 里面的模块名如果子对象还有子对象继续.getObject 即可
5、运行指定方法
接下来就简单了直接通过如下方法执行 js 中的指定方法 public void executeVoidFunction(String name, V8Array parameters)public String executeStringFunction(String name, V8Array parameters) public double executeDoubleFunction(String name, V8Array parameters) public int executeIntegerFunction(String name, V8Array parameters)……V8Object 提供了很多数据格式调用不过都差不多主要是在返回值那里帮你实现了数据的转化如果不想用转化好的格式希望自己来操作的话使用public V8Object executeObjectFunction() 拿到返回值自己去转化即可
6、释放资源
由于 V8 运行消耗较多的资源执行结束的时候要将在过程中创建的所有的资源释放避免导致内存泄漏。 V8提供了close方法如果只使用 v8.close() 进行释放或者未关闭过程中有用到 v8 runtime 的变量都会报如下错误正确的做法是将所有资源进行关闭。
java.lang.IllegalStateException: 3 Object(s) still exist in runtime三、进阶
通过以上的方式已经能执行很多逻辑了但在实践过过程中发现如何 js 的返回值是 Promise 的话不会等到最终的结果给我们而是直接返回了一个 Promise 对象以及看不到 console.log 打印的日志…… 诸如此类的问题需要解决这里主要讲讲这两种方法的实现。
注册 Native 插件
J2V8 是一个基于 V8 引擎的 Java 库它允许在 Java 中执行 JavaScript 代码。由于 J2V8 是在 Java 中运行的它没有直接访问浏览器或控制台的能力因此无法直接使用 console.log 函数来输出日志总结 J2V8 不能实现以下功能 浏览器 APIj2v8 是在 Java 中运行的因此无法直接访问浏览器 API如 DOM、BOM 等。这意味着 j2v8 无法直接操作网页内容、处理事件等文件系统访问j2v8 在 Java 中运行无法直接访问文件系统。如果需要访问文件系统需要使用 Java 提供的文件操作 API。定时器JavaScript 中有多种定时器函数如 setTimeout、setInterval 等可以在指定时间后执行代码。但 j2v8 无法实现这些定时器函数因为它无法直接访问系统的计时器。Web WorkerWeb Worker 是 JavaScript 中的一个特殊对象可以在后台线程中执行代码以避免阻塞主线程。但 j2v8 无法实现 Web Worker因为它无法直接访问操作系统的线程。Node.js APIj2v8 主要是为了在 Java 中执行浏览器端的 JavaScript 代码而设计的因此无法直接访问 Node.js API。如果需要在 Java 中执行 Node.js 代码可以考虑使用 Nashorn 等其他工具。 这里是 console.log的一个简单实现
V8Object 是 J2V8 中的一个类它代表了一个 JavaScript 对象对于 console.log 我们可以将 console 看作一个对象其有一个叫 log 的方法要实现在 js 中打印日志到 Android Studio 控制台如下即可
class ConsolePlugin {fun log(message: Any) {Log.d(ConsolePlugin, message.toString())}fun register(v8: V8) {val v8Console V8Object(v8)// 第一个 log 表示 在 Java 中该方法的名字第二个 log 表示在 JavaScript 中调用的名字 v8Console.registerJavaMethod(this, log, log, arrayOfClass*(Any::class.java))v8Console.setWeak()// 将含有叫log方法的一个对象加到运行环境中该对象被命名为 consolev8.add(console, v8Console)}
}ConsolePlugin().register(v8)具体代码可参考:J2V8_tutorial
执行返回值是 Promise 类型的方法
之前将的方法调用都是返回数据为基础类型由于在 Java/kotlin 中没有Promise类型的方法所以对于 Promise 方法我们需要进行一些特殊处理我们通过使用 CountDownLatch 可以来实现一个 “异步变同步” 的操作我们需要考虑的是如何接受到 resolve rejcet的调用js 中 Promise 的方法使用如下
PromiseMethod().then((result){// success got result}).catch((e){// error...});
在 J2V8中一样的实现
获取返回的 Promise 对象 val promiseObj v8.executeFunction(functionName, v8Array) as V8Object**执行 Promise 对象的 then 和 catch 方法 **
jsPromise.apply {val onResolveParameter V8Array(v8).push(onResolve)val onRejectParameter V8Array(v8).push(onReject)executeVoidFunction(then, onResolveParameter)executeVoidFunction(catch, onRejectParameter)....}其中 onResolve
val onResolve V8Function(jsRuntime) { receiver, parameters -……}具体代码可参考:J2V8_tutorial
四、总结
以上基本上能解决大部分 Android 调用 js的代码逻辑了这里对整体执行的流程进行一个总结
1、通过 webpack 对多个 .js 文件打包 2、初始化 V8 环境并加载 .js 文件 3、注册 Java 方法供 js 进行调用 4、读取指定的模板 5、执行目标 js 方法并释放 v8 执行过程中产生的资源
踩过的一些坑
1、java.lang.UnsupportedOperationException: StartNodeJS Not Supported.
这个库有一个 NodeJS.createNodeJS()方法以为是完美结合 NodeJs 的查了下不太支持 Android不过也有人提出解决方法https://stackoverflow.com/questions/42574824/how-to-use-nodejs-in-android-using-j2v8
2、java.lang.IllegalStateException: 3 Object(s) still exist in runtime
这是调用 v8.close 总是会遇到的问题一定需要确保使用了 v8 Runtime 过程变量有被释放掉可能有时候不知道具体哪个变量没有被释放
3、setTimeout、setInterval 无效
这是我最开始遇到的问题简单想着“既然能执行js代码那 setTimeout、setInterval 这些方法都是 js 最普通的方法应该没问题吧”如果有一些平时在 js 很常见的操作如果无法执行最好 check 一下 J2V8 是否支持
4、Undefined 相关
虽然源码里面通过了一个 Undefined 的类但是不能直接使用如果方法返回的 Undefined通过 V8Object 的 isUndefined() 去判断
引用
[1]J2V8 https://eclipsesource.com/blogs/tutorials/getting-started-with-j2v8/
[2] Registering Java Callbacks with J2V8 https://eclipsesource.com/blogs/2015/06/06/registering-java-callbacks-with-j2v8/
[3] Simple JS in Node.js https://yenhuang.gitbooks.io/android-development-note/content/wrap-js-library/simple-js-with-nodejs.html