cordova开发介绍(android平台)

来源:互联网 发布:pmc编程 编辑:程序博客网 时间:2024/05/22 01:42

转载请注明出处:http://blog.csdn.net/sproll

本文内容主要取材自cordova在线文档及网络上的资料。

1. cordova介绍

1.1. cordova历史

CordovaPhoneGap贡献给Apache后的开源项目,是从 PhoneGap中抽离出的核心代码,是驱动PhoneGap的核心引擎。有点类似WebkitGoogle Chrome的关系。渊源就是:早在201110月,Adobe收购了Nitobi Software和它的PhoneGap产品,然后宣布这个移动Web开发框架将会继续开源,并把它提交到Apache Incubator,以便完全接受ASF的管治。当然,由于Adobe拥有了PhoneGap商标,所以开源组织的这个PhoneGap v2.0版产品就更名为Apache Cordova

1.2. cordova功能

Apache Cordova是一个开源的移动开发框架,它支持使用标准的Web开发技术(HTML5CSS3JavaScript)开发跨平台的移动端应用。如果需要访问各平台本地化的功能,如摄像头、网络、传感器……,可以通过使用插件(plugin)来完成。

1.3. cordova架构

cordova架构示意图如下:

 

 

Web App层是开发人员编写代码的主要地方,应用程序以网页的形式呈现,在一个index.html的本地页面文件中引用所需要的各种Web资源,如CSSJavaScript、图像、影音文件等。应用程序的配置保存在config.xml文件中。

WebView层用来呈现用户界面,即web页面的展现。例如,在android平台是通过WebView控件实现web页面的呈现。

Plugins主要用于在JavaScript代码中调用各平台native的功能。Cordova项目已经包含一些核心的plugin,如电池、摄像头、通讯录等。开发人员也可以开发自定义的plugin,来实现所需要的功能。

1.4. cordova app的两种开发方式

1.4.1. Cross-platform (CLI) workflow

如果需要让应用运行于尽可能多的移动平台,则选择该方式。在这种方式下,cordova提供一些高级的工具去创建工程,而较少去考虑各平台的差异性。

1.4.2. Platform-centered workflow

如果要为某个平台定制应用,并且修改底层功能,则选择该方式。

1.5. 平台和插件支持

 


 

2. cordova开发环境

cordova命令行工具以npm包方式发布,安装过程如下:

2.1. 安装node.js

在其主页下载匹配的安装包:www.nodejs.org,并安装。

2.2. 安装cordova

linux或者OS X平台使用以下命令安装:

$ sudo npm install -g cordova

windows平台使用以下命令安装:

C:\>npm install -g cordova

 

-g参数表示全局安装,否则仅安装在当前目录。

2.3. 创建工程

进入所需建立工程的目录,运行命令:

$ cordova create hello com.example.hello HelloWorld

hello:工程目录的名称

com.example.hello:工程id

HelloWorld:工程名称

 

工程目录hello下的各个子目录如下:

├── platforms:各平台的工程目录,cordova编译工程时会将其覆盖

 |            ├── android

 |            ├── ios

 |            └── ...

├── merges:各平台的定制文件,该目录下的文件将覆盖www目录下的相同文件

 |            ├── android

 |            ├── ios

 |            └── ...

├── plugins:当前工程添加的各个plugin的目录

 |            ├── org.apache.cordova.device

 |            └── ...

├── www:主要的工程开发目录

 |            ├──  css

 |            ├──  img

 |            ├──  js

 |            ├──  index.html

└── config.xml:主要的工程配置文件

2.4. 添加移动平台

进入hello目录,运行命令:

$ cordova platform add android

该命令将在platforms目录下,自动生成android平台的工程。

也可以用以下命令删除已添加的平台工程:

$ cordova platform remove android

以下命令查看添加了哪些平台:

$ cordova platform list

2.5. 编译工程

以下命令编译cordova工程:

$ cordova build

也可以单独编译一个平台的工程:

$ cordova build android

2.6. 运行工程

android平台,以下命令运行模拟器:

$ cordova emulate android

模拟器运行后,以下命令测试工程:

$ cordova run android

2.7. 添加插件

cordova plugin可以在以下页面中获取详细的列表:cordova.apache.org/plugins/

 

向工程添加plugin的命令如下:

$ cordova plugin add cordova-plugin-camera

相似的,删除除plugin的命令如下:

$ cordova plugin remove cordova-plugin-camera

可以使用以下命令显示所有添加的plugin

$ cordova plugin list

2.8. 更新cordova框架

linux使用以下命令更新cordova

$ sudo npm update -g cordova

windows平台使用以下命令更新cordova

C:\>npm update -g cordova

 

也可以更新到指定版本:

$ sudo npm install -g cordova@3.1.0-0.2.0

 

以下命令显示cordova版本:

$ npm info cordova version

 

更新cordova的移动平台:

$ cordova platform update android

2.9. 
android studio打开工程

工程建立并添加android平台后,可以在/platform/android/目录下找到cordove创建的android工程。

注意:android工程是临时的,cordova会覆盖该目录下的文件。工程开发主要工作是开发工程目录下的www目录、config.xml文件,以及自定义的plugin,而不是修改该android目录下的内容。


2.10. hello world工程运行结果

 

2.11. cordova版本与android版本的对应关系

cordova-android Version

Supported Android API-Levels

5.X.X

14 - 23

4.1.X

14 - 22

4.0.X

10 - 22

3.7.X

10 - 21

3. config.xml

3.1. 文件内容示例

<?xml version='1.0' encoding='utf-8'?>

<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">

    <name>HelloCordova</name>

    <description>

        A sample Apache Cordova application that responds to the deviceready event.

    </description>

    <author email="dev@cordova.apache.org" href="http://cordova.io">

        Apache Cordova Team

    </author>

    <content src="index.html" />

    <plugin name="cordova-plugin-whitelist" version="1" />

    <access origin="*" />

    <allow-intent href="http://*/*" />

    <allow-intent href="https://*/*" />

    <allow-intent href="tel:*" />

    <allow-intent href="sms:*" />

    <allow-intent href="mailto:*" />

    <allow-intent href="geo:*" />

    <platform name="android">

        <allow-intent href="market:*" />

    </platform>

</widget>

3.2. 说明

config.xml文件是工程的全局配置中心。

 

当使用CLI编译的时候,该文件会被拷贝至各个平台的相应目录:

app/platforms/ios/AppName/config.xml

app/platforms/blackberry10/www/config.xml

app/platforms/android/res/xml/config.xml

... ...

3.3. <widget>的属性

id:必填项,app的反转域名标识符。

version:必填项,版本号。

versionCode:android平台,版本号。

xmlns:必填项,config.xml文件的namespace

xmlns:cdv:必填项,namespace前缀。

3.4. <widget>的子节点

3.4.1. <name>

app的正式名称,将显示在移动设备的home屏幕上和app store上。

3.4.2. <description>

app的说明文字。

3.4.3. <author>

作者信息,包含联系方式。

3.4.4. <content>

app的启动页面,默认为www目录下的index.html

3.4.5. <access>

定义一组允许app访问的外部服务器地址。

 

例如,允许访问所有服务器:

<widget ...>

    <access origin="*"></content>

</widget>

 

允许访问google服务器:

<widget ...>

    <access origin="http://google.com"></content>

</widget>

3.4.6. <allow-intent>

定义app向系统询问是否打开的URL地址。

3.4.7. <preference>

各种工程属性配置。

 

例如,以下为各平台通用配置:

<preference name="DisallowOverscroll" value="true"/>

<preference name="Fullscreen" value="true" />

<preference name="BackgroundColor" value="0xff0000ff"/>

<preference name="HideKeyboardFormAccessoryBar" value="true"/>

<preference name="Orientation" value="landscape" />

 

以下为android平台配置:

<preference name="KeepRunning" value="false"/>

<preference name="LoadUrlTimeoutValue" value="10000"/>

<preference name="InAppBrowserStorageEnabled" value="true"/>

<preference name="LoadingDialog" value="My Title,My Message"/>

<preference name="ErrorUrl" value="myErrorPage.html"/>

<preference name="ShowTitle" value="true"/>

<preference name="LogLevel" value="VERBOSE"/>

<preference name="AndroidLaunchMode" value="singleTop"/>

<preference name="DefaultVolumeStream" value="call" />

<preference name="OverrideUserAgent" value="Mozilla/5.0 My Browser" />

<preference name="AppendUserAgent" value="My Browser" />

3.4.8. <platform>

定义指定平台的参数:

<platform name="android">

    <preference name="Fullscreen" value="true" />

</platform>

3.4.9. icon设置

定义app图标的方式如下:

<platform name="android">

    <icon src="res/android/ldpi.png" density="ldpi" />

    <icon src="res/android/mdpi.png" density="mdpi" />

    <icon src="res/android/hdpi.png" density="hdpi" />

    <icon src="res/android/xhdpi.png" density="xhdpi" />

    <icon src="res/android/xxhdpi.png" density="xxhdpi" />

    <icon src="res/android/xxxhdpi.png" density="xxxhdpi" />

</platform>

4. cordova事件

4.1. 代码示例

4.1.1. html文件

<!DOCTYPE html>

<html>

  <head>

    <title>Device Ready Example</title>

 

    <script type="text/javascript" charset="utf-8" src="cordova.js"></script>

    <script type="text/javascript" charset="utf-8" src="example.js"></script>

  </head>

  <body onload="onLoad()">

  </body>

</html>

4.1.2. js文件

// example.js file

// Wait for device API libraries to load

function onLoad() {

    document.addEventListener("deviceready", onDeviceReady, false);

}

 

// device APIs are available

function onDeviceReady() {

    document.addEventListener("pause", onPause, false);

    document.addEventListener("resume", onResume, false);

    document.addEventListener("menubutton", onMenuKeyDown, false);

}

 

function onPause() {

}

 

function onResume() {

}

 

function onMenuKeyDown() {

}

4.2. cordova事件

cordova事件通过document.addEventListener()方法来注册。

PS:在cordova工程下,html页面中的事件需要用DOM对象的addEventListener方法来注册,如下:
        document.getElementById("button_test").addEventListener("click", TakePhoto, false);

如果使用HTML事件会无效,如下:

<button onclick="copyText()">Copy Text</button>

4.2.1. deviceready

cordova加载成功后调用,只有该事件被调用后,才表示cordova其它各个接口可以使用。经常在该事件中注册其它事件的Listener

4.2.2. pause

application被置于后台时调用。

4.2.3. resume

application被置于前台后调用。

4.2.4. backbutton

用户点击退回按钮时被调用。

4.2.5. menubutton

用户点击菜单按钮时被调用。

4.2.6. searchbutton

用户点击搜索按钮时被调用。

4.2.7. volumedownbutton

用户点击音量加按钮时被调用。

4.2.8. volumeupbutton

用户点击音量减按钮时被调用。

4.3. 各平台对cordova事件的支持

 

5. plugin开发

5.1. 添加plugin

添加plugin的命令上文已经介绍过,该命令也可以从git上添加plugin的命令:

$ cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git

添加自已开发的plugin的命令为(C:/plugin/MyPlugin为自已开发的plugin的保存目录):

$ cordova plugin add C:/plugin/MyPlugin

5.2. js中调用plugin

javascript代码中调用plugin的接口采用以下方法:

cordova.exec(function(winParam) {},

           function(error) {},

           "service",

           "action",

           ["firstArgument", "secondArgument", 42, false]);

function(winParam) {}:plugin接口调用成功后的回调函数

function(error) {}:plugin接口调用失败后的回调函数

"service":服务名称,即为plugin.xml中config-file项下的feature项中的name。
        <config-file target="res/xml/config.xml" parent="/*">
            <feature name="service_name">

"action":方法名称,即为plugin的java类中的exec函数里,识别的方法名称。

[/* arguments */]:传递给方法的参数,如果不需要参数,则输入“[]”,例如:

cordova.exec(function(winParam) {},

           function(error) {},

           "service",

           "action",

           []);

 

注意:使用前先声明cordova

var cordova = require('cordova');  

 

也可以这样声明:

var exec = require('cordova/exec');

在这种情况下,直接调用exe函数:

var exec = require('cordova/exec');

exports.getExtra = function(success, error) {

    exec(success, error, "ExtraInfo", "getExtra", []);

};

 

require、exportsmodule.exports都是node.js的语法,require意为引用外部模块,exportsmodule.exports意为声明当前js模块的接口。详细请参考node.js资料。

5.3. plugin必备的文件

一个plugin至少包含以下三部分内容:

├── src:各平台的plugin实现代码

 |            ├── android

 |            ├── ios

 |            └── ...

├── www声明pluginjs接口

 |            ├──  XXX.js

└── plugin.xml定义plugin的配置参数

5.4. plugin.xml

plugin.xml内容示例如下:

   

<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"

    xmlns:android="http://schemas.android.com/apk/res/android"

    id="cordova-plugin-device"

    version="1.1.1">

    <name>Device</name>

    <description>Cordova Device Plugin</description>

    <license>Apache 2.0</license>

    <keywords>cordova,device</keywords>

 

    <js-module src="www/device.js" name="device">

        <clobbers target="device" />

    </js-module>

 

    <!-- android -->

    <platform name="android">

        <config-file target="res/xml/config.xml" parent="/*">

            <feature name="Device" >

                <param name="android-package" value="org.apache.cordova.device.Device"/>

            </feature>

        </config-file>

 

        <source-file src="src/android/Device.java" target-dir="src/org/apache/cordova/device" />

    </platform>

</plugin>

5.4.1. <plugin>

设置pluginid等配置

xmlns:必填项,pluginnamespace,将添加到android工程的AndroidManifest.xml文件中。

id:必填项,pluginidnpm风格书写。

version:必填项,pluginversion

5.4.2. <name>

plugin的名称

5.4.3. <description>

plugin的描述

5.4.4. <author>

plugin的作者

5.4.5. <keyword>

plugin的关键字

5.4.6. <license>

plugin的授权说明

5.4.7. <asset>

该配置项下指定的文件将被拷贝到cordovawww目录,做为工程的一部分。放在<platform>节点下则表示仅对该平台生效。

示例:

<asset src="www/foo.js" target="foo.js" />

srcplugin开发目录下准备复制的源文件,目录路径相对于plugin.xml文件

target:拷贝到www目录下的目标文件,目录路径相对于www目录

5.4.8. <js-module>

每个<js-module>定义一个该pluginjs文件,一般为plugin接口注册的js文件,cordova建立工程时,会复制文件到www/plugins/my.plugin.id目录下,并且在www/cordova_plugins.js文件中添加对该js文件的声明。在启动时,cordova.js中会将这些js文件通过<script>插入到HTML页面中。

如果<js-module>嵌入在<platform>下,则仅对该平台生效。

 

示例1

<js-module src="socket.js" name="Socket">

    <clobbers target="chrome.socket" />

</js-module>

srcpluginjs源文件名称,目录路径相对于plugin.xml文件,拷贝目的路径为:www/plugins/your-plugin-id/

namejs模块的末尾名称,仅用于cordova.require语句导入js代码时。

clobbers:插入到windows对象的子属性或者方法,如上为window.chrome.socket

 

示例2

 <js-module src="socket.js" name="Socket">

    <runs/>

 </js-module>

runs:该js模块允许被cordova.require语句声明,但不能用于windows对象。

5.4.9. <dependency >

声明当前plugin需要其它plugin的支持。

示例:

 <dependency id="cordova-plugin-someplugin" url="https://github.com/myuser/someplugin" commit="428931ada3891801" subdir="some/path/here" />

  <dependency id="cordova-plugin-someplugin" version="1.0.1">

5.4.10. <platform >

针对具体平台的特别设置。

<platform>外的配置主要针对js文件,它们将被安装在每个平台上,<platform>内的主要为各平台下plugin的具体实现文件。

name:平台名称,可选择androidios

 

<source-file>:需要安装的源代码文件

src:源文件,文件目录相对于plugin.xml

target-dir:拷贝目录,相对于cordova项目的根目录,如com.alunny.foo包中目录为com/alunny/foo

示例1

<source-file src="src/android/Foo.java" target-dir="src/com/alunny/foo" />

 

<config-file>:用于在XML文件中追加配置项

target:目标文件,路径相对于cordove工程的目录。如果文件不存在,则该配置会被忽略。如果指定*,则工程目录下所有子目录都被搜索, 直到找到第一个匹配的文件。

parent:XPath格式的XML中父结点名称,配置内容会添加在这个父结点下。可以使用*来指定的根节点,例如:/*/plugins

after:指定当前配置添加在哪个兄弟节点后面。

示例2

<config-file target="res/xml/config.xml" parent="/*">

    <feature name="Device" >

        <param name="android-package" value="org.apache.cordova.device.Device"/>

    </feature>

</config-file>

<feature>定义plugin的接口类

<feature "name"="">plugin名称

<param name>:为"android-package"

<param value>:继承自CordovaPlugin类的接口类

 

示例3,为activity添加filter

 <config-file target="AndroidManifest.xml" parent="/manifest/application">

      <activity android:name="com.foo.Foo" android:label="@string/app_name">

          <intent-filter>

          </intent-filter>

      </activity>

  </config-file>

 

<config-file>中还可以为android平台添加权限配置。

示例4

<config-file target="AndroidManifest.xml" parent="/*">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

</config-file>

 

<lib-file>为工程添加lib库的引用。

示例:

 <lib-file src="src/BlackBerry10/native/device/libfoo.so" arch="device" />

src:库文件名称,目录相对于plugin.xml文件。

arch :库文件编译时的系统架构,可以是device、simulator、x86、x64、ARM


<resource-file>为工程添加资源文件,如layout xml文件。

src:源文件,目录相对于config.xml文件。

target:目标文件,目录相对于android工程根目录。

示例:

<resource-file src="src/android/java/activity_preview.xml" target="res/layout/activity_preview.xml" />


5.5. pluginjava实现类

plugin的实现类都从CordovaPlugin类继承,重写其中的execute()方法,完成所需的功能。

CordovaPlugin类定义见工程目录的以下子目录:platforms\android\CordovaLib\src\org\apache\cordova

cordova应用在android平台采用WebView实现,plugin针对每一个WebView都创建一个实例,只有当js脚本调用到plugin的时候才创建它的实例,除非配置onload参数。

<feature name="Echo">

    <param name="onload" value="true" />

</feature>

5.6. plugin的线程

plugin的代码运行在WebCore线程,而非WebView所处的主线程。

如果需要在UI线程运行,则采用以下方式:

public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {

    if ("beep".equals(action)) {

        final long duration = args.getLong(0);

        cordova.getActivity().runOnUiThread(new Runnable() {

        // 以下代码可以在其它子线程中运行

        //cordova.getThreadPool().execute(new Runnable() {

            public void run() {

                ...

                callbackContext.success(); // Thread-safe.

            }

        });

        return true;

    }

    return false;

}

6. 一个plugin的简单实例

本示例采用V5.1.1版本的cordova编译。

该实例实现:如果调用正确名称的plugin接口,则返回true;否则返回false。返回的结果在页面中弹窗显示。

6.1. plugin目录结构

├── src

 |            ├── android

 |                      ├── MyPlugin.java

├── www

 |            ├──  MyPlugin.js

└── plugin.xml

6.2. 操作步骤

1,按照“2 cordova开发环境”所描述的方法,建立cordova测试工程

2,按照“6.1 plugin目录结构”所描述,建立plugin目录,例如建立在c:\plugin目录下

3,打开“cmd.exe”程序,进入cordova测试工程目录

4,按照以下顺序执行命令

cordova plugin add c:\plugin

cordova platform add android

cordova build

5,使用android studio打开cordova工程目录下的platform/android目录下的工程,按“shift+F9”运行。

6.3. plugin.xml

<?xml version="1.0" encoding="utf-8"?>

<plugin id="com.sample" version="0.0.1" 

        xmlns="http://apache.org/cordova/ns/plugins/1.0"

        xmlns:android="http://schemas.android.com/apk/res/android">

    <name>MyPlugin</name>

    <description>test plugin</description>

    <js-module name="MyPlugin" src="www/MyPlugin.js">

        <clobbers target="cordova.plugins.MyPlugin"/>

    </js-module>

    <platform name="android">

        <config-file target="res/xml/config.xml" parent="/*">

            <feature name="MyPlugin">

                <param name="android-package" value="com.sample.MyPlugin"/>

            </feature>

        </config-file>

        <source-file src="src/android/MyPlugin.java" target-dir="src/com/sample"/>

    </platform>

</plugin>

6.4. MyPlugin.js

var exec = require('cordova/exec');

 

exports.getData = function(success, error) {

    exec(success, error, "MyPlugin", "getData", []);

};

6.5. MyPlugin.java

package com.sample;

 

import org.apache.cordova.CallbackContext;

import org.apache.cordova.CordovaPlugin;

import org.json.JSONArray;

import org.json.JSONException;

 

public class MyPlugin extends CordovaPlugin {

 

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) 

            throws JSONException {

        if (action.equals("getData")) {

            callbackContext.success("success in plugin");

            return true;

        }

else

{

            callbackContext.error("error in plugin");

return false;

}

    }

}

6.6. index.js

 // index.js为测试工程的www\js目录下js文件,其被www\index.html文件嵌入。

var app = {

    // Application Constructor

    initialize: function() {

        this.bindEvents();

    },

    // Bind Event Listeners

    //

    // Bind any events that are required on startup. Common events are:

    // 'load', 'deviceready', 'offline', and 'online'.

    bindEvents: function() {

        document.addEventListener('deviceready', this.onDeviceReady, false);

    },

    // deviceready Event Handler

    //

    // The scope of 'this' is the event. In order to call the 'receivedEvent'

    // function, we must explicitly call 'app.receivedEvent(...);'

    onDeviceReady: function() {

        app.receivedEvent('deviceready');

var extraInfo = cordova.require('com.sample.MyPlugin');

extraInfo.getData(function(message) { alert(message); }, 

function(message) { alert(message); });

    },

    // Update DOM on a Received Event

    receivedEvent: function(id) {

        var parentElement = document.getElementById(id);

        var listeningElement = parentElement.querySelector('.listening');

        var receivedElement = parentElement.querySelector('.received');

 

        listeningElement.setAttribute('style', 'display:none;');

        receivedElement.setAttribute('style', 'display:block;');

 

        console.log('Received Event: ' + id);

    }

};

 

app.initialize();

 

0 0
原创粉丝点击