Apache Cordova-Android框架原理研究笔记 I

来源:互联网 发布:汽车工业的重要性 知乎 编辑:程序博客网 时间:2024/06/05 02:02

由于工作原因,笔者对于所谓的Hybrid、Webpp开发模式产生了浓厚的兴趣。老习惯,笔者对于Apache Cordova(PhoneGap)框架进行了一番研究,小有收获,特此记录下来。

先看一张图,这是官网上对于Cordova总体框架架构的描述: 
Cordova总体架构 
第一部分:Cordova Application是Cordova框架独立于不同手机操作系统的一个封装层。具体包括 
1)Web app(包括具体的app的HTML/JS/CSS代码等); 
2)Cordova框架已经封装好的核心插件(如相机、存储等系统调用),这块是Cordova的核心部分。当然,开发者也可以基于它的插件体系,扩展出新的插件; 
第二部分:Mobile OS就是具体的手机操作系统层了,Cordova目前支持大部分的手机OS:iOS、Android、wp、blackberry等等; 
这张图可以让我们一目了然的了解Cordova框架总体的技术架构。实际上我们可以这么理解所谓的“跨平台”: 
Cordova预先帮我们预先封装了各种mobile os上最常用的本地api调用,然后以统一的JavaScript api形式提供给webapp开发者调用。(注:cordova还提供另外一种Hybird即混合开发模式,这个后面有时间再说。)对于webapp的开发者来说,无需关注系统底层调用实现细节,也就实现了所谓的“跨平台”。实际上,各平台涉及到本地能力的调用,以插件形式被封装了。(每个插件的实现实际上还是Native模式)。

笔者比较感兴趣的一点是JS和Native是如何实现互调的(各平台有差别,这里先研究Android的,重点是JS如何实现对于Native的调用),网上实际上有比较多的文章在解释这些,看下来感觉总不是太清晰,于是乎,你懂的,我直接对着github上Cordova-Android源码来了一番研究。

先把研究的结果共享出来:Cordova-Android是通过addJavascriptInterface(Android Webview的API)和JS Prompt这两种方式来实现JS对于Native API的调用。

具体介绍这两种方式前,我们先来看一个Cordova-Android框架中的一个关键类:CordovaActivity.java。 
该类继承了Android Activty类,实际上是Cordova-Android的Launcher Activity,也就是启动入口activity。我们通过一张图来描述下它干了哪些事: 
CordovaActivity调用时序图
应用启动后,核心干了两件事:读取config.xml和loadUrl。这个loadUrl实际上就是加载webapp的启动页(默认是index.html)

addJavascriptInterface方式: 
addJavascriptInterface方式时序图
看了上面的图,再看下其中的一个核心类的代码,就啥都明白啦。 
SystemExposedJsApi.java 
我们直接看代码,很短:

/*       Licensed to the Apache Software Foundation (ASF) under one       or more contributor license agreements.  See the NOTICE file       distributed with this work for additional information       regarding copyright ownership.  The ASF licenses this file       to you under the Apache License, Version 2.0 (the       "License"); you may not use this file except in compliance       with the License.  You may obtain a copy of the License at         http://www.apache.org/licenses/LICENSE-2.0       Unless required by applicable law or agreed to in writing,       software distributed under the License is distributed on an       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       KIND, either express or implied.  See the License for the       specific language governing permissions and limitations       under the License.*/package org.apache.cordova.engine;import android.webkit.JavascriptInterface;import org.apache.cordova.CordovaBridge;import org.apache.cordova.ExposedJsApi;import org.json.JSONException;/** * Contains APIs that the JS can call. All functions in here should also have * an equivalent entry in CordovaChromeClient.java, and be added to * cordova-js/lib/android/plugin/android/promptbasednativeapi.js */class SystemExposedJsApi implements ExposedJsApi {    private final CordovaBridge bridge;    SystemExposedJsApi(CordovaBridge bridge) {        this.bridge = bridge;    }    @JavascriptInterface    public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {        return bridge.jsExec(bridgeSecret, service, action, callbackId, arguments);    }    @JavascriptInterface    public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {        bridge.jsSetNativeToJsBridgeMode(bridgeSecret, value);    }    @JavascriptInterface    public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {        return bridge.jsRetrieveJsMessages(bridgeSecret, fromOnlineEvent);    }}

@JavascriptInterface暴露方法给JS,这里的exec接口方法实际上就实现了从JS到Native调用的“桥”。

至此,我们对于addJavscriptInterface这种方式的调用过程就搞清楚了。对于JS Prompt这种方式,原理上大同小异。实际上Cordova在SystemWebChromeClient.java这个类中重载了OnJsPrompt方法。实际的调用过程如下:webapp->prompt()->OnJsPrompt()->Native()。

0 0