Apache Cordova 教程:使用 Cordova 開發移動應用程序
已發表: 2022-03-11移動應用程序無處不在,從智能手機和平板電腦到智能手錶,很快也會出現在其他可穿戴設備中。 但是,為每個單獨的移動平台進行開發可能是一項艱鉅的任務,尤其是在您的資源有限,或者您是單個開發人員而不是移動應用程序開發公司的情況下。
這就是成為精通 Apache Cordova 開發人員可以派上用場的地方,因為它提供了一種使用標準 Web 技術(HTML5、CSS3 和 JavaScript)開發移動應用程序的方法。
2009 年,一家名為 Nitobi 的初創公司創建了 PhoneGap,這是一個用於訪問本地移動資源的開源 API,其目標是使開發人員能夠使用標準 Web 技術創建移動應用程序。 在 Nitobi 的設想中,大多數移動應用程序很快就會使用 PhoneGap 開發,但開發人員仍然可以在必要時選擇編寫本機代碼,無論是由於性能問題,還是缺乏訪問特定硬件的方法。
科爾多瓦PhoneGap?
沒有這樣的事,真的。 發生的事情是,Adobe 在 2011 年收購了 Nitobi,並將開源核心捐贈給了 Apache 軟件基金會,後者將其重新命名為 Apache Cordova。 您經常遇到的一個常見類比是,Cordova 之於 PhoneGap,就像 WebKit 之於 Chrome 或 Safari。
顯然,Cordova 和 PhoneGap 之間的差異在一開始是微乎其微的。 隨著時間的推移,Adobe PhoneGap 開發了自己的一組專有功能,而 Cordova 曾經——現在仍然——得到開源社區的支持。 本 Apache Cordova 評論和教程將更詳細地研究 Cordova 應用程序開發,雖然其中一些可能適用於 PhoneGap,但本質上不應將其視為 PhoneGap 教程。
Apache Cordova 功能
本質上,Cordova 對於本地開發的應用程序沒有任何限制。 使用 Cordova 獲得的只是一個 JavaScript API,它充當本機代碼的包裝器,並且跨設備保持一致。 您可以將 Cordova 視為具有 Web 視圖的應用程序容器,它覆蓋了設備的整個屏幕。 Cordova 使用的 Web 視圖與本機操作系統使用的 Web 視圖相同。 在 iOS 上,這是默認的 Objective-C UIWebView
或自定義的WKWebView
類; 在 Android 上,這是android.webkit.WebView
。
Apache Cordova 帶有一組預先開發的插件,可以訪問設備的相機、GPS、文件系統等。隨著移動設備的發展,添加對附加硬件的支持只是開發新插件的問題。
最後,Cordova 應用程序就像本地應用程序一樣安裝。 這意味著為 iOS 構建代碼將生成 IPA 文件,為 Android 構建 APK 文件,為 Windows Phone 構建代碼將生成 XAP 文件。 如果您在開發過程中投入足夠的精力,您的用戶甚至可能沒有意識到他們沒有使用本機應用程序。
Apache Cordova 開發工作流程
使用 Cordova 進行開發時,您可以遵循兩條基本路徑:
- 當您打算將應用程序部署到盡可能多的平台時,很少或沒有特定於平台的開發,您應該使用跨平台工作流。 支持此工作流的主要工具是 Cordova 命令行界面 (CLI),它用作更高級別的抽象,用於為不同平台配置和構建應用程序。 這是比較常用的開發路徑。
- 如果您計劃在考慮特定平台的情況下開發應用程序,則應使用以平台為中心的工作流程。 這樣,您將能夠通過將本機組件與 Cordova 組件混合,在較低級別調整和修改您的代碼。 即使您可以使用這種方法進行跨平台開發,但過程會更長,更乏味。
通常建議從跨平台開發工作流程開始,因為切換到以平台為中心的開發相當簡單。 但是,如果您最初從以平台為中心的工作流程開始,您將無法切換到跨平台開發,因為一旦您運行構建過程,CLI 將覆蓋您的自定義設置。
先決條件和 Cordova 安裝
在安裝和運行與 Cordova 相關的任何內容之前,您需要為您打算為其構建應用程序的每個平台安裝 SDK。 本文將重點介紹Android平台; 但是,涉及其他平台的過程是相似的。
您應該下載此處找到的 Android SDK。 對於 Windows,SDK 以安裝程序的形式提供,而對於 Linux 和 OSX,它以存檔的形式提供,可以簡單地提取。 解壓/安裝軟件包後,您需要將sdk/tools
和sdk/platform-tools
目錄添加到PATH
變量中。 Cordova 使用PATH
變量來查找構建過程所需的二進製文件。 如果您沒有安裝 Java,您應該繼續安裝 JDK 和 Ant。 ANT_HOME
和JAVA_HOME
應設置為 JDK 和 Ant 的 bin 文件夾,安裝 Android SDK 後,將ANDROID_HOME
變量設置為Android/Sdk
。 三個*_HOME
變量中的所有位置也應該在您的PATH
變量中。
安裝 SDK 後, android
命令將在您的命令行中可用。 執行它以打開 SDK 管理器並安裝最新的工具和 Android API。 您可能需要Android SDK 工具、Android SDK 平台工具、Android SDK 構建工具、SDK 平台、Google API 英特爾 x86 Atom 系統映像、Android SDK 源和英特爾 x86 仿真器加速器(HAXM 安裝程序) 。 之後,您將能夠使用android avd
創建一個模擬器。
Cordova CLI 依賴於 Node.js 和 Git 客戶端,因此請繼續從 nodejs.org 下載並安裝 Node,從 git-scm.com 下載並安裝 Git。 您將使用 npm 安裝 Cordova CLI 本身以及安裝其他插件,並且 Cordova 將在後台使用 git 以下載所需的依賴項。 最後,運行
npm install -g cordova
…全局安裝 Cordova CLI( npm install cordova
本身是不夠的。)
總而言之,這些是您將需要的軟件包:
- 爪哇
- 螞蟻
- 安卓 SDK
- 節點JS
- 吉特
這些環境變量需要更新:
-
PATH
-
JAVA_HOME
-
ANT_HOME
-
ANDROID_HOME
引導應用程序
如果您已成功安裝 Cordova,您現在應該可以訪問 Cordova 命令行實用程序。 打開您的終端或命令行,然後導航到您要創建第一個 Cordova 項目的目錄。 要引導應用程序,請鍵入以下命令:
cordova create toptal toptal.hello HelloToptal
命令行由命令cordova
的名稱和子命令create
組成。 使用三個附加參數調用該子命令:將放置應用程序的文件夾、應用程序的命名空間及其顯示名稱。 這會在具有以下結構的文件夾中引導應用程序:
toptal/ |-- hooks/ |-- platforms/ |-- plugins/ |-- www/ `-- config.xml
www
文件夾包含您的應用程序核心。 這是您放置所有平台通用的應用程序代碼的地方。
雖然 Cordova 允許您輕鬆開發適用於不同平台的應用程序,但有時您需要添加自定義項。 在為多個平台開發時,您不想修改各種platforms/[platform-name][assets]/www
目錄中的源文件,因為它們經常被頂級www
文件覆蓋。
此時,您還可以打開config.xml
文件並更改應用程序的元數據,例如作者和描述。
使用以下方法添加您的第一個平台:
cordova platform add android
如果您稍後改變主意,您可以輕鬆地從構建過程中刪除一個平台:
cordova platform rm android
檢查平台目錄後,您會注意到其中的android
文件夾。 對於您添加的每個平台,Cordova 將在平台中創建一個新目錄並複制其中的www
文件夾。 例如,如果您想為 Android 定制您的應用程序,您可以修改platforms/android/assets/www
中的文件並切換到特定於平台的shell 工具。
但是,請記住,如果您使用 CLI(用於跨平台開發)重新構建應用程序,Cordova 將覆蓋您為每個平台所做的更改,因此請確保您將它們置於版本控制之下,或者您執行特定於平台的操作完成跨平台開發後的變化。 正如我們前面提到的,從跨平台遷移到特定於平台的開發很容易。 朝另一個方向發展則不然。
如果您想繼續使用跨平台工作流程並仍然進行特定於平台的自定義,您應該使用頂級合併文件夾。 從 Cordova 版本 3.5 開始,此文件夾已從默認應用程序模板中刪除,但如果您需要它,您可以在其他頂級目錄( hooks
、 platforms
、 plugins
和www
)旁邊簡單地創建它。
特定於平台的自定義放在merges/[platform-name]
中,並在頂級www
文件夾中的源文件之後應用。 這樣,您可以為某些平台添加新的源文件,也可以用特定於平台的源文件覆蓋整個頂級源文件。 以下面的結構為例:
merges/ |-- wp8/ | `-- app.js |-- android/ | `-- android.js |-- www/ `-- app.js
在這種情況下,Android 的輸出文件將包含app.js
和android.js
文件,但 Windows Phone 8 的輸出文件將僅包含在 merges merges/wp8
文件夾中找到的app.js
文件,因為merges/[platform]
中的文件會覆蓋www
中的文件。
plugins 目錄包含每個平台的插件的信息。 此時,您應該只有android.json
文件,該文件應具有以下結構:
{ "prepare_queue": { "installed": [], "uninstalled": [] }, "config_munge": { "files": {} }, "installed_plugins": {}, "dependent_plugins": {} }
讓我們構建應用程序並將其部署到 Android 設備。 如果需要,您也可以使用模擬器。
Cordova 提供了幾個 CLI 步驟來構建和運行您的應用程序: cordova prepare
、 cordova compile
、 cordova build
(這是前兩個的快捷方式)、 cordova emulate
和cordova run
(它包含build
並且也可以運行模擬器)。 這不應該讓您感到困惑,因為在大多數情況下,您希望在模擬器中構建和運行您的應用程序:
cordova run --emulator
如果需要,您可以通過 USB 端口插入您的設備,啟用 USB 調試模式並將您的第一個 Apache Cordova 應用程序直接部署到您的設備上,只需運行:
cordova run
這會將您的所有文件複製到platforms/*
並執行所有必需的任務。
您可以通過指定要為其構建應用程序和/或什至特定模擬器的平台的名稱來限制構建過程的範圍,例如:
cordova run android --emulator
要么
cordova run ios --emulator --target="iPhone-8-Plus"
動手實踐 Apache Cordova 教程
讓我們創建一個簡單的教程應用程序來演示 Cordova 及其插件的使用。 整個演示可以在這個 GitHub 存儲庫中找到,以便您可以下載它並通過這個簡短的 Cordova 教程來瀏覽它的一部分。
我們將使用您創建的初始設置並添加其他代碼。 假設我們想將新項目添加到虛構的 Toptal 數據庫中,並查看現有項目。 打開 index.html 並按以下方式設置兩個選項卡:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <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, height=device-height, target-densitydpi=device-dpi" /> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" /> <link rel="stylesheet" href="css/jquery.mobile-1.4.5.min.css" /> <link rel="stylesheet" type="text/css" href="css/toptal.css" /> <title>Hello Toptal</title> </head> <body> <div> <div> </div> </div> <footer> <ul> <li class="tab-button active" data-tab="#search-tab">Search Projects</li> <li class="tab-button" data-tab="#add-tab">Post a Project</li> </ul> </footer> <div></div> <script src="js/lib/jquery-1.11.1.min.js"></script> <script src="js/lib/jquery.mobile-1.4.5.min.js"></script> <script type="text/javascript" src="cordova.js"></script> <script type="text/javascript" src="js/SQLiteStorageService.js"></script> <script type="text/javascript" src="js/Controller.js"></script> <script type="text/javascript" src="js/index.js"></script> </body> </html>
請注意,我添加了 Bootstrap 和 jQuery Mobile 作為依賴項。 請注意,已經為構建現代混合應用程序開發了更好的解決方案和框架,但是由於大多數(如果不是全部)Web 開發人員都熟悉這兩個庫,因此將它們用於初學者教程是有意義的。 如果您願意,可以從 GitHub 下載樣式表或使用您自己的樣式表。
讓我們移動到index.js
文件,並將其剝離為以下內容:
var app = { // Application Constructor initialize: function() { if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) { document.addEventListener("deviceready", this.onDeviceReady, false); } else { this.onDeviceReady(); } }, onDeviceReady: function() { // We will init / bootstrap our application here }, }; app.initialize();
請記住,Cordova 應用程序所提倡的架構是設置單頁應用程序 (SPA)。 這樣,所有資源只在應用程序啟動時加載一次,並且只要應用程序運行,就可以一直停留在 Web 視圖中。 此外,使用 SPA,用戶將不會有頁面重新加載,這對於本機應用程序來說並不典型。 記住這一點,讓我們設置一個簡單的控制器來在兩個選項卡之間切換:
var Controller = function() { var controller = { self: null, initialize: function() { self = this; this.bindEvents(); self.renderSearchView(); }, bindEvents: function() { $('.tab-button').on('click', this.onTabClick); }, onTabClick: function(e) { e.preventDefault(); if ($(this).hasClass('active')) { return; } var tab = $(this).data('tab'); if (tab === '#add-tab') { self.renderPostView(); } else { self.renderSearchView(); } }, renderPostView: function() { $('.tab-button').removeClass('active'); $('#post-tab-button').addClass('active'); var $tab = $('#tab-content'); $tab.empty(); $("#tab-content").load("./views/post-project-view.html", function(data) { $('#tab-content').find('#post-project-form').on('submit', self.postProject); }); }, renderSearchView: function() { $('.tab-button').removeClass('active'); $('#search-tab-button').addClass('active'); var $tab = $('#tab-content'); $tab.empty(); var $projectTemplate = null; $("#tab-content").load("./views/search-project-view.html", function(data) { $projectTemplate = $('.project').remove(); // Load projects here }); } } controller.initialize(); return controller; }
到目前為止,控制器有兩種方法,一種用於渲染 Search View,另一種用於渲染 Post Project 視圖。 讓我們在index.js
文件中初始化它,首先在頂部聲明它並在 onDeviceReady 方法中構造它:

// top of index.js var controller = null
// inside onDeviceReady method controller = new Controller();
最後,在index.html
的index.js
引用上方添加一個腳本引用。 您可以直接從 GitHub 下載 Search 和 Post 視圖。 由於部分視圖是從文件中讀取的,因此某些瀏覽器(例如 Chrome)在嘗試呈現您的頁面時會抱怨跨域請求。
這裡可能的解決方案是運行本地靜態服務器,例如使用node-static
npm 模塊。 此外,在這裡您可以開始考慮使用一些框架,例如 PhoneGap 和/或 Ionic。 它們都提供了一系列開發工具,包括在瀏覽器中模擬、熱重載和代碼生成(腳手架)。
現在,讓我們通過運行以下命令簡單地部署到 Android 設備:
cordova run android
此時,您的應用程序應該有兩個選項卡。 第一個選項卡允許搜索項目:
第二個選項卡允許發布新項目:
我們現在所擁有的只是一個在 Web 視圖中運行的經典 Web 應用程序。 我們還沒有真正使用過任何本機功能,所以讓我們現在嘗試這樣做。 一個常見的問題是如何在設備上本地存儲數據,或者更準確地說,使用什麼類型的存儲。 有幾種方法可以去:
- 本地存儲
- WebSQL
- 索引數據庫
- 通過 Web 服務訪問的服務器端存儲
- 提供其他選項的第三方插件
LocalStorage 可以存儲少量數據,但如果您正在構建數據密集型應用程序,它就不夠了,因為可用空間從 3 MB 到 10 MB 不等。 對於這種情況,IndexedDB 可能是更好的解決方案。 WebSQL 已被棄用,並且在某些平台上不受支持。 最後,使用 Web 服務來獲取和修改數據非常適合 SPA 範式,但是當您的應用程序脫機時它就會崩潰。 PWA 技術和 Service Worker 最近已進入 Cordova 世界以幫助解決此問題。
此外,還有許多額外的第三方插件可以填補 Cordova 核心的空白。 File 插件可能非常有用,因為它可以讓您訪問設備的文件系統,從而允許您創建和存儲文件。 現在,讓我們試試 SQLitePlugin,它為您提供本地 SQLite 數據庫。 您可以通過運行將其添加到您的項目中:
cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin
SQLitePlugin 為設備的 SQLite 數據庫提供 API,並作為真正的持久性機制。 我們可以通過以下方式創建一個簡單的存儲服務:
SQLiteStorageService = function () { var service = {}; var db = window.sqlitePlugin ? window.sqlitePlugin.openDatabase({name: "demo.toptal", location: "default"}) : window.openDatabase("demo.toptal", "1.0", "DB para FactAV", 5000000); service.initialize = function() { // Initialize the database var deferred = $.Deferred(); db.transaction(function(tx) { tx.executeSql( 'CREATE TABLE IF NOT EXISTS projects ' + '(id integer primary key, name text, company text, description text, latitude real, longitude real)' ,[], function(tx, res) { tx.executeSql('DELETE FROM projects', [], function(tx, res) { deferred.resolve(service); }, function(tx, res) { deferred.reject('Error initializing database'); }); }, function(tx, res) { deferred.reject('Error initializing database'); }); }); return deferred.promise(); } service.getProjects = function() { // fetch projects } service.addProject = function(name, company, description, addLocation) { // add a new project } return service.initialize(); }
您可以從 GitHub 下載用於獲取和添加項目的代碼,並將其粘貼到相應的佔位符中。 不要忘記將 SQLiteStorageService.js 添加到 Controller.js 上方的 index.html 文件中,並通過修改 Controller 的 init 函數在控制器中對其進行初始化:
initialize: function() { self = this; new SQLiteStorageService().done(function(service) { self.storageService = service; self.bindEvents(); self.renderSearchView(); }).fail(function(error) { alert(error); }); }
如果您看一下 service.addProject(),您會注意到它調用了 navigator.geolocation.getCurrentPosition() 方法。 Cordova 有一個地理定位插件,您可以使用它來獲取手機的當前位置,您甚至可以使用 navigator.geolocation.watchPosition() 方法在用戶位置發生變化時接收更新。
最後,讓我們添加控制器事件句柄,以便從數據庫中添加和獲取項目:
renderPostView: function() { $('.tab-button').removeClass('active'); $('#post-tab-button').addClass('active'); var $tab = $('#tab-content'); $tab.empty(); $("#tab-content").load("./views/post-project-view.html", function(data) { $('#tab-content').find('#post-project-form').on('submit', self.postProject); }); }, postProject: function(e) { e.preventDefault(); var name = $('#project-name').val(); var description = $('#project-description').val(); var company = $('#company').val(); var addLocation = $('#include-location').is(':checked'); if (!name || !description || !company) { alert('Please fill in all fields'); return; } else { var result = self.storageService.addProject( name, company, description, addLocation); result.done(function() { alert('Project successfully added'); self.renderSearchView(); }).fail(function(error) { alert(error); }); } }, renderSearchView: function() { $('.tab-button').removeClass('active'); $('#search-tab-button').addClass('active'); var $tab = $('#tab-content'); $tab.empty(); var $projectTemplate = null; $("#tab-content").load("./views/search-project-view.html", function(data) { $('#addressSearch').on('click', function() { alert('Not implemented'); }); $projectTemplate = $('.project').remove(); var projects = self.storageService.getProjects().done(function(projects) { for(var idx in projects) { var $div = $projectTemplate.clone(); var project = projects[idx]; $div.find('.project-name').text(project.name); $div.find('.project-company').text(project.company); $div.find('.project-description').text(project.description); if (project.location) { var url = '<a target="_blank" href="https://www.google.com.au/maps/preview/@' + project.location.latitude + ',' + project.location.longitude + ',10z">Click to open map</a>'; $div.find('.project-location').html(url); } else { $div.find('.project-location').text("Not specified"); } $tab.append($div); } }).fail(function(error) { alert(error); }); }); }
要添加控制台和對話框插件,請執行以下命令:
cordova plugin add org.apache.cordova.dialogs cordova plugin add org.apache.cordova.console
cordova.console 插件將通過在模擬器中啟用console.log()
功能來幫助您進行調試。
您可以通過 Chrome 遠程調試器輕鬆調試 Android 應用程序。 連接設備後,單擊右上角(X 按鈕下方)的下拉菜單,展開更多工具,然後單擊檢查設備。 您應該會在列表中看到您的設備,並且應該能夠打開其調試控制台。
Safari 為調試在 USB 連接的設備或模擬器上運行的 iOS 應用程序提供了相同的功能。 只需在 Safari 設置 > 高級選項卡下啟用開發人員工具。
cordova.dialogs 插件啟用本機通知。 一種常見的做法是使用 cordova.dialogs API 以下列方式重新定義windows.alert
方法:
overrideBrowserAlert: function() { if (navigator.notification) { // Override default HTML alert with native dialog window.alert = function (message) { navigator.notification.alert( message, // message null, // callback "Toptal", // title 'OK' // buttonName ); }; } }
應該在deviceready
事件處理程序中調用overrideBrowserAlert
函數。
您現在應該能夠添加新項目並從數據庫中查看現有項目。 如果您選中“包括位置”複選框,設備將調用 Geolocation API 並將您的當前位置添加到項目中。
讓我們通過設置圖標和啟動畫面來為應用程序添加點睛之筆。 將以下內容添加到您的config.xml
文件中:
<platform name="android"> <icon src="www/img/logo.png" /> <splash src="www/img/logo.png" density="mdpi"/> <splash src="www/img/logo.png" density="hdpi"/> <splash src="www/img/logo.png" density="xhdpi"/> </platform>
最後,在www/img
文件夾中放置一個徽標圖像。
您自己的 Cordova 應用程序
我們完成了 Apache Cordova 應用程序開發的基本步驟,並使用了我們自己的 JavaScript 架構和 CSS 樣式表。 本 Cordova 教程試圖展示 Apache Cordova 作為一種使用熟悉技術開發移動應用程序的方法的潛力,從而減少開發時間和為不同平台構建多個應用程序所需的工作量。
但是,在構建將要投入生產的應用程序時,建議您使用現有框架。 除了在預定義的體系結構中構建您的應用程序之外,這還可能為您提供一組組件,這些組件將幫助您的應用程序更接近原生的外觀和感覺。 一些值得注意的框架是 Ionic、Framework7、Weex、Ratchet、Kendo UI 和 Onsen UI。 祝你好運!