在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的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

最新文章

  1. ASP.NET MVC 提示there was error getting the type的解决方法
  2. MYSQL管理之主从同步管理
  3. Servlet分页技术
  4. 关于scut使用WebService
  5. [Javascript] Maybe Functor
  6. [lua]尝试一种Case语法糖
  7. 5.4.3 RegExp构造函数属性
  8. SVN 1.8.x 服务器安装(转)
  9. 用 node.js 创建第一个Hello World
  10. Node.js 8有哪些重要功能和修复?
  11. PPT在HTML网页上播放方法
  12. 由浅入深的讲述Get和Post的区别
  13. cookie跨域共享
  14. Android的Launcher启动流程 “Launcher部分启动流程”
  15. python3 urllib.parse 常用函数
  16. es6中的部分新特性
  17. Bootstrap 框架 day57
  18. OpenGL笔记(四) API参考
  19. BT601. BT709色彩空间
  20. 基于MATLAB的均值滤波算法实现

热门文章

  1. .after()和.before()的关系
  2. UVa 10214 Trees in a Wood. (数论-欧拉函数)
  3. java 中判断字符串相等
  4. 《剑指offer》面试题13—O(1)时间删除链表结点
  5. 201621123016 《Java程序设计》第十二周学习总结
  6. 51nod1212【最小生成树kruskal算法】
  7. IT兄弟连 JavaWeb教程 JSTL标签的使用
  8. C# 正则表达式输出查询结果
  9. 解决DDOS攻击生产案例
  10. bzoj4472:[Jsoi2015]salesman