在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的交互细节介绍相关推荐

  1. Cordova应用的JavaScript代码和自定义插件代码的调试

    我之前写过三篇Cordova相关的技术文章.当我们使用Cordova将自己开发的前端应用打包安装到手机上后,可能会遇到需要调试Cordova应用的时候. 本文就介绍Cordova应用的调试步骤. 如果 ...

  2. java如何调用网页_如何使用网页开发自己的app,在网页中的按钮与自己的java代码绑定来实现打电话即javascript代码调用java代码,和java代码来调用javascript代码...

    1首先是如何在自己的app里用网页显示,这样可以较快的更新界面而不需要让客户端升级,方法如下: xml文件: android:layout_width="fill_parent" ...

  3. silverlight 中javascript 代码与托管代码的互调用 以及一些思考

    silverlight 客户端javascript 代码与托管代码的互调用时比较用意义的同时,因为silverlight本身就是一个插件,如果两者之间不能进行相互的调用,对于web 上的一些特殊的功能 ...

  4. 利用unity和steamVR完成场景漫游(二) 关于steamVR插件中的代码详解

    1.SteamVR.cs 单例管理类,管理SteamVR程序的运行和终止. 2.SteamVR_Camera.cs 给场景添加一个最基本可运行的SteamVR组. 3.SteamVR_CameraFl ...

  5. Android插件中使用EventBus出现java.lang.IllegalArgumentException: Expected receiver of type xxx, but got xx

    使用场景 由于所开发的Android项目是个老项目,EventBus使用的还是EventBus2,整个项目是插件化架构,不同插件使用的ClassLoader不同.插件1中有个onEvent方法,用来更 ...

  6. 网页中Javascript代码的应用方式

    Javascript加入网页有两种方法: 1.直接加入HTML文档 这是最常用的方法,大部分含有Javascript的网页都采用这种方法,如: <script language="Ja ...

  7. android 表格xml,【Android】利用表格布局,Android中xml文件与java的交互制作登录界面...

    登录界面是图形编程.网页编程的一个经典而又基础的程序. 在安卓中,如图所示一个基本登录界面: 点击取消按钮就关闭这个程序,点击登录按钮则显示用户输入的用户名与密码. 一.基本布局 这个程序利用到安卓中 ...

  8. Zed-Unity插件中代码注释——ZEDManager.cs

    文章目录 Zed Unity 插件中的代码注释 引言 ZEDManager.cs Zed Unity 插件中的代码注释 引言 Zed真是一个精品商品,提供的api的解释真的很齐全. 代码的可读性很高. ...

  9. mvc中js是如何调用HTML的,MVC中javascript直接调用Model

    最近做一个统计页面, Model从后台已经获取了数据集合,想直接在前台展示,而这个展示是需要用js生成图表的. 控制器部分代码: public ActionResult Index() { var m ...

最新文章

  1. python字典程序题_python字典练习题
  2. 进程通信学习笔记(Posix消息队列)
  3. 如何在属性面板中增加一个属性-UI界面编辑器(XproerUI)教程
  4. MySQL千万级数据JDBC插入
  5. 查看数据库系统字符集
  6. latex表格名的引用问题
  7. jeecg开源社区第12期架构学习班开始报名了
  8. 关于映射的一些理解与常见命题
  9. 语言迭代发_从今天开始,每天学点R语言~
  10. [转]Yii Framework: 从 model 中生成 select option
  11. chrome session丢失_为什么还是由这么多人搞不懂Cookie、Session、Token?
  12. Android Storage Manager
  13. Linux 常用命令 Updating
  14. 关于BUCK降压的一些学习笔记2-->滞回比较器产生三角波
  15. 生成html水印,兼容ie8,ie兼容性问题与解决办法,移动端水印给出的建议
  16. android 免root冻结,自冻FreezeYou(超强免ROOT冻结神器)
  17. 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决
  18. 中国女排世界排名跌至第二,为何排名下跌?郎平这样回答
  19. 给孩子吃鸡蛋的五大误区
  20. 两个ListView实现的Android点餐页面

热门文章

  1. /bin/bash^M: bad interpreter: 没有那个文件或目录
  2. WebAPI(part1)--API及DOM
  3. abs int 宏定义_在标准C中,预处理语句,特别是宏定义中,常常出现'#'和'##'符号,#字符串创建运算符#...
  4. HTML 按钮(button)的 disable 属性和 disable property
  5. SAP 电商云 Spartacus UI Angular Component 动态创建的单步调试
  6. 一个用于 Angular 开发的 Chrome 扩展 - Angular Dev Tools
  7. SAP Fiori Elements List Report table 里的普通按钮,Global 按钮 和 Determining 按钮
  8. SAP Spartacus 2.1.0 加载homepage的逻辑
  9. 如何从ngrx-store-devtools.js里找到actions的触发源头
  10. Scala println的实现原理调试