Cordova開發(fā)指南

通過一個月的Cordova學習, 我將知識點總結(jié)為三部分:

  1. 純Cordova開發(fā)---不依賴原生平臺
  2. 原生平臺混合Cordova開發(fā)
  3. 插件開發(fā)

在進行Cordova開發(fā)之前, 先花點時間了解一下的Cordova的原理和Cordova的框架結(jié)構(gòu).

  1. Cordova是開發(fā)跨平臺web App的工具, 使用前端技術(shù)來開發(fā)App, 可以節(jié)省成本和快速發(fā)布.
  2. Cordova的底層邏輯是:HTML+CSS搭建頁面, 使用JS和原生平臺交互來展示原生平臺的功能.
  3. Cordova所有功能是建立在各種插件上的, 所以插件開發(fā)是Cordova開發(fā)的重點.

純Cordova開發(fā)

這種開發(fā)模式不需要各原生平臺開發(fā)人員參與, 只需要前端猿將開發(fā)好的web App放入到Cordova工程中, 然后使用Cordova-CLI(Cordova命令行界面)將web App和各種插件配種好后, 就可以build, run進行各平臺的構(gòu)建和調(diào)試了. 以下是純Cordova開發(fā)的步驟:

  1. Cordova的安裝
  2. 使用Cordova-CLI創(chuàng)建Cordova項目----創(chuàng)建Cordova項目后, 前端猿就可以在www/進行開發(fā), 今后的大部分工作都集中在這個文件下.
    1. 添加平臺
    2. 添加插件
    3. 構(gòu)建Cordova項目
    4. 在各原生平臺上運行Cordova App
  3. Cordova項目更新

一.Cordova的安裝

CLI工具需要使用npm來安裝, 因為它被發(fā)布到了npm.
按照下面步驟來按照CLI:

  1. 下載和安裝Node.js.
  2. (可選)如果你的電腦沒有安裝Git的話, 下載和安裝git client, 因為后續(xù)CLL需要使用git來下載git倉庫中的資源. 各OS的安裝方法自行百度.
  3. 使用Node.js中的npm來安裝cordova模塊. cordova模塊會自動被npm下載.
    1. 在OS x和linux下

       $ sudo npm install -g cordova
      

      如果出現(xiàn)"xx/xx/xx(例如/usr/local/share) permission denyed"的錯誤,可以在npm命令前加上sudo前綴.

    2. 在window中

       C:\>npm install -g cordova
      

      上面的-g標志告訴npm全局安裝cordova. 否則, 它將安裝在當前工作目錄的node_modules子目錄中.

安裝之后, 你應該能夠在命令行上運行cordova, 不需要參數(shù), 它會打印幫助文本.

二.創(chuàng)建Cordova工程

1.使用CLI命令創(chuàng)建 create

cd到維護源代碼的目錄, 并創(chuàng)建一個cordova項目:

$ cordova create hello com.example.hello HelloWorld

這將為你的cordova應用程序創(chuàng)建所需的目錄結(jié)構(gòu). 默認情況下, cordova create腳本會生成一個基于Web的框架應用程序, 其主頁是項目下www/目錄中的index.html文件

打開Mac終端輸入上面的命令, 創(chuàng)建一個Cordova項目, 得到項目目錄結(jié)構(gòu)如下:


15427793118491.jpg

上面的Create命令的解釋:

  1. 保存項目的路徑, 比如上面的"hello", 該路徑是缺省的.
  2. 項目的id, 默認值是io.cordova.hellocordova; 安卓中的Java包名, iOS的bundleID都需要用到這個, 所以最好不要缺省, 或者要好好對待這事, 該值以后可以修改.
  3. 項目的name, 默認是HelloCordova, 該值也可以修改, 安卓平臺可能會使用該值作為類名.
  4. 上面idname的都會配到config.xml中
    15450994158002.jpg

2.使用模板創(chuàng)建工程 --template

使用模板App中的代碼可以快速搭建你的cordova-app.

  1. 首先你要去npm網(wǎng)站上, 使用關(guān)鍵字cordova:template來搜索可以用的template. 如下圖所示:

    15446646202387.jpg

  2. 這里我使用第二template-cordova-template-ngx-onsenui來創(chuàng)建一個項目, 可以的命令有如下:

$ cordova create hello com.example.hello HelloWorld --template <npm-package-name>
$ cordova create hello com.example.hello HelloWorld --template <git-remote-url>
$ cordova create hello com.example.hello HelloWorld --template <path-to-template>
  1. 我選擇第一個命令, 在我本地創(chuàng)建如下項目:
cordova create UseCordovaTemplate personal.zxx.cordovatemplate --template cordova-template-ngx-onsenui

無錯執(zhí)行完上面命令后, done! 使用模板生成了一個新項目.

我們來看下, 使用模板創(chuàng)建的項目的和不是模板創(chuàng)建的區(qū)別:

15446654222528.jpg

發(fā)現(xiàn)多了幾個文件和一個src文件夾.

  1. 接下來添加平臺-iOS:
cedardeiMac-6:Desktop zhouxingxing$ cd UseCordovaTemplate/
cedardeiMac-6:UseCordovaTemplate zhouxingxing$ cordova platform add ios
添加成功后, 會在`platforms/`生成一個iOS項目:
15446659436862.jpg
  1. 然后我運行構(gòu)建, 運行cordova項目
cordova build ios 
cordova run ios 

發(fā)現(xiàn)一個錯誤:

No target specified for emulator. Deploying to iPhone-X, 12.1 simulator
/Users/zhouxingxing/Desktop/UseCordovaTemplate/platforms/ios/build/emulator/HelloCordova.app/Info.plist file not found.

上網(wǎng)搜索, 發(fā)現(xiàn)是因為Xcode 10更新了構(gòu)建系統(tǒng), 但cordova并支持, 官方給出的解決方案是手動選擇不適用系的構(gòu)建系統(tǒng):

# Cordova CLI
cordova run ios --buildFlag='-UseModernBuildSystem=0'
cordova build ios --buildFlag='-UseModernBuildSystem=0'

詳細信息請參考:https://github.com/apache/cordova-ios/issues/407


下面的添加平臺platform/插件plugin/構(gòu)建build/運行run這些命令都需要你剛才創(chuàng)建項目的路徑下工作, 比如剛才的*/hello/.

3.添加平臺 platform

  1. 下面的這些命令必須在上面創(chuàng)建項目的目錄下運行, 或者子目錄也行
$ cd hello
  1. 添加你App定位的平臺. 我們將添加'ios'和'android'平臺并確保它們保存到config.xml和package.json:
$ cordova platform add ios

添加完iOS后, 查看項目結(jié)構(gòu), 發(fā)現(xiàn)在platform目錄下多了一個ios/, 里面的內(nèi)容是一個iOS項目目錄:

15427803342837.jpg

并且安裝了一個叫cordova-plugin-whitelist的插件, 在plugins/也發(fā)現(xiàn)多了一個文件夾.

同樣安裝Android平臺后, `platform`也會多一個安卓項目:
    
    $ cordova platform add android
  1. 查看你添加的平臺:
$ cordova platform ls

15427809918948.jpg

運行添加或刪除平臺的命令會影響項目platform目錄的內(nèi)容, 其中每個指定的平臺都顯示為子目錄

注意:使用CLI構(gòu)建應用程序時, 你不應編輯/platforms/目錄中的任何文件. Cordova在準備構(gòu)建應用程序或重新安裝插件時, 會定期自動覆蓋此目錄中的文件.

  1. config.xml的變化


    15451003095257.jpg

更多關(guān)于平臺的操作(比如, 刪除平臺, 添加特定版本的平臺, 從本地添加平臺)請看參考Cordova-CLI參考

4.添加插件 plugin

插件的定義:

  1. 插件是指能夠使Cordova WebView和相應原生平臺就行交互的注入代碼包. 插件給基于Web的App提供對原生設備和平臺功能的訪問.
  2. 本質(zhì)上是一個js文件+原生類(比如Android的Java類,iOS的OC類), JavaScript接口供前端調(diào)用,這影藏了背后的各種native代碼的實現(xiàn).

插件添加和刪除

  1. 插件添加可以通過插件id和Git repo的url來添加:
    $ cordova plugin add cordova-plugin-xyprogress //通過插件id
    $ cordova plugin add https://github.com/cheerszhou/CordovaPulginForTest.git //通過Git url添加

添加完插件后, 在項目目錄的下plugins/會顯示你添加的插件:

15451029455183.jpg

而且config.xml中也會注冊這些插件:
15451029967640.jpg
  1. 插件刪除:
    $ cordova plugin rm cordova-plugin-xyprogress

運行上面命令后, 在plugins/config.xml也會刪除相應的插件

  1. 插件更新,先刪除,后在添加:
$ cordova plugin rm cordova-plugin-xxxx
$ cordova plugin add cordova-plugin-xxxx
  1. 列舉安裝的插件:
$ cordova plugin ls

更多關(guān)于如何管理(按版本添加, 插件沖突)插件的命令請參考Cordova-CLI參考

5.構(gòu)建和運行

創(chuàng)建項目, 添加平臺和插件后, 你可以進行構(gòu)建App了. 在構(gòu)建之前, 你需要檢查你的開發(fā)環(huán)境是否搭建好了, 因為構(gòu)建各個平臺的App需要的環(huán)境是不一樣的, 比如iOS你需要安裝Mac系統(tǒng), Xcode, xcode-select, ios-deploy.

  1. 檢查各平臺需要的環(huán)境要求:
$ cordova requirements

運行上面命令, 你從terminal中可以看到如下提示信息, 安裝提示信息去搭建各平臺需要的環(huán)境:


15427816348232.jpg

關(guān)于各平臺的構(gòu)建環(huán)境, 請看:
1. 安卓平臺環(huán)境要求
2. iOS平臺環(huán)境要求
3. Windows平臺環(huán)境要求

  1. 使用$ cordova build構(gòu)建所有平臺項目, 也可以構(gòu)建特定平臺, 如iOS:
$ cordova build ios

更多關(guān)于build的命令請參考Cordova-CLI參考

  1. 使用$ cordova run來構(gòu)建并運行所有平臺, 也可使用下面帶選項的命令:
  • 在Android平臺上,名為Nexus_5_API_23_x86模擬器上運行的當前cordova項目的發(fā)布版本. 運行時使用特定構(gòu)建配置:
cordova run android --release --buildConfig=..\myBuildConfig.json --target=Nexus_5_API_23_x86
  • 使用真機或模擬器(如果沒有連接設備)在Android平臺上運行當前cordova項目的調(diào)試版本. 跳過構(gòu)建:
cordova run android --nobuild
  • 在ios設備上運行當前cordova項目的調(diào)試版本:
cordova run ios --device
  • 枚舉可用于運行此應用程序的所有連接設備和可用模擬器的名稱:
cordova run ios --list
  • 或者模擬器中運行:
cordova emulate ios
//指定模擬器使用的模擬設備:
cordova emulate ios --target iPhone-6s
cordova emulate ios --target iPhone-6s-Plus

運行后, 默認顯示的www下的index.thml頁面,下面是iOS和Android運行效果圖:

15427936848078.jpg
15451048960901.jpg

6.調(diào)試和測試

  1. 調(diào)試一般通過cordova run命令運行各平臺模擬上, 可以直觀看到結(jié)果

  2. Cordova創(chuàng)建的iOS/android平臺項目是可以直接打開的. Xcode/Android Studio內(nèi)置的調(diào)試/分析工具對你進行iOS/android插件開發(fā)時非常有用. 請注意, 在各平臺IDE中打開項目時, 建議你不要在IDE中編輯代碼. 這將會改變項目的platform文件夾(而不是www)中的代碼, 并且更改可能會被覆蓋. 相反, 你應該編輯www文件夾中的代碼, 并通過運行cordova build復制你的更改到各個平臺.

  3. 插件開發(fā)者如果要在native IDE中進行開發(fā)時, 可以用--link標志來將他們開發(fā)插件通過cordova plugin add加入項目中. 這樣插件鏈接的文件會相互影響---platform中的插件文件改變會反映在插件的原文件中(反之亦然).

  4. 使用Safari和Chrome進行調(diào)試

三.升級Cordova和項目

  1. 安裝cordova工具后, 你始終可以通過運行以下命令將其更新到最新版本:
$ sudo npm update -g cordova
  1. 使用此語法安裝特定版本:
$ sudo npm install -g cordova@3.1.0-0.2.0
  1. 運行cordova -v以查看當前正在運行的版本. 要查找最新發(fā)布的cordova版本, 你可以運行:
$ npm info cordova version
  1. 要更新你要定位的平臺:
$ cordova platform update android --save
$ cordova platform update ios --save
...etc.

原生平臺混合Cordova開發(fā)

可以在原生App使用Cordova中的web頁面, 這節(jié)分為塊內(nèi)容, 分別是:

  1. iOS項目中混合Cordova
  2. Android項目中混合Cordova

在iOS項目中混合Cordova

一.將Cordova項目資源添加到Xcode項目中

  1. 首先你有一個iOS原生項目, 比如CordovaHybridByPod

  2. 你有一個Cordova項目, 如果沒有使用cordova create創(chuàng)建一個, 并添加iOS平臺, 因為后面需要用到cordova項目中的內(nèi)容

  3. 打開你的iOS項目, 然后將cordova中的頂層config.xml文件復制到iOS項目下, 并且選擇Create groups for any added folders

    15451156495138.jpg

  4. CordovaLib/CordovaLib.xcodeproj復制到Xcode項目中

    15451164624141.jpg

  5. 在Xcode項目導航欄中選擇CordovaLib.xcodeproj, 然后在File Inspector中, 設置LocationRelative to Group

    15451172791832.jpg

  6. 選中Xcode項目的target, 然后在Build Settings中的Other Linker Flags中添加-force_load-Objc

    15451175544109.jpg

    注:這里有個bug, 官網(wǎng)說添加-force_load-Objc, 發(fā)現(xiàn)添加-force_load后, 原生buildbuild報錯. 所以網(wǎng)上有人推薦添加-all_load-Objc.

  7. 打開Build Phases中的Link Binaries with Libraries, 將下面的庫添加進去:

AssetsLibrary.framework
CoreLocation.framework
CoreGraphics.framework
MobileCoreServices.framework
15451177930921.jpg
  1. 打開Target DependenciesLink Binaries with Libraries都加入CordovaLibbuild后的產(chǎn)物CordovaLib.a, 如果看不到libCordova.a, 可以在Cordova項目目錄下運行cordova build命令.

    15451193738756.jpg

  2. Build Settings中的Header Search Paths.加入下面這些值:

    "$(TARGET_BUILD_DIR)/usr/local/lib/include"
"$(OBJROOT)/UninstalledProducts/include"
"$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include"
"$(BUILT_PRODUCTS_DIR)"
15451197053500.jpg

二.使用CDVViewController

  1. 添加下面的頭文件:
#import<Cordova/CDVViewController.h>
  1. 創(chuàng)建一個新CDVViewController實例, 在其他地方使用時, 強引用它:
CDVViewController* viewController = [CDVViewController new];
  1. (可選)設置wwwFolderName屬性, 默認為www:
viewController.wwwFolderName = @"myfolder";
  1. (可選),在config.xml<content>標簽中設置start page, 也可以是本地文件:
<content src="index.html"/>

...或者一個遠程地址:

<content src="http://apache.org" />
  1. (可選),設置屬性useSplashScreen, 默認值為NO:
viewController.useSplashScreen = YES;
  1. 設置view frame, 總要設置為最新的值:
viewController.view.frame = CGRectMake(0,0,320,480);
  1. 添加Cleaver到view中:
[myView addSubview:viewController.view];
  1. 首先我將cordova中的包含index.html添加到Xcode項目, 然后在ViewController.m中使用CDVViewController如下:
```
//
//  ViewController.m
//  CordovaHybridByPod
//
//  Created by developer_zxx on 2018/12/13.
//  Copyright ? 2018 developer_zxx. All rights reserved.
//
#import "ViewController.h"
#import <Cordova/CDVViewController.h>
@interface ViewController ()
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)showCordovaWebview:(UIButton *)sender {
    CDVViewController * cordovaVC = [[CDVViewController alloc]init];
    cordovaVC.wwwFolderName = @"www";
    [self presentViewController:cordovaVC animated:YES completion:nil];
}
@end

```
  1. 運行結(jié)果:


    15451218123026.jpg
  2. 之后Cordova中的webView就交給www下的前端資源來管理了


在Android項目中混合Cordova

  1. 首先你有一個Android原生項目, 比如NativeProjectForAndroid

  2. 你有一個Cordova項目, 如果沒有使用cordova create創(chuàng)建一個, 并添加Android平臺, 因為后面需要用到cordova項目中的內(nèi)容

  3. 將Cordova項目中的platforms/android/下的res/config.xml, assets/www/下的文件添加到你安卓項目相應的目錄下

    15451299418564.jpg

  4. 將將Cordova項目中的platforms/android/下的CordovaLib作為Android項目的moudle導入

    15451304082351.jpg

  1. cordova-plugin-whitelist插件的Java實現(xiàn)類添加到Android項目,該類在platforms/android/src/java中可以找到.

    15451308578311.jpg

  2. 此時你可以在Android原生項目中使用CordovaActivity.java, 該類顯示www下的資源, 在MainActivity.java中跳轉(zhuǎn)到Cordova Webview中.

    15451311657579.jpg

  3. 運行結(jié)果:


    15451316891061.jpg

插件開發(fā)

Cordova項目中大量使用插件, 除了Cordova平臺提供的核心插件外, 開發(fā)者需要針對一些額外需求自定義開發(fā)插件.

一. 插件工作的原理

  • Cordova插件是通過JavaScript對外提供接口來訪問native功能, 從而能讓前端在web app中開發(fā)類似native的功能.
  • 每個JavaScript對外提供的方法最終是通過調(diào)用Cordova提供的cordova.exec方法來調(diào)用native中的方法
  • 插件中方法最終都是調(diào)用native方法, 所以需要相應的native方法實現(xiàn)
  • 插件開發(fā)包含三個主要部分分別是:JavaScript接口, 原生類的實現(xiàn), config.xml配置文件

二. 插件開發(fā)示例

下面按步驟講解一個插件開發(fā),該插件實現(xiàn)toast功能

A.搭建插件結(jié)構(gòu)

  1. 當你打算去寫一個插件時, 最好先去閱覽一遍已存在的插件, 這樣你就可以有的放矢, 并且可以去github看相應的源代碼.
  2. 上面的插件結(jié)構(gòu)你可以手動創(chuàng)建, 也可以使用plugman來幫你搭建, 最好使用plugman(如果沒有安裝, 可以使用npm install -g plugman)來搭建, plugman搭建如下:
命令:plugman create --name [插件名] --plugin_id [插件ID] --plugin_version [插件版本號]
例子:plugman create --name ZxxToast --plugin_id cordova-plugin-zxxToast --plugin_version 1.0.0
15452197134048.jpg
  1. 上面的插件文件結(jié)構(gòu)邊包含:

    1. www,里面是一個js文件,插件的JavaScript接口部分
    2. src,原生平臺代碼實現(xiàn),可以包含Android,iOS,WP等,你要支持哪個平臺,就在下面創(chuàng)建一個平臺子文件夾,如某個已經(jīng)發(fā)布的插件:
    15451327489750.jpg
    1. config.xml, 該文件起配置作用,制定插件的關(guān)鍵信息,初始如下, 后面還需對其進行編輯:
      15452203423842.jpg

B.創(chuàng)建JavaScript接口

接下來是創(chuàng)建給前端調(diào)用的js接口,這里需要一些前端知識。

  1. 打開插件目錄下www中的ZxxToast.js文件,在ZxxToast.js中提供你想要的輸出的接口

    function ZxxToast() {
    }
    
    ZxxToast.prototype.optionsBuilder = function () {//構(gòu)建傳給native的參數(shù)
    
      // defaults
      var message = null;
      var duration = 1.0;
      var position = "center";
      var addPixelsY = 0;
    
      return {
        withMessage: function(m) {
          message = m.toString();
          return this;
        },
    
        withDuration: function(d) {
          duration = d.toString();
          return this;
        },
    
        withPosition: function(p) {
          position = p;
          return this;
        },
    
        withAddPixelsY: function(y) {
          addPixelsY = y;
          return this;
        },
    
        build: function() {
          return {
            message: message,
            duration: duration,
            position: position,
            addPixelsY: addPixelsY
          };
        }
      };
    };
    
    
    ZxxToast.prototype.showWithOptions = function (options, successCallback, errorCallback) {
      options.duration = (options.duration === undefined ? 'long' : options.duration.toString());
      options.message = options.message.toString();
      cordova.exec(successCallback, errorCallback, "Toast", "show", [options]);//調(diào)用原始api,Toast為原始類名 ,show為原始類提供的方法
    };
    //js 提供給外部的api
    ZxxToast.prototype.show = function (message, duration, position, successCallback, errorCallback) {
      this.showWithOptions(
          this.optionsBuilder()
              .withMessage(message)
              .withDuration(duration)
              .withPosition(position)
              .build(),
          successCallback,
          errorCallback);
    };
    
    
    ZxxToast.install = function () {
      if (!window.plugins) {
        window.plugins = {};
      }
    
      window.plugins.ZxxToast = new ZxxToast();
      return window.plugins.ZxxToast;
    };
    
    cordova.addConstructor(ZxxToast.install);
    

    上面的show方法就是對外提供的接口.

  2. JavaScript接口??提供了前端接口, 使其成為插件中最為重要的部分. 你可以隨意構(gòu)建你的JavaScript接口, 但你必須在后面使用下面語法來調(diào)用cordova.exec和原生平臺進行通信:

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

下面解釋每個參數(shù)的作用:

  • function(winParam) {}:一個成功回調(diào)函數(shù). 如果exec調(diào)用成功, 該函數(shù)會被調(diào)用, 參數(shù)由你傳入.
  • function(error) {}:一個錯誤回調(diào)函數(shù). 如果操作完成失敗, 該函數(shù)會調(diào)用.
  • service:用來被原生調(diào)用的服務名. 與之對應的是原生類, 更多信息在下面各平臺的指導中.
  • action:用來被原生調(diào)用的動作, 與之對應的類, 請看原生平臺指導
  • [/* arguments */]: 一組傳給原生環(huán)境的參數(shù)

C.原生平臺對插件接口的實現(xiàn)

這里先實現(xiàn)iOS平臺的接口支持

  1. 因為插件類需要引用Cordova庫的CDVPlugin類, 所以先創(chuàng)建一個空的Cordova項目, 然后添加iOS平臺, 用到的命令如下:
$ cordova create CordovaDemo
$ cordova platform add ios
$ cordova build ios 
  1. 用Xcode打開在剛才創(chuàng)建的Cordova項目下的platforms/ios/中的iOS工程:

    15452233552528.jpg

  2. 在Xcode中創(chuàng)建一個名為Toast的OC類:


    15452235505656.jpg

    上面的提供的方法, 在JavaScript接口中可以通過exec()方法中的action參數(shù)來指定.

  3. 類Toast的實現(xiàn)文件Toast.m如下:

    #import "Toast.h"
    #import "Toast+UIView.h"
    #import <Cordova/CDV.h>
    
    @implementation Toast
    
    - (void)show:(CDVInvokedUrlCommand*)command {
      NSDictionary* options = [command argumentAtIndex:0];
      NSString *message  = options[@"message"];
      NSString *duration = options[@"duration"];
      NSString *position = options[@"position"];
      NSNumber *addPixelsY = options[@"addPixelsY"];
      
      
      if (![position isEqual: @"top"] && ![position isEqual: @"center"] && ![position isEqual: @"bottom"]) {
        CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"位置參數(shù)無效. 有效的參數(shù)可選:top, center, bottom"];
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
        return;
      }
      
      NSTimeInterval durationMS ;
      if ([duration doubleValue] < 1.0) {
          CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"時間參數(shù)無效. 時間參數(shù)必須>1.0"];
          [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
          return;
      } else {
        durationMS = [duration doubleValue];
      }
      
      [self.webView makeToast:message
                     duration:durationMS
                     position:position
                   addPixelsY:addPixelsY == nil ? 0 : [addPixelsY intValue]
                         data:nil
                      styling:nil
              commandDelegate:self.commandDelegate
                   callbackId:command.callbackId];
      
      CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
      pluginResult.keepCallback = [NSNumber numberWithBool:YES];
      [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }
    
    - (void)hide:(CDVInvokedUrlCommand*)command {
      [self.webView hideToast];
      
      CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
      [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }
    
    @end
    
  4. 在剛才創(chuàng)建ZxxToast插件目錄的src/創(chuàng)建一個文件名為iosandroid的文件夾(后續(xù)用),然后將將上面創(chuàng)建的native類實現(xiàn)copy進去, 如果原生類依賴某些第三庫, 也要copy進去:

    15452250601299.jpg

D.配置plugin.xml文件

  1. 添加原生平臺配置

    <?xml version='1.0' encoding='utf-8'?>
    <plugin id="cordova-plugin-zxxToast" version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
        <name>ZxxToast</name>
        <name>Toast</name>
        
        <description>
            讓webview彈toast框
        </description>
        
        <author>zhouxingxing</author>
        
        <js-module name="ZxxToast" src="www/ZxxToast.js">
            <clobbers target="cordova.plugins.ZxxToast" />
        </js-module>
        
        <engines>
            <engine name="cordova" version=">=3.0.0"/>
        </engines>
        
        <!-- ios -->
        <platform name="ios">
            
            <config-file target="config.xml" parent="/*">
                <feature name="Toast">
                    <param name="ios-package" value="Toast"/>
                </feature>
            </config-file>
            
            <header-file src="src/ios/Toast+UIView.h"/>
            <source-file src="src/ios/Toast+UIView.m"/>
            <header-file src="src/ios/Toast.h"/>
            <source-file src="src/ios/Toast.m"/>
            
            <framework src="QuartzCore.framework" />
        </platform>
    </plugin>
    
    
  2. 上面的節(jié)點解釋:

    • id:代表這個插件的唯一標示,在上傳到npm后,用戶都是通過這個插件id去下載的

    • <name>:這里name可以和id不一樣的,這個name就是插件的name,沒有其他對應關(guān)系

    • <js-module>:文件中可能會有多個js-module的,一個js-module就是一個調(diào)用的方式,這里用戶調(diào)用的方式就是cordova.plugins.ZxxToast.xxxMethod,之后我們會對外提供toast這個方法,那調(diào)用方式就為cordova.plugins.ZxxToast.show

有關(guān)更多plugin.xml配置的相關(guān)信息, 請參考重要配置文件plugin.xml

F.插件調(diào)試

這里的插件調(diào)試即需要前端知識, 也需要原生開發(fā)經(jīng)驗所以有點難度. 而且測試代碼需要在前端頁面上實現(xiàn). 所以下面的部分測試內(nèi)容有可能不是那么的好.

  1. 為你的插件創(chuàng)建一個package.json文件:

    ZXX_MBP:ZxxToast developer_zxx$ plugman createpackagejson /Users/developer_zxx/Desktop/cordova-plugin-zxxToast/ZxxToast //輸入這個命令后, 命令行提示輸入一些關(guān)鍵信息
    name: (cordova-plugin-zxxToast) zmmzxxx //你在npm注冊的用戶名
    version: (1.0.0) //版本
    git repository: //可以輸入github倉庫地址, 你可以將插件發(fā)布到github, 這里我還沒創(chuàng)建, 在發(fā)布的時候再去github創(chuàng)建代碼庫
    author: zhouxingxing //作者
    license: (ISC) MIT //許可證
    About to write to /Users/developer_zxx/Desktop/cordova-plugin-zxxToast/ZxxToast/package.json:
    
    {
      "name": "zmmzxxx",
      "version": "1.0.0",
      "description": "\n        讓webview彈toast框\n    ",
      "cordova": {
        "id": "cordova-plugin-zxxToast",
        "platforms": [
          "ios"
        ]
      },
      "keywords": [
        "ecosystem:cordova",
        "cordova-ios"
      ],
      "engines": [
        {
          "name": "cordova",
          "version": ">=3.0.0"
        }
      ],
      "author": "zhouxingxing",
      "license": "MIT"
    }
    Is this OK? (yes) //回車就好
    
  2. 創(chuàng)建一個用來測試插件的Cordova項目:

$ cordova create TestCordovaPlugin
$ cd TestCordovaPlugin/
$ cordova platform add ios android
  1. 進入你上面創(chuàng)建的, 然后從本地添加你的插件:
$ Cordova plugin add /Users/developer_zxx/Desktop/cordova-plugin-zxxToast/ZxxToast

運行上面命令后, 打開TestCordovaPlugin項目, 在plugins/下發(fā)現(xiàn)了你開房的創(chuàng)建, 說明已經(jīng)安裝好了

15452699436240.jpg

  1. 編寫測試代碼, 打開TestCordovaPlugin根目錄www/下的index.html文件,添加一按鈕<button onclick="window.app.showShortTop()">Toast showLongBottom</button>:
    <!DOCTYPE html>
<html>
    <head>
        
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Hello World</title>
    </head>
    <body>
        <div class="app">
            <h1>Apache Cordova</h1>
            <div id="deviceready" class="blink">
                <p class="event listening">Connecting to Device</p>
                <p class="event received">Device is Ready</p>
            </div>
            <button onclick="window.app.showShortTop()">Toast showLongBottom</button> //在首頁添加測試按鈕

        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript" src="js/Toast.js"></script>
    </body>
</html>

15452714151725.jpg
  1. 打開www/js/下的index.js文件, 在里面直接引用插件的js接口:
    var app = {
    // Application Constructor
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
    },

    // deviceready Event Handler
    //
    // Bind any cordova events here. Common events are:
    // 'pause', 'resume', etc.
    onDeviceReady: function() {
        this.receivedEvent('deviceready');
    },

    // 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);
        //測試
        window.plugins.ZxxToast.show('Hello World!!!','4','bottom' ,function(a){
        console.log('toast success: ' + a)
        }, function(b){
        alert('toast error: ' + b)
        })
    }
};
app.initialize();
  1. 使用cordova run ios運行項目, 看效果:
15452738469378.jpg
  1. 然后你可以使用Xcode打開platforms/ios/下的項目進行調(diào)試, 你對下圖標記的文件就行修改調(diào)試, 調(diào)好后, 將修改同步到插件中即可:
    15452741342015.jpg

原因安卓平臺的插件開發(fā)和發(fā)布, 和iOS類似, 只是語言和開發(fā)環(huán)境變了, 可以參考下面的文章:

  1. 使用plugman創(chuàng)建插件-android:https://blog.csdn.net/u014284625/article/details/79922677
  2. apache-cordova官方文檔:https://cordova.apache.org/docs/en/latest/

三. 發(fā)布插件

插件的js接口, 原生代碼都已經(jīng)實現(xiàn)了, 那么你測好后, 就可以發(fā)布該插件了

你可以將插件發(fā)布到任何基于npmjs的注冊處, 但推薦的是npm注冊處. 這樣其他開發(fā)者能夠使用plugman或cordova-cli來自動安裝你的插件.

  1. 為了發(fā)布插件到npm, 你需要按照下面步驟:

    • 安裝plugmanCLI:
    $ npm install -g plugman
    
    • 為你的插件創(chuàng)建一個package.json文件:
    $ plugman createpackagejson /path/to/your/plugin
    
    • 發(fā)布
    $ npm  adduser #假如你現(xiàn)在還沒有賬號
    $ npm  pbulish /path/to/your/plugin
    

    更多關(guān)于npm使用方法, 請參考npm文檔中心的Publishing npm Packages

  2. 使用npm pbulish之前, 需要你將你的插件代碼上傳到github上面, 這樣你可以使用Git管理對你的插件進行版本控制, cordova-cli也可以直接使用Git url來下載你的插件.

四. 關(guān)于iOSWKWebView的使用

由于iOS8 Apple開始推薦使用更先進的WKWebView, 所以在iOS的最新的版本中, 我們不得不使用WKWebView, Cordova默認支持UIWebView. 而想要使用WKWebView的話就需要使用核心插件cordova-plugin-wkwebview-engine

使用方法:
這個插件要求cordova的版本>4.0.0

  1. 安裝發(fā)布版本:
$ cordova create wkwvtest my.project.id wkwvtest
$ cd wkwvtest
$ cordova platform add ios@4
$ cordova plugin add cordova-plugin-wkwebview-engine
  1. 安裝測試版本:
cordova create wkwvtest my.project.id wkwvtest
cd wkwvtest
cordova platform add https://github.com/apache/cordova-ios.git#master
cordova plugin add https://github.com/apache/cordova-plugin-wkwebview-engine.git#master

但是這個插件依然有些問題, 在Stack Overflow網(wǎng)站查資料時, 有人推薦使用cordova-plugin-ionic-webview

參考文檔

  1. iOS原生項目嵌入Cordova:https://blog.csdn.net/yl19920713/article/details/78487149
  2. 如何在原生工程中引入Cordova工程: https://blog.csdn.net/e20914053/article/details/50170487
  3. 手動創(chuàng)建插件目錄:http://www.cocoachina.com/ios/20180608/23718.html
  4. 使用plugman創(chuàng)建插件-ios:https://blog.csdn.net/u014284625/article/details/80699275
  5. 使用plugman創(chuàng)建插件-android:https://blog.csdn.net/u014284625/article/details/79922677
  6. apache-cordova官方文檔:https://cordova.apache.org/docs/en/latest/
  7. 創(chuàng)建并調(diào)試Cordova插件:https://www.outsystems.com/blog/posts/how-to-create-a-cordova-plugin-from-scratch/
  8. 如何測試插件:https://kerrishotts.github.io/pgday/workshops/2017/campp/testing.html
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 導語 這篇文章主要介紹了如何在Android平臺上使用Cordova 的command-line interfac...
    jorstinchan閱讀 22,832評論 6 41
  • 導語 Apache Cordova是一個開源的移動開發(fā)框架。允許你用標準的web技術(shù)-HTML5,CSS3和Jav...
    ApolloGuibo閱讀 4,545評論 2 9
  • 開篇簡言 我是一名前端工程師,剛剛完成了一個基于cordova的webapp,并且安卓和蘋果雙端都已上線,趁熱寫個...
    Lucy_Lucy閱讀 6,132評論 6 18
  • 黑咕隆咚的夜,鄰居家的黑貓再忍受不了女主人的聒噪,跑到我這邊串門來了。 黑色的爪子在沉沉夜幕里試探著前進,他小心翼...
    盞雪閱讀 628評論 15 1
  • 日精進打卡 【知~學習】 【經(jīng)典 不滿足于現(xiàn)狀,總想做得更好,總想不斷提升自己,有沒有這種"想法"或許就是"成功"...
    J0hn先生閱讀 214評論 0 0

友情鏈接更多精彩內(nèi)容