Cordova插件中JavaScript代码与Java的交互细节介绍
在Cordova官网中有这么一张架构图:大家看右下角蓝色的矩形框"Custom Plugin"——自定义插件。意思就是如果您用Cordova打包Mobile应用时,发现您的移动应用里需要使用一些功能,这些功能用普通的JavaScript无法实现,而是需要调用移动平台的一些原生API才能实现时,我们就需要自己实现自定义插件。这些插件通过在特定的移动平台上采用原生开发实现,比如Android Studio中的Java开发,然后再通过JavaScript wrapper的方式暴露给您的Mobile应用。比如您是用Cordova在Android平台上打包生成APK文件,那么您的Mobile代码(JavaScript)里还是不会直接调用您用Java实现的Custom Plugin,而是调用Custom Plugin对应的JavaScript wrapper。
那么JavaScript wrapper本身是JavaScript代码,它是怎么调用到Custom Plugin的Java实现的?本文就会介绍这个细节。
下图是OData离线存储插件(OData Offline Store)的JavaScript实现代码的一部分。下图第232行会调用设备的native API进行离线存储的打开操作:
exec(win, error, 'OData', 'openOfflineStore', [this, options ? options : {}]);
这个exec函数从哪里来?由Cordova框架实现,通过语句 require(‘cordova/exec’)返回。
那么当应用执行到JavaScript代码:exec(win, error, 'OData', 'openOfflineStore', [this, options ? options : {}]); 的时候,程序流是如何从这个JavaScript的exec函数进入到Android平台的原生API执行呢?
打开PackagedApp文件夹里的android子文件夹,有一个JavaScript文件:cordova.js:
里面能看到函数exec的定义和实现:
进而去查看androidExec函数的实现细节:
第938行:var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
第943行的五个参数含义:
success, fail, service, action, args
- success & fail: JavaScript回调函数,当移动平台上的Java原生API执行完毕后,这个JavaScript回调函数会被调用到。
- service: 待执行的Java Native API的Java实现类名称。
- action: 待执行的Java Native API的Java实现类的方法名称。
- args: JavaScript传递给Java native API的参数数组。
2. 在安卓平台上,JavaScript调用Java的技术实现方式有两种:定义在下图JavaScript代码中的jsToNativeModes对象中:PROMPT和JS_OBJECT。相对应的,Java调用JavaScript有三种模式:POLLING, LOAD_URL和ONLINE_EVENT:
看下面这段Java代码,暴露了一个方法getSomeString给JavaScript端消费:
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class WebViewGUI extends Activity {
WebView mWebView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWebView = new WebView(this);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JavaScriptInterface(),
"jsinterface");
mWebView.loadUrl("file:///android_asset/www/index.html");
setContentView(mWebView);
}
final class JavaScriptInterface {
JavaScriptInterface() {
}
public String getSomeString() {
return "string";
}
}
}
在JavaScript代码里消费上述Java代码暴露的getSomeString方法:
<script>
var String = window.jsinterface.getSomeString();
</script>
我们再回过头来看看AndroidExec的实现:
var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
在AndroidExec的实现里, nativeApiProvider的get方法返回一个实例,然后执行exec方法。而881行代码说明nativeApiProvider的实现位于文件夹cordova/android下面的nativeapiprovider.js里:
打开nativeapiprovider.js,在第21行的注释里我们得到了重要信息: currentApi要么来自Java文件ExposedJsApi.java,要么来自PromptBasedNativeApi.java。
Java文件ExposedJsApi.java可以在这个文件夹内找到:
platform/android/CordovaLib/src/org/apache/cordova
ExposedJsApi实际就是个Java interface,上面声明了一个exec方法:
JavaScript到Java的执行通过prompt调用完成:
Java类SystemExposedJsApi实现了这个interface,再将执行流转交给类CordovaBridge的实例.
CordovaBridge再调用PluginManager:
PluginManager首先根据名字找到负责处理该请求的Java plugin的实现类,再调用该实现类的方法:
以OData离线存储的实现类为例,我们在其实现代码里能发现有大量的IF-ELSE分支,每个分支处理不同的离线存储操作请求。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:


Cordova插件中JavaScript代码与Java的交互细节介绍的更多相关文章
- Cordova应用的JavaScript代码和自定义插件代码的调试
我之前写过三篇Cordova相关的技术文章.当我们使用Cordova将自己开发的前端应用打包安装到手机上后,可能会遇到需要调试Cordova应用的时候. 本文就介绍Cordova应用的调试步骤. 如果 ...
- silverlight 中javascript 代码与托管代码的互调用 以及一些思考
silverlight 客户端javascript 代码与托管代码的互调用时比较用意义的同时,因为silverlight本身就是一个插件,如果两者之间不能进行相互的调用,对于web 上的一些特殊的功能 ...
- Grunt 使用(二)uglify插件压缩javascript代码
本文在配置grunt基本环境的基础下,讲解如何使用grunt-contrib-uglify进行javascript压缩 本文只介绍了grunt-contrib-uglify插件的一种压缩方式适用于大部 ...
- Webview 中 Javascript 无法调用 Java 对象
[问题产生] Webview 通过 addjavascriptInterface 传递对象给前端,一切正常.但是 Android官方已提醒此功能是有安全风险,改用 safe-java-js-webvi ...
- jni中c代码调用java代码
原理是使用反射的机制 java中反射的例子: Class<?> forName = Class.forName("com.example.ndkcallback.DataProv ...
- ionic使用cordova插件中的Screenshot截图分享功能
需要实现操作,考试完成后需要将成绩生成一张图片,分享出去, import { Screenshot } from '@ionic-native/screenshot'; constructor(pri ...
- JavaScript翻译成Java
这两天公司有一个需求,将一段加密的JavaScript代码转换为JAVA版. JavaScript中的某一段代码: 前期查看了整个JavaScript代码,发现代码中,方法里面嵌套方法,各种不合规的变 ...
- 使用Bootstrap的popover标签中嵌入插件,并且为插件注册事件实现Ajax与后台交互
下午研究了一下bootstrap的popover写了个例子.如果项目很多地方都需要用到可以考虑封装成插件. javascript代码: <script type="text/javas ...
- 由闭包引起的对javascript代码可维护性的思考
在最近的编程实践中由闭包的使用引起了我对javascript代码可维护性的思考.面向对象的其中一个特性封装性通过封装可以降低类与类之间或模块与模块之间耦合性从而使我们的设计更加高内聚低耦合,在大规模的 ...
随机推荐
- 【转】C/C++使用心得:enum与int的相互转换
https://blog.csdn.net/lihao21/article/details/6825722 如何正确理解enum类型? 例如: enum Color { red, white, blu ...
- Hadoop 源代码组织结构
Hadoop 2.X 包括 编译好的可以直接部署的文件hadoop-{VERSION}.tar.gz; 还有源代码文件hadoop-{VERSION}-src.tar.gz , 需要 Maven 编译 ...
- ASP.NET Core MVC 2.x 全面教程_汇总贴
Reshaper快捷键盘 快速生成属性:prop Ctrl+. ASP.NET Core MVC 2.x 全面教程:https://www.bilibili.com/video/av38392956 ...
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">详解
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Cpython 解释器下实现并发编程
背景知识: 顾明思议: 进程即正在执行的一个过程,进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统, 是操作系统最核心的概念,也是操作系统提供的最古老的最重要的抽象概念之一.操作系统的其他所 ...
- HTML学习笔记(三)样式CSS
1.样式 外部样式表(通过css文件定义样式,整体样式) 当样式需要被应用到很多页面的时候,使用外部样式表,在 head 部分<link>. <head> <link r ...
- Lightoj 1147【DP】
题意: 把n个人分成两部分,要你怎么分使得两部分尽可能相等: 思路: 如果我们把一部分人的重量达到离sum/2最近,那就一定行啊 其实就是一条棒,两种不同的棒去拼接成一条棒,然后最好就是离mid最近, ...
- C# interface 的特性 无法被implement class继承
最近做interface添加特性后,implement class 无法继承. 微软要求class是实现Interface而不是继承,所以我们必须手动添加特性,而不能自动继承. 对于abstract ...
- CSS优先级、CSS选择器、编写CSS时的注意事项
CSS的优先级: 内嵌样式>ID选择器>类选择器>标签选择器 内部样式>内部样式>外部样式 CSS的选择器: 选择器:在 CSS 中,选择器是一种模式,用于选择需要添加样 ...
- UVA10140 Prime Distance【素数/数论】By cellur925
题目传送门 我们注意到,L,R是肥肠大的.........我们不可能在1s内筛出2^31内的全部质数. “上帝为你关上一扇门,同时为你打开一扇窗” 我们又注意到,R-L是肥肠比较小的,珂以从这入手解决 ...