[转] Android PhoneGap Cordova 体系结构
说明:
本文档只针对Cordova(PhoneGap)的Android端,基于Cordova2.1.0版本。
一.总体结构
Cordova的目标是用HTML,JS,来完成手机客户端的开发,并且是只开发一次可以在各种手机平台上跑,所以理想状态是用JS去控制所有事件。Cordova基于WebView组件。每个继承自DroidGap的Activity对应一个独立的CordovaWebView。Cordova提供了一些列的JS接口来访问Android的native(详细参见http://docs.phonegap.com/en/2.1.0/)。以插件(Plugin)的形式提供自定义接口给JS端访问。
二.一些疑问
1. Cordova框架是如何启动的?
2. 插件是怎么回事?如何工作的。
3. Cordova的官方文档都是说JS如何访问Android的native,那么在Android的native中是否可以访问JS的函数?如何访问?
三.结构解剖
1.Cordova的启动
1、 如何启动
Cordova提供了一个Class(DroidGap)和一个interface(CordovaInterface)来让Android开发者开发Cordova。一般情况下实现DroidGap即可,因为DroidGap类已经做了很多准备工作,可以说DroidGap类是Cordova框架的一个重要部分;如果在必要的情况下实现CordovaInterface接口,那么这个类中很多DroidGap的功能需要自己去实现。
继承了DroidGap或者CordovaInterface的Activity就是一个独立的Cordova模块,独立的Cordova模块指的是每个实现了DroidGap或者CordovaInterface接口的Activity都对应一套独立的WebView,Plugin,PluginManager,没有共享的。(我觉得这样是很不爽的,没有共享,如果plugin和Activity很多的情况下这样是相当的耗资源)
当在实现了DroidGap或者CordovaInterface接口的Activity的onCreate方法中调用DroidGap的loadUrl方法即启动了Cordova框架。
2、启动过程
public class A extends DroidGap{}
a. 在A的onCreate方法中首先调用super. onCreate(),
这一步中创建了一个LinearLayout(LinearLayoutSoftKeyboardDetect.class)布局,以及计算这个Layout的大小及显示的一些方式。在后面的过程中会将一个WebView加到这个LinearLayout中。
b. 再次调用DroidGap 的loadUrl()方法
DroidGap. loadUrl()中首先判断A的CordovaWebView是否实例化,如果没有回实例化一个CordovaWebView对象并将该对象添加到父LinearLayout中去,同时将该LinearLayout添加的ContentView。见以下代码:
public void onCreate(Bundle savedInstanceState) {
…
root = new LinearLayoutSoftKeyboardDetect(this, width, height);
…
}
public void init() {
CordovaWebView webView = new CordovaWebView(DroidGap.this);
this.init(webView,
new CordovaWebViewClient(this, webView),
new CordovaChromeClient(this, webView));
}
public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) {
this.appView = webView;
this.appView.setId(100);
…
this.root.addView(this.appView);
setContentView(this.root);
}
public void loadUrl(String url) {
if (this.appView == null) {
this.init();
}
…
}
这样就完成了我们在一般开发中使用的模式:
public void onCreate(Bundle savedInstanceState) {
super. onCreate(Bundle savedInstanceState);
setContentView(resID);
…
}
在初始化完CordovaWebView后调用CordovaWebView.loadUrl()。此时完成Cordova的启动。
c. 在实例化CordovaWebView的时候, CordovaWebView对象会去创建一个属于当前CordovaWebView对象的插件管理器PluginManager对象,一个消息队列NativeToJsMessageQueue对象,一个JavascriptInterface对象ExposedJsApi,并将ExposedJsApi对象添加到CordovaWebView中,JavascriptInterface名字为:_cordovaNative。
d. Cordova的JavascriptInterface
在创建ExposedJsApi时需要CordovaWebView的PluginManager对象和NativeToJsMessageQueue对象。因为所有的JS端与Android native代码交互都是通过ExposedJsApi对象的exec方法。在exec方法中执行PluginManager的exec方法,PluginManager去查找具体的Plugin并实例化然后再执行Plugin的execute方法,并根据同步标识判断是同步返回给JS消息还是异步。由NativeToJsMessageQueue统一管理返回给JS的消息。
e. 何时加载Plugin,如何加载
Cordova在启动每个Activity的时候都会将配置文件中的所有plugin加载到PluginManager。那么是什么时候将这些plugin加载到PluginManager的呢?在b中说了最后会调用CordovaWebView.loadUrl(),对,就在这个时候会去初始化PluginManager并加载plugin。PluginManager在加载plugin的时候并不是马上实例化plugin对象,而是只是将plugin的Class名字保存到一个hashmap中,用service名字作为key值。
当JS端通过JavascriptInterface接口的ExposedJsApi对象请求Android时,PluginManager会从hashmap中查找到plugin,如果该plugin还未实例化,利用java反射机制实例化该plugin,并执行plugin的execute方法。
2.Cordova插件
在『1』中已经接触了些Cordova插件的东西,这里总结下Cordova的插件
Cordova插件只是一个普通的java类,没有什么特殊之处。插件中的execute方法只是Cordova框架的一个规定。
Cordova为了方便于插件的管理,所以引进了一个PluginManager来管理插件。在ExposedJsApi中,PluginManager起一个代理作用。
在原生态的WebView开发中,我们可以给WebView添加一个JavascriptInterface对象来使JS可以访问android的代码;在Cordova也有一个这样的对象ExposedJsApi。
在ExposedJsApi中,它将请求转发给我们的PluginManager,这个时候PluginManager会根据给的service的名字来查找具体的Plugin并执行。
所以,我认为Cordova插件是android端的API,提供给JS。
在Cordova虽然有JavascriptInterface对象ExposedJsApi,但在JS端并不是真正通过android提供的window.JavascriptInterface.request这种方式来请求。在JS端,Cordova是通过JS的prompt()函数触发ChromeClient中的onJsPrompt方法,通过onJsPrompt去获取到请求,再将请求转发给ExposedJsApi。
注:在Cordova中,Java端和JavaScript端都准备了代码来使用特殊URL('http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;)的方式交互请求,但并没有真正使用。
3.Cordova的数据返回
Cordova中通过exec()函数请求android插件,数据的返回可同步也可以异步于exec()函数的请求。
在开发android插件的时候可以重写public boolean isSynch(String action)方法来决定是同步还是异步。
Cordova在android端使用了一个队列(NativeToJsMessageQueue)来专门管理返回给JS的数据。
1、同步
Cordova在执行完exec()后,android会马上返回数据,但不一定就是该次请求的数据,可能是前面某次请求的数据;因为当exec()请求的插件是允许同步返回数据的情况下,Cordova也是从NativeToJsMessageQueue队列头pop头数据并返回。然后再根据callbackID反向查找某个JS请求,并将数据返回给该请求的success函数。
2、异步
Cordova在执行完exec()后并不会同步得到一个返回数据。Cordova在执行exec()的同时启动了一个XMLHttpRequest对象方式或者prompt()函数方式的循环函数来不停的去获取NativeToJsMessageQueue队列中的数据,并根据callbackID反向查找到相对应的JS请求,并将该数据交给success函数。
注:Cordova对本地的HTML文件(file:// 开头的URL)或者手机设置有代理的情况下使用XMLHttpRequest方式获取返回数据,其他则使用prompt()函数方式获取返回数据。
4.Android代码访问JS
翻了Cordova的官方文档和Cordova代码,发现Cordova并未提供一种方式来让我们在Android中去访问JS。现在想来可能是这样的道理(个人观点),因为Cordova框架的性质就是一个用HTML+JS来开发APP的,相当于java用的虚拟机层(比喻不是很恰当),所以Cordova未提供Android访问JS的方式。
如果需要Android访问JS,只有使用原生态WebView开发的方式
loadUrl(“javascript:xxx”)
因为在Cordova框架中需要访问JS的时候也是使用的这种方式,如下(Activity的onResume事件):
public void handleResume(boolean keepRunning, boolean activityResultKeepRunning)
{ // Send resume event to JavaScript
this.loadUrl("javascript:try{cordova.fireDocumentEvent('resume');}catch(e){console.log('exception firing resume event from native');};"); // Forward to plugins
if (this.pluginManager != null) {
this.pluginManager.onResume(keepRunning);
} // Resume JavaScript timers (including setInterval)
this.resumeTimers();
paused = false;
}
不正确之处请各位指正。
转自:
http://my.oschina.net/tonywolf/blog
[转] Android PhoneGap Cordova 体系结构的更多相关文章
- [Phonegap+Sencha Touch] 移动开发36 Phonegap/Cordova项目的图标和启动画面(splashscreen)配置
原文地址:http://blog.csdn.net/lovelyelfpop/article/details/40780111 Phonegap/Cordova项目中的config.xml文件.里面配 ...
- 如何安装 PhoneGap / Cordova (for Win10)
最近需要配置 PhoneGap / Cordova 环境,折腾了一阵子,写篇博客 Mark 一下整个过程. 具体参照了:http://www.assortedgarbage.com/apigee/ 以 ...
- PhoneGap+Cordova+SenchaTouch-01-环境搭建
转http://my.oschina.net/zhongwenhao/blog/369465 环境搭建基于 windows ,mac系统可以借鉴 1.安装NodeJS 和ruby http://no ...
- 跨平台移动开发phonegap/cordova 3.3全系列教程-helloworld
1. 建立专案(cordova) 打开cmd命令行 cordova create ACESMobile aces.mobile ACES cd aces mobile 如图 2. 安装插件 ...
- 跨平台移动开发phonegap/cordova 3.3全系列教程-目录
目录(更新完成后会附上源码供参考) 第一章 android平台开发 phonegap/cordova简介 1.开发环境搭建 2.helloworld 3.启动画面 4.结合asp.net/jqmboi ...
- phonegap+cordova+ionic调用原生API
上一篇博客讲了phonegap+cordova+ionic的环境搭建,今天再来分享一篇cordova调用原生API的文章.从技术角度上来讲,这并不是很难,只是有些细节要是没有注意,或者某些步骤不知道的 ...
- WINDOWS下PhoneGap(Cordova)安装笔记
1.首先下载Node.js 安装nodejs很简单直接点击安装文件下一步直至成功即可,安装notejs的同时npm也会同时安装 成功后打开notejs的命令行工具 输入“node -v”," ...
- Android的系统体系结构
目录: Android的系统体系结构 Android的四种常用组件 Activity的启动流程 Android的系统体系结构 在入门了一个简单的Android的Hello World以后,我们首先来看 ...
- phonegap/cordova常用命令
创建项目 cordova create foldername com.wps.test projectName cd foldername 基本设备信息 设备 API: cordova plugin ...
随机推荐
- WPF打印原理,自定义打印
一.基础知识 1.System.Printing命名空间 我们可以先看一下System.Printing命名空间,东西其实很多,功能也非常强大,可以说能够控制打印的每一个细节,曾经对PrintDial ...
- iOS——浅谈iOS中三种生成随机数方法
ios 有如下三种随机数方法:
- Jenkins进阶系列之——16一个完整的JENKINS下的ANT BUILD.XML文件
网上看见的,确实很全,该有的基本都覆盖到了.自己拿来稍微改改就可以用了. 注:property中的value是你自己的一些本地变量.需要改成自己的 <?xml version="1.0 ...
- javascript模块化详解
模块化:每个模块只完成一个独立的功能,然后提供该功能的接口.模块间通过接口访问.模块中的(过程和数据)对于其它模块来说是私有的(不能访问修改) 原始人写法: function m1(){ //... ...
- 【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历
背景 最近收到这样一个问题: Storm处理消息时会根据Topology生成一棵消息树,Storm如何跟踪每个消息.如何保证消息不丢失以及如何实现重发消息机制? 虽已回复,但心想还是看下storm这块 ...
- JavaScript基础2---控制权DOM操作
文档对象模型DOM(Document Object Model)定义访问和处理HTML文档的标准方法.DOM将HTML文档呈现为带有元素,属性和文本的树结构(节点树). HTML文档可以说由节点构成的 ...
- Koala Framework是什么?我为什么要写这个框架?
当时的监管组,技术力量累积的很少,还在直连DB,使用着DataTable.DataSet作为数据的承载,监管是公司最近几年主推的项目,所以领导们决定进行重要调整. 初来乍到 由于之前没有任何的技术积累 ...
- [BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1295 分析:很巧妙的一道spfa从搜索的角度是搜索在所有1中搜索删除哪T个1,对整个图询问,这 ...
- WCF 入门(25,26,27,28)
前言 项目赶时间,工期紧,熬过这段时间应该就好了吧.希望如此. 今天把自己那部分写的差不多了,回来和小伙伴一起又看了一遍<夏洛特烦恼>,还挺好看的,明天继续加班,do it. 第25-28 ...
- 第四十一课:CSS3 animation详解
animation是css3的另一个重要的模块,它成型比transition晚,吸取了Flash的关键帧的理念,实用性高. animation是一个复合样式,它可以细分为8个更细的样式. (1)ani ...