您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
Cordova android框架详解
 
作者:随机 来源:博客园 发布于 2015-6-23
   次浏览      
 

一、Cordova 核心java类说明

CordovaActivity:Cordova Activity入口,已实现PluginManager、WebView的相关初始化工作, 只需继承CordovaActivity实现自己的业务需求。

PluginManager: 插件管理器

ExposedJsApi :javascript调用Native, 通过插件管理器PluginManager 根据service找到具体实现类。

NativeToJsMessageQueue:Native调用javascript,主要包括三种方式:loadUrl 、 轮询、反射WebViewCore执行js

二、 Cordova框架类图

三、Cordova框架启动

当实现了DroidGap或者CordovaInterface接口的Activity的onCreate方法中调用DroidGap的loadUrl方法即启动了Cordova框架。

Cordova提供了一个Class(DroidGap extends CordovaActivity)和一个interface(CordovaInterface)来让Android开发者开发Cordova。

一般情况下实现DroidGap即可,因为DroidGap类已经做了很多准备工作,可以说DroidGap类是Cordova框架的一个重要部分;如果在必要的情况下实现CordovaInterface接口,那么这个类中很多DroidGap的功能需要自己去实现。继承了DroidGap或者CordovaInterface的Activity就是一个独立的Cordova模块,独立的Cordova模块指的是每个实现了DroidGap或者CordovaInterface接口的Activity都对应一套独立的WebView,Plugin,PluginManager,没有共享的。

在初始化完CordovaWebView后调用CordovaWebView.loadUrl()。此时完成Cordova的启动。

1.Cordova关联对象初始化

在实例化CordovaWebView的时候, CordovaWebView对象会去创建一个属于当前CordovaWebView对象的插件管理器PluginManager对象,一个消息队列NativeToJsMessageQueue对象,一个JavascriptInterface对象ExposedJsApi,并将ExposedJsApi对象添加到CordovaWebView中,JavascriptInterface名字为:_cordovaNative。

2. Cordova的JavascriptInterface

在创建ExposedJsApi时需要CordovaWebView的PluginManager对象和NativeToJsMessageQueue对象。因为所有的JS端与Android native代码交互都是通过ExposedJsApi对象的exec方法。在exec方法中执行PluginManager的exec方法,PluginManager去查找具体的Plugin并实例化然后再执行Plugin的execute方法,并根据同步标识判断是同步返回给JS消息还是异步。由NativeToJsMessageQueue统一管理返回给JS的消息。

3. 何时加载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方法。

4.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()函数方式获取返回数据。

5、webView.sendJavascript 发送到js队列,onNativeToJsMessageAvailable 负责执行js.

Native 调用 JS 执行方式有三种实现 LoadUrlBridgeMode、 OnlineEventsBridgeMode、PrivateApiBridgeMode

1、webView.sendJavascript 发送js方法到JS队列

2、onJsPrompt 方法拦截,获取调用方式

》》如果是gap_bridge_mode,则执行 appView.exposedJsApi.setNativeToJsBridgeMode(Integer.parseInt(message));

》》如果是gap_poll, 则执行 appView.exposedJsApi.retrieveJsMessages("1".equals(message));

3、调用setBridgeMode 方法调用onNativeToJsMessageAvailable 执行javascript调用

四、Native调用javascript 方式:NativeToJsMessageQueue

1、loadUrl javascript 调用方式

private class LoadUrlBridgeMode extends BridgeMode

if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) {
}

2、Navitive事件通知javascript轮询获取Navitive数据

private class OnlineEventsBridgeMode extends BridgeMode

3、通过Java反射获取webview 的sendMessage 方法执行js, 支持 Android 3.2.4之上(包含)

---可以解决loadUrl 隐藏键盘的问题:当你的焦点在输入,如果这通过loadUrl调用js,会导致键盘隐藏

private class PrivateApiBridgeMode extends BridgeMode

 

    Field f = webViewClass.getDeclaredField("mProvider");

    f.setAccessible(true);

    webViewObject = f.get(webView);

    webViewClass = webViewObject.getClass();

 

    Field f = webViewClass.getDeclaredField("mWebViewCore");

    f.setAccessible(true);

    webViewCore = f.get(webViewObject);

 

   if (webViewCore != null) {

        sendMessageMethod =       webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class);

       sendMessageMethod.setAccessible(true);   

    }

 

     Message execJsMessage = Message.obtain(null, EXECUTE_JS, url);

     sendMessageMethod.invoke(webViewCore, execJsMessage);

4、Native注册javascript接口 _cordovaNative

boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT
 <= Build.VERSION_CODES.HONEYCOMB_MR2);

// Bug being that Java Strings do not get converted to JS strings automatically.
This isn't hard to work-around on the JS side, but it's easier to just use the prompt bridge instead.

if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {

Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");

return; 

} else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {

// addJavascriptInterface crashes on the 2.3 emulator.

Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");

return;

}

this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
   
次浏览       
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新活动计划
软件架构设计方法、案例与实践 8-23[特惠]
Linux内核编程及设备驱动 8-15[北京]
Python、数据分析与机器学习 8-23[特惠]
嵌入式软件架构设计 8-22[线上]
QT应用开发 9-5[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   

Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合

领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...