1. 程式人生 > >ionic和ionic2 環境下編寫自定義cordova外掛

ionic和ionic2 環境下編寫自定義cordova外掛

1 增加android的平臺

對於一個ionic專案,在主目錄下通過以下命令列增加android平臺。

cordova platform add android

然後在platforms目錄下就會出現一個android資料夾:

android directory

之後可以使用配置了android開發環境的eclipse選中上圖android目錄開啟該專案;也可以使用Android Studio開啟上圖android目錄,這時候需要要配置gradle,直接選擇確定下載即可(此時建議開啟全域性代理),注意專案的路徑中不能含有非ascii碼字元(例如中文),否則gradle會build失敗。

本例使用Android Studio來演示,eclipse環境下只要找到對應的檔案即可。

2 使用Android Studio開發外掛原始碼

2.1 介紹專案目錄

開啟專案後,專案目錄如下:

android project

該專案有兩個模組,第一個是CordovaLib,裡面是cordova庫的程式碼,我們就不用管了(如果是用eclipse開啟這會顯示為一個單獨的專案)

第二個模組便是我們自己的專案了,就如普通的android專案目錄一樣。我們在專案主目錄WWW目錄下的程式碼都被原封不動的拷貝到assets/www目錄下,又額外添加了一些cordova js庫,這些檔案我們也不用管。

2.2 開發外掛原始碼

如下圖,新建一個org.apache.cordova.hello包,改包名可隨意取。然後在改包下新建一個HelloPlugin.java檔案:

Hello Plugin

HelloPlugin的程式碼如下:

package org.apache.cordova.hello;

import android.widget.Toast;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;

/**
 * Created by duocai on 2017/4/10.
 */
//所有的自定義plugin都需要繼承CordovaPlugin這個類
public class HelloPlugin extends CordovaPlugin { //然後需要複寫這個execute方法 @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (action.equals("hello")) { String text = ""; for (int i = 0; i < args.length(); i++) { text += args.getString(i) + "\n"; //這取決於js程式碼傳進來的引數型別。 } Toast.makeText(this.cordova.getActivity(), text, Toast.LENGTH_LONG).show(); callbackContext.success("success: " + text);//使用回掉的方法,返回資訊 //callbackContext.error("dd"); //對應有返回錯誤的方法 return true; } return false; } }

execute有三個引數,這個對應js的呼叫程式碼會更好理解(詳見2.4部分):

cordova.exec(callbackContext.success, callbackContext.error, PluginName, action, args);

其中action就對應action;args在js端就是普通的js陣列;callbackContext.success, callbackContext.error分別是成功和失敗時的兩個回掉函式,前面java程式碼中:

callbackContext.success("success: " + text);//使用回掉的方法,返回資訊

這一行就呼叫了第一個回掉函式。

PluginName的意義就是指定了當前的java檔案(詳見2.3本分)

2.3 在配置檔案中配置HelloPlugin:

2.1的目錄結構中,我們可以看到res/xml目錄下有一個config.xml配置檔案,開啟檔案增加配置如下:

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.ionicframework.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <!-- xmlns若是報找不到檔案錯誤也不用管-->
    <name>HelloCordova</name>
    <description>
        An Ionic Framework and Cordova project.
    </description>
    <author email="[email protected]" href="http://example.com.com/">
      Your Name Here
    </author>
    <content src="index.html" />
    <access origin="*" />
    <preference name="loglevel" value="DEBUG" />
    <preference name="webviewbounce" value="false" />
    <preference name="UIWebViewBounce" value="false" />
    <preference name="DisallowOverscroll" value="true" />
    <preference name="SplashScreenDelay" value="2000" />
    <preference name="FadeSplashScreenDuration" value="2000" />
    <preference name="android-minSdkVersion" value="16" />
    <preference name="BackupWebStorage" value="none" />
    <!-- 前面為自動生成,含義由名字可以看出個大概>

    <!--新增配置檔案 name="HelloPlugin"指定了js端呼叫時需要傳遞的PluginName引數-->
    <feature name="HelloPlugin">
      <!--value的值為剛剛開發的HelloPlugin檔案的路徑-->
      <param name="android-package" value="org.apache.cordova.hello.HelloPlugin" />
    </feature>

</widget>

2.4 通過js程式碼呼叫外掛

/**
 * Created by duocai on 2016/9/6.
 */
angular.module('ctrl.camera', [])

  .controller('CameraCtrl', function($scope) {
    var success = function(data) {
      alert(data);
    }

    //引數與前面的java程式碼對應如下
    //js: cordova.exec(callbackContext.success, callbackContext.error, PluginName, action, args);
    //java: public boolean execute(String action, JSONArray args, CallbackContext callbackContext)
    // 此外 js 多餘的 PluginName 在2.3的配置檔案中配置
    //<feature name="HelloPlugin"> // PluginName
      //<param name="android-package" value="org.apache.cordova.hello.HelloPlugin" />
    //</feature>
    cordova.exec(success, null, "HelloPlugin", "hello", ["hello", "world", "!!!"]);
  });

其餘沒有註釋的部分是angular controller的語法,就不再贅述。

至此就利用cordova的庫完成了通過js程式碼呼叫原生java程式碼。

2.5 效果演示

demo

其中下面小黑框是java程式碼的輸出,上面大黑框是js程式碼的輸出。

3 配置為符合ionic外掛格式的外掛

我們都知道使用在開發ionic專案時,是不需要上面那樣在android studio中使用外掛的。這是cordova 的外掛進行了進一步的封裝,知道了上面的過程後,我們就知道ionic的外掛格式要求到底幹了什麼事。

在開發之前需要做一點準備,每次執行cordova build android 的時候,都會複寫platforms/android目錄下檔案。所以我們將剛剛的android專案目錄改名為android plugin development。然後在執行:

cordova platform add android

來增加 android 平臺

3.1 外掛目錄

my plugin

按上圖所示建一個外掛目錄。src和www無所謂怎麼建,但這樣建條理更清晰,plugin.xml一定要在其所在的位置。

3.2 各個檔案內容

  1. HelloPlugin.java就是上面的檔案直接拷貝過來即可

  2. plugin.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <plugin id="org.cordova.HelloPlugin" version="0.0.1"
            xmlns="http://apache.org/cordova/ns/plugins/1.0"
            xmlns:android="http://schemas.android.com/apk/res/android">
      <name>HelloPlugin</name>
      <description>Description</description>
    
      <!-- js 部分 -->
      <!-- plugin 'org.cordova.HelloPlugin'(看上面id) 下 定義module HelloPlugin -->
      <!-- 配置後會將HelloPlugin.js配置到android專案assets/www/plugins 目錄下,做了語法補充完整,
        有興趣可以自己開啟看看 -->
      <js-module name="HelloPlugin" src="www/HelloPlugin.js">
        <clobbers target="HelloPlugin"/>
      </js-module>
    
      <!--android 部分就是
      1. 在第2部分提到的res/xml/config.xml新增plugin配置
      2. 將對應的檔案拷貝到對應的目錄下-->
      <platform name="android">
        <config-file parent="/*" target="res/xml/config.xml">
          <!--新增配置檔案 name="HelloPlugin"指定了js端呼叫時需要傳遞的名稱引數-->
          <feature name="HelloPlugin">
            <!--value的值為剛剛開發的HelloPlugin檔案的路徑-->
            <param name="android-package" value="org.apache.cordova.hello.HelloPlugin" />
          </feature>
        </config-file>
        <source-file src="src/android/HelloPlugin.java" target-dir="src/org/apache/cordova/hello"/>
      </platform>
    </plugin>
  3. HelloPlugin.js

    /**
    * Created by admin on 2017/4/10.
    */
    var exec = require('cordova/exec');
    
     // 符合格式要求可在其它js檔案中呼叫該模組
     module.exports = {
    
       show: function (message) {
      //基本上等同於前面第2部分所說的cordova.exec()
         exec(null,null, "HelloPlugin", "hello", [message]);
       }
    
     };
  4. 呼叫外掛,依然以前面的CameraCtrl為例

      /**
    * Created by duocai on 2016/4/10.
    */
    angular.module('ctrl.camera', [])
    
     .controller('CameraCtrl', function($scope) {
       HelloPlugin.show("hello world !!!") // HelloPlugin在前面的plugin.xml裡配置
     });

3.3 執行結果

demo

4 進一步分析

  1. 比較第二部分和第三部分,如果是要自己寫外掛的化,不如待到前端寫的差不多了,然後直接轉移到android studio專案來寫,如第二部分那樣擴充套件原生程式碼,並通過js呼叫。修改少量的js程式碼和html。這樣做使得擴充套件功能變得簡單,但是這樣做的後果是沒有多平臺。
  2. 比較第二部分和第三部分,可以得出js-module不是必須配置的,配置之後則可以使用cordova進一步封裝的語法來呼叫。針對於自己的外掛,我們可以直接呼叫cordova.exec(), 但是這樣做的後果是模組不分離。

5 對於ionic2的說明【2017-6-22更新】

angular升級到angular2,ionic也隨之升級。那麼針對於ionic2該如何使用自定義外掛呢?這裡只說使用是因為cordova並沒有升級,所以它的工作原理和外掛的編寫並不會有所改變,只是使用方式要發生變化。那麼到底如何使用呢。

  1. ionic2自帶的外掛,我看了一下使用npm管理到@ionic-native空間下,又進行了一層封裝,這對於自定義外掛來說,使用成本較高,不推薦。
  2. 在前面所說的在android studio中直接程式設計是否依然有效呢。答案當然是依然有效。Typescript在編譯時依然會編譯成js es5的語法,所以在android studio中,依然只能看到普通的js程式碼,在這裡面使用cordova.exec()方法的效果當然是與ionic1中一樣了。(但是編譯後的js檔案難讀,對程式設計不友好,這裡也不推薦使用)
  3. 除了ionic內建外掛的使用方式(這是一種好的方式)外,還有沒有其它使用方式呢,答案是有的,而且方法很多,下面會說一種推薦的方法。

下面會以ionic2 tabs樣式的初始專案做一個講解。

5.1 繼續在android stuio中編寫

當我們使用android studio如上所示開啟專案時,目錄結構依然不變,不過我們自己寫的程式碼都被編譯到assets/www/build/main.js 這個檔案中,這個檔案很長也很難閱讀,我們可以通過搜尋直接定位要修改的位置(搜尋方法名,類名之類的),例如我搜索ionic2 tabs樣式初始專案中ContactPage這個類定位到如下位置:

var ContactPage = (function () {
    function ContactPage(navCtrl) {
        this.navCtrl = navCtrl;
    }
    return ContactPage;
}());

接下來在建構函式(建構函式會在頁面初始載入時被呼叫)中新增前面2.4所說的直接呼叫(前提是要像第2部分所說的配置好)

var ContactPage = (function () {
    function ContactPage(navCtrl) {
        this.navCtrl = navCtrl;
        var success = function(data) {
          alert(data);
        }
        cordova.exec(success, null, "HelloPlugin", "hello", ["hello", "world", "!!!"]);
    }
    return ContactPage;
}());

之後,編譯執行,效果如下圖所示,與前面所展示無異。但是現在這個js檔案不像是ionic1中的直接拷貝而是編譯形成的,難以閱讀,也不可能被再複用,所以不推薦使用這種方式。僅供大家瞭解一下外掛進一步是怎麼工作的。
這裡寫圖片描述

5.3 封裝cordova外掛並在ionic2中呼叫(推薦)

封裝外掛,前面第三部分說的非常清楚,封裝方式與前面無異。額外補充一點就是前面好像忘了說明這個外掛是怎麼用的。使用方式很簡單,例如將前面HelloPlugin目錄放在當前專案的目錄下,然後使用命令列:
ionic plugin add HelloPlugin
命令格式是ionic plugin add 外掛目錄路徑,剛剛這個例子使用相對路徑。
新增好外掛後,接下來說明如何在ionic2中使用,前面已經說了使用方式有很多種,接下來說明一種推薦的,以ionic2 tabs樣式初始專案src/pages/contact/contact.ts這個元件為例,它原始如下所示:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-contact',
  templateUrl: 'contact.html'
})
export class ContactPage {

  constructor(public navCtrl: NavController) {
  }

}

然後為了使用HelloPlugin外掛,應當做如下修改:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
// 利用declare語法宣告HelloPlugin物件,不需要初始華。這個語法有點像C++裡的宣告語法。
declare let HelloPlugin;
@Component({
  selector: 'page-contact',
  templateUrl: 'contact.html'
})
export class ContactPage {

  constructor(public navCtrl: NavController) {
    // 這裡使用就像前面第三部分所說的一樣,但是為了在Typescript中使用HelloPlugin這個全域性變數,需要前面的宣告,不然typescript編譯時會報錯,因為找不到HelloPlugin
    HelloPlugin.show("hello world !!!")
  }
}

然後說面一下HelloPlugin這個變數名字是從哪裡來的。看前面3.2.2 plugin.xml配置檔案中的如下部分:

<--就是在這裡配置的-->
<js-module name="HelloPlugin" src="www/HelloPlugin.js">
        <clobbers target="HelloPlugin"/>
      </js-module>

這種使用外掛的方式非常簡單,只需在檔案的開始部分使用
declare let 物件名
來宣告這個物件就可以在typescript中直接使用,你完全可以把他當成是一種import,來引用你在外掛中定義的全域性物件。所以這是一種推薦的使用方式。
最後效果如下:
這裡寫圖片描述

5.4 剛剛的declare是怎麼工作的。

我們都知道一個html檔案如果引用了多個js檔案,那麼全域性變數在這些檔案中是可以直接相互引用的。剛剛的declare所做的事情就是:儘管我沒有初始化這個物件,但是我會在其它某個檔案中,宣告並初始化這個全域性物件,所以接下來檔案中typescript要繞過對這個物件的檢查。
我們看一下編譯後main.js檔案(前面提到過):

var ContactPage = (function () {
    function ContactPage(navCtrl) {
        this.navCtrl = navCtrl;
        // Test Hello plugin
        HelloPlugin.show("hello world !!!");
    }
    return ContactPage;
}());

然後在整個js檔案中,再也找不到第二個HelloPlugin。所以前面的declare let HelloPlugin在typescript中實現就是告知Typescript忽略接下來對Helloplugin的語法檢查,將其原封保留即可。
等到編譯成js檔案,就完全和ionic1是一樣的環境了。

5.5 最後歡迎讀者提出或指出一些問題,我有時間的時候會做出補充,謝謝!!!

相關推薦

ionicionic2 環境編寫定義cordova外掛

1 增加android的平臺 對於一個ionic專案,在主目錄下通過以下命令列增加android平臺。 cordova platform add android 然後在platforms目錄下就會出現一個android資料夾: 之後可以使用配置了

django 在自己app編寫定義sql

node2:/django/mysite#cat query_mysql.py # !/usr/bin/env python # -*- coding: utf-8 -*- from django.db import connection,transaction impo

專案實戰之日誌的使用:Jboss環境新增定義日誌

日誌介紹 日誌已經成為應用軟體中不可缺少的一部分,現在我沒發現哪個上線並且正常運營的專案沒有新增日誌;並且是否寫日誌已經成為了檢測程式設計師是否專業的一個基本品德,就像寫註釋一樣,灰常重要!Apach

ionic 呼叫定義cordova外掛

ionic 作為一個跨平臺h5框架,收到越來越多的開發人員的歡迎,如何通過ionic去呼叫原生開發的SDK?可以通過 js 呼叫cordova 外掛的方式來實現。本文通過一個簡單的例子程式,來實現通過ionic 來呼叫 原生介面。該例子通過網頁開啟原生的的一個UIViewC

為Android Studio編寫定義Gradle外掛的教程

Google已經建議Android開發全部轉向Android Studio開發,Android Studio 是使用gradle編譯、打包的,那麼問題來了,gradle可是有一堆東西...,為了徹底瞭解gradle,今天就來學習下如何寫自己的gradle外掛(當然外掛原始碼是使用groovy寫的),先看如下

ionic2中利用定義cordova外掛(Plugin)ts調iOS原生的值(iOS原生的值傳給ts)

一、安裝外掛 1、安裝plugman $npm install -g plugman 如果出現下面的錯誤,在前面加"sudo"(sudo可以將許可權提升到超級使用者級別,即Windows中的管理員)

Android與js互動(四)定義cordova外掛

首先昨天我做測試的時候js端一直無法呼叫寫在js的方法後來查了資料才知道是在index.html中使用js時 需要刪除這一行 <meta http-equiv="Content-Security-Policy" content="default-src 'self'

VSWPF定義控件的基本步驟基本代碼實現

emp don 謝謝 generic 管理器 參數 bubuko 類的屬性 typeof 一、自定義控件的基本步驟: (本示例項目名稱為:W;添加的自定義控件名稱為) 1、 在“解決方案資源管理器”窗口的項目名上: 右擊à添加à新建項(Ctrl+Shift+A)

關於nagios系統使用shell指令碼定義監控外掛編寫以及沒有實時監控圖的問題

關於nagios系統下shell自定義監控外掛的編寫、指令碼規範以及沒有實時監控圖的問題的解決辦法 在自已編寫監控外掛之前我們首先需要對nagios監控原理有一定的瞭解 Nagios的功能是監控服務和主機,但是他自身並不包括這部分功能,所有的監控、檢測功能都是通過各種外掛來完成的。 啟動Nagios後,

Hadoop完全分散式實現定義排序、分割槽分組

    經過前面一段時間的學習,簡單的單詞統計已經不能實現更多的需求,就連自帶的一些函式方法等也是跟不上節奏了;加上前面一篇MapReduce的底層執行步驟的瞭解,今天學習自定義的排序、分組、分割槽相對也特別容易。 自定義排序 自定義的排序有許多許多,根據不同的業務需

Django基礎(21): Django admin管理後臺詳解()如何定義actions, 表單美化admin

本文是Django Admin詳解系列文章的最後一篇,將重點介紹如何自定義動作(action), 如何自定義表單欄位(form fields)和美化Django admin。如果你還沒有閱讀過前面兩篇文章,建議先閱讀。 謂action及如何自定義action ac

Qt編寫定義控制元件52-顏色拉框

一、前言 這個控制元件寫了很久了,元老級別的控制元件之一,開發之初主要是自己的好幾個專案要用到,比如提供一個顏色下拉框設定對應的曲

基於jupyter lab搭建網頁程式設計環境並新增定義python kernelmatlab kernel以及plotly的使用

> 內容轉載自[我的部落格](https://blog.whuzfb.cn/blog/2020/08/02/install_jupyter_lab/) [TOC] ## 說明 即使該系統有使用者`zfb`、`root`、`test`、`ubuntu`等,下面介紹的步驟隻影響本使用者,既不需要`roo

Spring Boot如何定義Repository中的DAO方法

hibernate reat 軟件測試 bst pass update pop 後綴 mark 環境配置介紹 jdk 1.8, spring Boot 1.5.3.RELEASE, MySQL, Spring Data, JPA 問題描述 Spring Data提供了一套簡

項目版本不同導致Eclipse報錯問題——關於在JDK1.7環境中,運行JDK1.8環境編寫的項目

water 錯誤 顯示 lips 1.8 ips avi 序號 fill 本人電腦環境配置的是JDK1.7,朋友的是JDK1.8 ,我把她編的java文件導入到我電腦裏的Eclipse(LUNA版本)的時候,項目出現一個紅色嘆號,當然運行是肯定出錯了。SO我就開始了解決之旅

Tomcat使用定義錯誤頁面

tomcat html 最近在整理部分服務器的時候發現有一臺業務量並不是很大的Windows服務器可以下架了,但是目前在服務器上還有一個使用IIS的站點,知道這個站點在平時的訪問量不大,就打算做遷移,打開IIS看了下這個站點上都是html純靜態頁面,連數據庫連接的交互都沒有。好吧,這樣就簡單了,

Linux環境編寫C程序

gcc gdb Linux環境下編寫包括頭文件C程序出 一:gcc編譯鏈接用法:gcc [選項] 文件...選項:-pass-exit-codes 在某一階段退出時返回最高的錯誤碼--help 顯示此幫助說明--target-help

Confluence 6 升級定義的站點空間應用你的定義布局

Confluence當你升級你的 Confluence 到其他一個主要的 Confluence 發行版本的時候,你需要手動應用你修改過的任何全局或者空間級別的布局。除非有特殊的聲明,針對一些非主要的 Confluence 升級,你的自定義修改應該是不需要重新應用上去的。什麽是主要版本,什麽是非主要版本?主要版

Confluence 6 升級定義的站點空間獲得你的定義布局

Confluence我們建議你在對站點進行布局修改的時候,你需要為你修改的 Confluence 站點或空間布局保留所有的修改記錄。如果沒有的話,你應該可以通過下面的辦法找到你的自定義修改。這個方法將會把你對全部網站和空間級別的修改以一個單一的輸出而表現出來。從這個輸出文件,你應該能找到你修改過的自定義文件。

Hadoop生態圈-hive編寫定義函數

聲明 定義函數 責任 原創 否則 oop -h 作者 AD             Hadoop生態圈-hive編寫自定義函數                                    作者:尹正傑 版權聲明:原創作品,謝絕轉載!否則將追究法律責任。