Apache Cordova 教程:使用 Cordova 开发移动应用程序

已发表: 2022-03-11
注意:由于这是最初编写的,因此我已更新本文以使用 [email protected][email protected][email protected]

移动应用程序无处不在,从智能手机和平板电脑到智能手表,很快也会出现在其他可穿戴设备中。 但是,为每个单独的移动平台进行开发可能是一项艰巨的任务,尤其是在您的资源有限,或者您是单个开发人员而不是移动应用程序开发公司的情况下。

这就是成为精通 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 功能

Apache Cordova 开发工作流程

使用 Cordova 进行开发时,您可以遵循两条基本路径:

  • 当您打算将应用程序部署到尽可能多的平台时,很少或没有特定于平台的开发,您应该使用跨平台工作流。 支持此工作流的主要工具是 Cordova 命令行界面 (CLI),它用作更高级别的抽象,用于为不同平台配置和构建应用程序。 这是比较常用的开发路径。
  • 如果您计划在考虑特定平台的情况下开发应用程序,则应使用以平台为中心的工作流程。 这样,您将能够通过将本机组件与 Cordova 组件混合,在较低级别调整和修改您的代码。 即使您可以使用这种方法进行跨平台开发,但过程会更长,更乏味。

通常建议从跨平台开发工作流程开始,因为切换到以平台为中心的开发相当简单。 但是,如果您最初从以平台为中心的工作流程开始,您将无法切换到跨平台开发,因为一旦您运行构建过程,CLI 将覆盖您的自定义设置。

先决条件和 Cordova 安装

在安装和运行与 Cordova 相关的任何内容之前,您需要为您打算为其构建应用程序的每个平台安装 SDK。 本文将重点介绍Android平台; 但是,涉及其他平台的过程是相似的。

您应该下载此处找到的 Android SDK。 对于 Windows,SDK 以安装程序的形式提供,而对于 Linux 和 OSX,它以存档的形式提供,可以简单地提取。 解压/安装软件包后,您需要将sdk/toolssdk/platform-tools目录添加到PATH变量中。 Cordova 使用PATH变量来查找构建过程所需的二进制文件。 如果您没有安装 Java,您应该继续安装 JDK 和 Ant。 ANT_HOMEJAVA_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 开始,此文件夹已从默认应用程序模板中删除,但如果您需要它,您可以在其他顶级目录( hooksplatformspluginswww )旁边简单地创建它。

特定于平台的自定义放在merges/[platform-name]中,并在顶级www文件夹中的源文件之后应用。 这样,您可以为某些平台添加新的源文件,也可以用特定于平台的源文件覆盖整个顶级源文件。 以下面的结构为例:

 merges/ |-- wp8/ | `-- app.js |-- android/ | `-- android.js |-- www/ `-- app.js

在这种情况下,Android 的输出文件将包含app.jsandroid.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 preparecordova compilecordova build (这是前两个的快捷方式)、 cordova emulatecordova 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.htmlindex.js引用上方添加一个脚本引用。 您可以直接从 GitHub 下载 Search 和 Post 视图。 由于部分视图是从文件中读取的,因此某些浏览器(例如 Chrome)在尝试呈现您的页面时会抱怨跨域请求。

这里可能的解决方案是运行本地静态服务器,例如使用node-static npm 模块。 此外,在这里您可以开始考虑使用一些框架,例如 PhoneGap 和/或 Ionic。 它们都提供了一系列开发工具,包括在浏览器中模拟、热重载和代码生成(脚手架)。

现在,让我们通过运行以下命令简单地部署到 Android 设备:

 cordova run android

此时,您的应用程序应该有两个选项卡。 第一个选项卡允许搜索项目:

Apache Cordova 应用程序

第二个选项卡允许发布新项目:

Apache Cordova 项目发布

我们现在所拥有的只是一个在 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 移动教程应用程序

您自己的 Cordova 应用程序

我们完成了 Apache Cordova 应用程序开发的基本步骤,并使用了我们自己的 JavaScript 架构和 CSS 样式表。 本 Cordova 教程试图展示 Apache Cordova 作为一种使用熟悉技术开发移动应用程序的方法的潜力,从而减少开发时间和为不同平台构建多个应用程序所需的工作量。

但是,在构建将要投入生产的应用程序时,建议您使用现有框架。 除了在预定义的体系结构中构建您的应用程序之外,这还可能为您提供一组组件,这些组件将帮助您的应用程序更接近原生的外观和感觉。 一些值得注意的框架是 Ionic、Framework7、Weex、Ratchet、Kendo UI 和 Onsen UI。 祝你好运!

相关: Cordova 框架:Ionic 与 Framework7