鍍金池/ 教程/ 嵌入式/ Plugin 開發(fā)
云端 Cordova
UI 框架 jQuery Mobile
配置文件 config.xml
UI 框架 Ionic Framework
Plugin 開發(fā)
slides & books
應(yīng)用圖標(biāo) icon 和啟動頁面 SplashScreen
Sample 工程解析
使用 Hooks 自定義 build 過程
JS 是如何調(diào)用本地 API 的?
deviceready 事件
為 Android APK 簽名
調(diào)試工具 Debug
幾個不可或缺的 lib
環(huán)境搭建(Windows / Android)
Native API 的使用

Plugin 開發(fā)

Cordova 提供的功能能夠滿足一般應(yīng)用,但是對于復(fù)雜的應(yīng)用或者對性能要求比較嚴(yán)格的應(yīng)用來說,并不是很理想的。所以就需要在某些場景下自己寫代碼來彌補這些不足,類似 Titanium Module 一樣,Cordova 也提供了 Plugin 功能。Cordova 本身訪問 Native 接口都是通過 Plugin 的方式提供的,可以參考官方 Plugin 代碼,而且 GitHub 上也存在不少開源的 Cordova Plugin,所以這些都是最好的教程。

Plugin 的分類大概有兩種:

  • JavaScript-only Plugin:不需要寫 Native 代碼,不依賴平臺的共通的 JS 代碼
  • Native Plugin:彌補 Cordova 提供的功能以外的 Native 調(diào)用,依賴各個平臺寫不同的 Native 代碼

(1)Plugin 構(gòu)成

引用

|- plugin.xml 
|- www 
|   +- hello_world.js 
+- src 
    |- android 
    |     +- com/rensanning/cordova/plugin/HelloWorldPlugin.java 
    +- ios 
        |- HelloWorldPlugin.h 
        +- HelloWorldPlugin.m

plugin.xml : 必須。通知 CLI 哪個平臺應(yīng)該從什么地方 Copy 哪些文件到什么地方,以及 CLI 在生成 config.xml 時應(yīng)該根據(jù)平臺加入什么樣的特殊設(shè)置。
JavaScript 文件 : 必須。一個 Plugin 至少應(yīng)該有一個 JS 文件,也可以引入其他的 lib(比如:handlebars.js),定義為 js-module,會被 cordova.js 會自動讀入。
原生代碼 :可選。
靜態(tài)文件 : 可選。HTML、圖像等

其中 plugin.xml 文件配置如下:

Xml 代碼

<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    xmlns:rim="http://www.blackberry.com/ns/widgets"
    xmlns:android="http://schemas.android.com/apk/res/android"
    id="org.apache.cordova.device"
    version="0.2.8">
    <name>Device</name>
    <description>Cordova Device Plugin</description>
    <license>Apache 2.0</license>
    <keywords>cordova,device</keywords>
    <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git</repo>
    <issue>https://issues.apache.org/jira/browse/CB/component/12320648</issue>

    <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>

plugin -- 命名空間、ID、版本
name -- 名稱
description -- 描述
keywords -- 關(guān)鍵字
engines -- Cordova 版本
js-module -- js 文件地址,會被默認(rèn)加載到首頁面(index.html),通過 clobbers 元素的定義把就是的 module.exports 自定賦給 window 對象。
platform -- 各個平臺設(shè)置

(2)創(chuàng)建 JS Plugin

文件夾結(jié)構(gòu):

引用

sample 
│  plugin.xml 
│ 
└─www 
        hello_world.js

plugin.xml:

Xml 代碼

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    id="com.rensanning.cordova.helloworld"
    version="0.0.1">
    <name>HelloWorldPlugin</name>
    <description>HelloWorldPlugin Description</description>
    <author>rensanning</author>
    <license>Apache 2.0 License</license>
    <engines>
        <engine name="cordova" version=">=3.0.0" />
    </engines>
    <js-module src="www/hello_world.js" name="helloworld">
        <clobbers target="HelloWorld" />
    </js-module>
</plugin>

hello_world.js:

Js 代碼

var HelloWorld = function() {};

HelloWorld.prototype.say = function() {
    alert("Hello World");
};

var helloWorld = new HelloWorld();
module.exports = helloWorld;

創(chuàng)建工程測試 Plugin:

引用

cordova create simplePlugin com.rensanning.cordova.simplePlugin SimplePlugin 
cd simplePlugin 
cordova platform add android 
cordova plugin add E:\plugins\sample

修改 index.html 后啟動測試即可。

Html 代碼

<button onclick="test();">Click me!</button>
<script type="text/javascript">
  function test() {
      HelloWorld.say();
  }
</script>

http://wiki.jikexueyuan.com/project/cordova-3.x-primer-foundation/images/12.1.png" alt="picture12.1" />

(3)創(chuàng)建 Native Plugin

以 Android 下獲取 Carrier Code 為例。

文件夾結(jié)構(gòu):

引用

carrier 
│  plugin.xml 
│ 
├─src 
│  └─android 
│          CarrierPlugin.java 
│ 
└─www 
        carrier.js

plugin.xml:

Xml 代碼

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    id="com.rensanning.cordova.carrier"
    version="0.0.1">
    <name>CarrierPlugin</name>
    <description>CarrierPlugin Description</description>
    <author>rensanning</author>
    <license>Apache 2.0 License</license>
    <engines>
        <engine name="cordova" version=">=3.0.0" />
    </engines>
    <js-module src="www/carrier.js" name="carrier">
        <clobbers target="Carrier" />
    </js-module>
    <platform name="android">
        <source-file src="src/android/CarrierPlugin.java" target-dir="src/com/rensanning/cordova/carrier" />
        <config-file target="res/xml/config.xml" parent="/*">
            <feature name="CarrierPlugin">
                <param name="android-package" value="com.rensanning.cordova.carrier.CarrierPlugin"/>
            </feature>
        </config-file>
        <config-file target="AndroidManifest.xml" parent="/*">
            <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        </config-file>
    </platform>
</plugin>

CarrierPlugin.java:

Java 代碼

public class CarrierPlugin extends CordovaPlugin {
    public static final String TAG = "CarrierPlugin";
    public static final String ACTION_GET_CARRIER_CODE = "getCarrierCode";
    public TelephonyManager tm;

    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        Context context = this.cordova.getActivity().getApplicationContext();
        tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (ACTION_GET_CARRIER_CODE.equals(action)) {
            String carrier = tm.getSimCountryIso();
            Log.d(TAG, carrier);
            callbackContext.success(carrier);
            return true;
        }
        return true;
    }
}

carrier.js:

Js 代碼

var cordova = require('cordova');

var Carrier = function() {};

Carrier.prototype.getCarrierCode = function(success, error) {
    cordova.exec(success, error, 'CarrierPlugin', 'getCarrierCode', []);
};

var carrier = new Carrier();
module.exports = carrier;

修改 index.html 后啟動測試即可。

Html 代碼

<button onclick="test2();">Carrier Code!</button>
<script type="text/javascript">
  function test2() {
    Carrier.getCarrierCode(onSuccess, onFailure);
  }
  function onSuccess(result) {
    alert("Result: " + result);
  }
  function onFailure(err) {
    alert("Failure: " + err);
  }
</script>

http://wiki.jikexueyuan.com/project/cordova-3.x-primer-foundation/images/12.2.png" alt="picture12.2" />

***Cordova device APIs從Cordova 3.0開始全 Plugin 的機制稍有變化,默認(rèn)都不可用,需要什么添加什么:

http://wiki.jikexueyuan.com/project/cordova-3.x-primer-foundation/images/12.3.png" alt="picture12.3" />

Plugin 的添加和刪除也同時提供兩種方式: Cordova CLI、Plugman。
但是不同的是 Plugman一次只能為一個 platform 添加 Plugin,而 Cordova CLI 是為所有平臺都添加 Plugin。
Cordova CLI 內(nèi)部實際上也是調(diào)用的 Plugman。

安裝 plugman

引用

npm install plugman -g 
plugman -v 
plugman help

添加 Plugin

引用

plugman --platform android --project <directory> --plugin <name|url|path> [--plugins_dir <directory>] [--www <directory>] [--variable <name>=<value>]

刪除 Plugin

引用

plugman --uninstall --platform android --project <directory> --plugin <id> [--www <directory>] [--plugins_dir <directory>]

詳細參考:https://github.com/apache/cordova-plugman/
Cordova Plugin Registry 有以下兩個:http://plugins.cordova.io/、http://plugreg.com/plugins

***Plugin 的 js 中直接寫代碼即可,CLI 會包裝你的代碼:
比如:

Js 代碼

cordova.define("com.rensanning.cordova.helloworld.helloworld", function(require, exports, module) { var HelloWorld = function() {};

HelloWorld.prototype.say = function() {
    alert("Hello World");
};

var helloWorld = new HelloWorld();
module.exports = helloWorld;
});

參考:
Plugin Development Guide
Plugin Specification(plugin.xml)