玩轉cordova

方健發表於2014-11-28

寫在前面

話說HTML5和原生程式碼這個口水仗打了很久了。打口水仗的人多半都是噴口水而已。這其中的奧妙真正幹活的人才知道。如果說HTML5能完全代替原生,那要原生幹什麼?如果說HTML5完全不可用,那這麼多牛逼的網站是打臉的麼?所以說呢,webview在android和ios就是個控制元件,你就好好的當他控制元件來用。webview是一個有完整UI系統和生態系統的控制元件。用好了那是好處多多的。

好,那麼問題來了。作為一個控制元件,是少不了和原生程式碼互動的。但是常見的用法似乎只是用來開啟一個網頁。這個勉強算是 "原生程式碼 call js", 還是一次性的。但是"js call 原生"要怎麼玩呢?我曾經研究過一番,在前人的基礎上寫了個工具https://github.com/fangj/WebViewJavascriptBridge 但是不太完善。那麼有現成的cordova 是要用起來的。

在說cordova之前。我大概說一下webview和原生怎麼互動的:

  • Android

Android->JS : loadUrl
JS->Android: JavascriptInterface

  • IOS IOS->JS: loadUrl
    JS->IOS: loadUrl, IOS攔截自定義schema

下面正式開始講:
主要內容都在文件裡
http://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html#The%20Command-Line%20Interface
http://cordova.apache.org/docs/en/4.0.0/guide_hybrid_plugins_index.md.html#Plugin%20Development%20Guide
http://cordova.apache.org/docs/en/4.0.0/guide_platforms_android_plugin.md.html
http://cordova.apache.org/docs/en/4.0.0/guide_platforms_ios_plugin.md.html

  • 用命令列工具生成cordova工程

    sudo npm install -g cordova
    cordova create hello com.example.hello HelloWorld
    cd hello
    cordova platform add ios
    cordova platform add android
    cordova build
    

此時android和ios的工程已經生成,可以用你的IDE開啟執行了。

  • 開始寫外掛。先看JS裡怎麼呼叫:

    cordova.exec(function(winParam) {},
                 function(error) {},
                 "service",
                 "action",
                 ["firstArgument", "secondArgument", 42, false]);
    

幾個引數分別是:成功回撥。失敗回撥。要呼叫的物件(service)。要呼叫的方法(action)。方法的引數[...]。

  • 在IOS裡怎麼寫外掛

Echo.h

    #import "CDVPlugin.h"

    @interface Echo : CDVPlugin
    - (void)echo:(CDVInvokedUrlCommand*)command;
    @end

Echo.m

    #import "Echo.h"

    @implementation Echo
    - (void)echo:(CDVInvokedUrlCommand*)command
    {
        CDVPluginResult* pluginResult = nil;
        NSString* echo = [command.arguments objectAtIndex:0];

        if (echo != nil && [echo length] > 0) {
            NSLog(@"ios received %@",echo);
            NSLog(@"ios send OK");
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
        } else {
            NSLog(@"ios send fail");
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
        }

        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }
    @end

還有很關鍵的。在ios工程目錄下找到config.xml,加上這麼一句

 <feature name="Echo">
    <param name="ios-package" value="Echo" />
    <param name="onload" value="true" />
</feature>

feature name是JS中呼叫的外掛名,ios-package的value是IOS中對應的類名。

  • Android 中外掛怎麼玩
    Echo.java

    package org.apache.cordova.plugin;
    
    
    import android.util.Log;
    import org.apache.cordova.CallbackContext;
    import org.apache.cordova.CordovaPlugin;
    import org.json.JSONArray;
    import org.json.JSONException;
    
    
    /**
     * Created by fangjian on 14-11-28.
     */
    public class Echo extends CordovaPlugin {
        @Override
        public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
            if (action.equals("echo")) {
                String message = args.getString(0);
                this.echo(message, callbackContext);
                return true;
            }
            return false;
        }
    
    
    
    private void echo(String message, CallbackContext callbackContext) {
        if (message != null &amp;&amp; message.length() &gt; 0) {
            Log.d("cordova plugin", "android sent OK");
            callbackContext.success(message);
        } else {
            Log.d("cordova plugin", "android sent Fail");
            callbackContext.error("Expected one non-empty string argument.");
        }
    }
    
    }

同樣,需要找到Android工程目錄下的config.xml,加上這麼一句

<feature name="Echo">
    <param name="android-package" value="org.apache.cordova.plugin.Echo" />
    <param name="onload" value="true" />
</feature>

android-package是android對應的類名。