在 Visual Studio 中使用 Apache Cordova 编写跨平台混合应用程序
深谙标准 HTML、CSS 和 JavaScript 的 Web 开发人员早已知晓 Web 应用程序通过单一的代码库就可满足各种设备和客户的需求。而响应式 Web 设计的引入还可让 Web 应用程序提供强大的移动体验。
然而,流行趋势似乎偏了方向:数据显示,移动客户在应用程序上花费的时间占到大约 80%,而在浏览器方面为 20%。简单地说,通过平台应用商店就可以了解到本机应用程序的知名度与使用情况,而即使是最好的移动 Web 解决方案也无法实现这点。此外,尽管 W3C 和浏览器供应商努力通过新的 HTML5 标准呈现本机平台功能,仍是前路漫漫。与本机应用程序和本机 API 相比,在提供新事物以取悦客户方面,移动 Web 和 HTML5 通常处于劣势。
难道您必须咬紧牙关编写本机应用程序?难道您必须要学习不同的语言和 UI 范例,为每个平台承担高昂的项目管理成本,随后错失潜在的市场机会?
根本不需要!Apache Software Foundation (ASF) 管理的开源框架 Apache Cordova (cordova.apache.org) 将为您翻开新的篇章。通过 Cordova,您可以利用 HTML、CSS 和 JavaScript 技能以及丰富的社区资源针对 Android、Amazon Fire、iOS、Mac OS X、Windows、Windows Phone、BlackBerry、Web 浏览器等创建应用程序。更妙的是,Web 应用程序受限于浏览器支持的功能,而 Cordova 插件模型则可充分调用本机平台 API。
因此,Cordova 可以在不牺牲功能的情况下为您提供 Web 的跨平台优势,为您进入移动应用程序市场开辟出一条充满吸引力的道路。我们将通过构建一个简单的自拍应用程序来演示其工作原理,如图 1 所示。
图 1 Here My Am!Android 设备上的应用程序
Visual Studio 中的 Cordova
Cordova 的使用通常是通过节点程序包管理器 (npm) 和 Cordova 命令行界面来进行。根据目标平台,还需要安装 Apache Cordova 文档 (bit.ly/1tJ19fq) 的“平台指南”部分中描述的诸如平台 SDK 之类的其他组件。对于许多希望面向 Android、iOS 和 Windows 开发的程序员而言,这会涉及到大量工作,可能需要花一些时间来学习各种错综复杂的工具。
为了简化工作,并将 Visual Studio 的强大功能与高效引入 Cordova,Microsoft 正在推出 Visual Studio Tools for Apache Cordova。该工具包目前为预览版,作为 Visual Studio 2013 Update 4 的扩展提供 (bit.ly/11m4vKH),并内置于 Visual Studio 2015 预览版中 (bit.ly/1u1dsSQ),其可为 Android 和 iOS 目标正确安装并配置每一个第三方依赖项(Windows 自动随附 Visual Studio)。然后,自动将 Cordova 进程加入到 Visual Studio IDE 中,诸如安装插件、运行生成以及部署到设备和仿真器。此外,其还可以提供您期望 Visual Studio 带来的所有便利,如 IntelliSense、集成调试、项目和配置管理,与 Visual Studio Online 集成,以及能够使用 TypeScript。
若要面向使用 Visual Studio 的 Android 和 Windows 进行开发,您只需要一台装有 Windows 8 或更高版本的计算机即可(您可以从 Windows 7 进行 Android 开发)。若要面向 iOS 开发,则需要一台装有 Xcode 5.1 或更高版本的 Mac,您可以在 Parallels 或 VMware Fusion 上的 Windows 中运行 Visual Studio。(请参阅“安装针对 iOS 执行生成的工具”MSDN 库页面 bit.ly/1GqnEuK 了解详细信息,包括有关远程生成代理 vs-mda-remote 的信息,该代理运行在 Mac 上,允许您通过本地网络或 VPN 连接从 Visual Studio 执行生成、运行和调试。)
Web 主机和响应式跨浏览器 CSS
我们将调用自拍应用程序“Here My Am!”(Kraig 的儿子在 3 岁时使用过这个短语),其 HTML5 标记非常简单,如图 2 所示。
图 2 “Here My Am!”的 HTML 标记应用程序
<body>
<div class="mainContainer">
<div class="title mainChild">
<h1 class="titlearea ">Here My Am!</h1>
</div>
<div id="locationSection" class="mainChild subsection">
<h2 class="section-title">Here:</h2>
<div id="locationControls">
<input id="txtLocation" type="text" placeholder="tap to edit" />
<button id="btnLocate" class="iconGlobe"></button>
</div>
</div>
<div id="photoSection" class="mainChild subsection">
<h2 id="photoHeading" class="section-title">My:</h2>
<div id="photo">
<img id="photoImg" src="#" draggable="false"
alt="Tap to capture image from camera" />
</div>
</div>
<div id="shareSection" class="mainChild">
<button id="btnShare" class="shareButton" disabled>Share</button>
</div>
</div>
</body>
接下来,我们需要可以匹配图 1 的相应样式,这为我们探索 Cordova 的核心本质提供了机会。
本机移动应用程序一般从编译的可执行文件运行:您使用 Objective-C、Swift、Java、C# 和 C++ 之类语言编写的代码被编译成移动操作系统可以理解的二进制格式。另一方面,必须将 HTML、CSS 和 JavaScript 提供给能够在运行时解析、呈现并执行该源代码的主机(如浏览器)。一些平台,如 Windows 8/8.1 和 Windows Phone 8.1,提供直接将 HTML、CSS 和 JavaScript 呈现为本机应用程序的系统级主机。若要详细了解有关这方面的信息,请参阅由 Kraig Brockschmidt 撰写的免费电子书籍《Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition》(Microsoft Press, 2014 年)bit.ly/1jyOYLC。如果可能,Cordova 就会使用此功能。此外,在 iOS 和 Android 上,目前其在本机应用程序包装器内采用了类似浏览器的 WebView 元素,如图 3 所示。无论哪种方式,您必须具有可在应用程序上下文中运行 Web 标准代码的环境。
图 3 Cordova 在本机应用程序环境中运行 HTML、CSS 和 JavaScript
问题是,这些主机环境各不相同。每一个都是操作系统中本机浏览器的变体,如图 4 所示。
图 4 主机环境基础
移动平台 | 主机基础 |
Windows 8/8.1、Windows Phone 8/8.1 | Internet Explorer 10/11 |
Android 4.x、5.0 | Android Browser 4.x、5.0(为了达到最佳实现,建议使用 4.4 或更高版本) |
iOS7、iOS8 | iOS Safari 7.1/8 或更高版本,取决于更新 |
因此,Cordova 应用程序的 CSS 必须工作在每个目标平台的 Web 主机中,就像 Web 应用程序必须使用各种有前缀和无前缀的样式工作在不同的浏览器中一样,您可以使用类似的方法。例如,将应用程序文件放在 Web 主机上,并在 Internet Explorer、Chrome 和 Safari(在 Mac 上)中将其打开,然后使用浏览器开发人员工具在不同的窗口大小中测试您的样式,上述做法会很有帮助。此外,在 caniuse.com 交叉引用您的样式,这可以确切标识出哪些浏览器和移动环境中支持 HTML5 和 CSS3 的哪些功能(特别要记住查看 Android Browser 和 iOS Safari)。当然,简单的布局更具适应性,您可以使用 CSS 框架,比如 jQuery Mobile、Ionic 和 Bootstrap。您还可以使用 CSS 预处理程序(如 LESS 或 SASS),从 Visual Studio 2013 Update 2 开始提供支持,但需要在 Cordova 生成之前运行。
类似地,移动应用程序也会遇到屏幕大小和方向的多种组合,如图 5 所述。
图 5 常见的屏幕大小组合
纵向宽度/横向高度 | 纵向高度/横向宽度 |
240(低端手机) | 320, 400, 480 |
320(中级手机) | 在 Windows 上,窄视图还有 462、480、470、568 以及更高的高度。 |
480(中级手机) | 在 Windows 上,纵向大于 500 像素的还有 640、800、854 以及其他高度。 |
720、768(平板电脑) | 960、1024 或更大。和 Windows 上的一些视图一样,iPad 是 1024×768。 |
大于 768 | iPad 2 和更高版本;大多数 Windows 便携式计算机和平板电脑以及许多 Android 平板电脑。 |
因此,响应式 Web 设计的所有原则(使用媒体查询来调整页边距、字体大小、布局、动画等)对于 Cordova 应用程序至关重要(为了简单起见,“Here My Am! ”应用程序仅支持纵向模式)。还要留意,设备的实际屏幕尺寸不一定就是报告给 CSS 呈现引擎的尺寸。高 DPI 显示器通常会应用一个比例因子,这意味着图 5 中的尺寸适用于 [min | max]-[width | height] 媒体查询,而不适用于 [min | max]-device-[width | height] 查询。在某些情况下,缩放不一定是精确的;在 iPad 上名义上为 768 像素尺寸在 CSS 中可能会显示为 767 像素。尽早并经常测试,以及再次考虑 CSS 框架或预处理工具。
Cordova 应用程序项目结构
在我们的标记和 CSS 形式规整后,我们可以将其引入 Cordova 应用程序。在 Visual Studio 中,使用“文件”|“新建”|“项目”并选择“JavaScript”|“Apache Cordova 应用程序”|“空白应用程序 (Apache Cordova)”创建一个 Cordova 应用程序,按图 6 所示设定项目结构(请注意,具体取决于 Tools for Cordova 方法 RTM)。
图 6 Visual Studio 中的项目结构
文件夹或文件 | 是否可以重命名? | 说明 |
css | 是的 | 样式表文件夹。CSS、图像和脚本文件夹都可以随意进行重命名,并从您的 HTML 文件进行引用。 |
图像 | 是的 | 与平台无关的图形的默认(空)文件夹。 |
合并 | 不能 | 特定于平台的 JavaScript 的文件夹。依赖于该文件夹名的生成工具(如“res”)。 |
res | 不能 | 特定于平台资源(如图标,闪屏和清单)的文件夹。 |
脚本 | 是的 | JavaScript 文件的默认文件夹。 |
config.xml | 不能 | 符合 W3C Packaged Web Apps(Widgets)规范的全局配置文件。它用作一个通用的清单,其设置转化为特定于平台的清单条目。Visual Studio 提供了一个 config.xml 设计器,您可以编辑原始 XML,因为有些设置并不显示在设计器中。 |
index.html | 是的 | 应用程序的默认起始页,在 config.xml 的“通用”|“起始页”字段中提及。如果对其重命名,需相应地更新 config.xml。 |
对于我们的应用程序,我们将标记放入 index.html,将样式放入 css/index.css。我们还为各种内容(已复制到 css/frameworks、css/fonts 和 scripts/frameworks 中以保持秩序井然)引入了跨平台 WinJS 3.0 库(当然,您可以使用任意数量的其他库,如 AngularJS 和 Bootstrap)。以下是 index.html 的 <head> 元素:
<!-- Recommended to prevent pinch zoom in webviews -->
<meta name="viewport" content="user-scalable=no" />
<link href="css/frameworks/ui-dark.css"
rel="stylesheet" /> <!-- WinJS -->
<link href="css/index.css" rel="stylesheet" /> <!-- App styles -->
<script src="cordova.js"></script> <!-- Cordova standard -->
<!-- WinJS -->
<script src="scripts/frameworks/base.js"></script>
<script src="scripts/frameworks/ui.js"></script>
<script src="scripts/frameworks/winjs.js"></script>
<!-- Project references -->
<script src="scripts/platformOverrides.js"></script>
<script src="scripts/index.js"></script>
请注意对 cordova.js 的引用,您无法在项目中找到它;系统会自动将其作为生成进程的一部分引入。
至于 platformOverrides.js,根脚本文件夹中此名称的文件是空的,但在 merges/windows/scripts 中的另一个文件夹将加载另一个名为 winstore-jscompat.js 的文件(以帮助满足第三方库的需求)。在生成时,merges/<platform> 下的所有文件和文件夹都将复制到最终文件夹结构,覆盖根项目中有着相同名称的所有文件。在 Windows 上,scripts/platformOverrides.js 由 merges/windows/scripts/platformoverrides.js 替换。这么做您就可以根据需要合并特定于平台的代码,相同文件级的合并也可用于 CSS、图像以及其他事项。请记住,这是一个文件级合并,而不是文件内容的合并!还要注意的是,合并文件夹可能遭弃用,以支持功能检测方法。
res 文件夹中的内容有类似之处,但行为更为多样化,因为这些资源是应用程序包所需,而非供运行在 WebView 或主机中的代码使用。请记住,必要时,Cordova 可在 WebView 周围生成一个本机应用程序包装器,也就是说,当目标平台需要时,它可为本机应用程序包创建一个文件夹结构。图 7 图示了 Visual Studio 项目的不同部分在生成过程中的终止位置。如果您生成一个项目,然后打开 bld/debug/platforms 文件夹,就可以看到结果。我们稍后会使用此行为自定义 Windows/Windows Phone 应用程序清单。
图 7 源项目的不同部分如何在特定于平台的生成文件夹中终止(可能已出现变化)
本机 API 和插件
我们现在准备将 JavaScript 中的行为添加到我们的应用程序。默认情况下,Visual Studio 中的 Cordova 应用程序模板提供如图 8 中所示的代码(大多数注释已忽略),其中 Cordova 的 deviceready、暂停和恢复事件抽象类似于各种平台上的应用程序生命周期事件(请参阅 Apache Cordova 文档 bit.ly/1u1hT1n 的“事件”部分,了解全部名册)。
图 8 Cordova 应用程序模板中的默认代码
(function () {
"use strict";
document.addEventListener('deviceready',
onDeviceReady.bind(this), false);
function onDeviceReady() {
document.addEventListener('pause', onPause.bind(this), false);
document.addEventListener('resume', onResume.bind(this), false);
// Perform other initialization here.
};
function onPause() {
};
function onResume() {
};
} )();
为简单起见,我们不会在“Here My Am!”中保留任何数据,所以我们已经移除了暂停和恢复处理程序。
需要注意的是,deviceready 通常在 DOMContentLoaded 之后触发,这样您就可以在您的 deviceready 处理程序中执行与 DOM 相关的初始化。但是,在某些调试方案中,比如通过无线网络使用 Visual Studio 远程调试,deviceready 有可能会在 DOMContentLoaded 之前触发,导致空对象异常。Here My Am! 使用一些标志来处理这种差异。
以下是我们现在需要在我们的应用程序中执行的操作:
- 使用用户的位置初始化“Here”字段并关联 locate 按钮。
- 使用默认消息初始化照片区域,并将其关联至相机捕捉。
- 启用共享位置和图像。
- 锁定显示方向为纵向。
虽然我们可以使用 HTML5 地理位置 API,并编写代码来分享到特定的社交网络,但我们会在相机捕捉方面遇到问题,因为两个主要的 WebView 限制会影响 Cordova 的开发(例如,在 iOS 和 Android 上):
- WebViews 会阻止 JavaScript 访问任何本机平台 API,因为从潜在的远程源加载的不受信任的 JavaScript 代码会构成安全威胁。(在 Windows 平台上,封装 JavaScript 是受信任的,并且可以调用本机 API,但远程加载的脚本则不可以。)
- WebViews 通常只支持 HTML5 API 的一个子集(各平台会有所差异,请查看 caniuse.com),许多本机功能还远远没有适合的 HTML5 标准。
幸运的是,其中所包含的本机应用程序和任何 WebView 都可通过由 OS 提供的特殊机制进行通信。Cordova 通过插件抽象这些机制,如图 9 所示。简单地说,插件中包含加载到 WebView 中的通用 JavaScript 接口,从而可以使用平台的信道与为平台编译的本机代码进行对话,并可以使用本机 API。此外,由于基础平台支持本机 JavaScript 应用程序,所以没有必要借助这样的桥梁,但插件仍用于抽象平台差异。
图 9 需要桥接时 Cordova 插件的结构,如在 iOS 和 Android 上
ASF 为常用本机 API 提供一套核心的 Cordova 插件,如存储、媒体、网络、地理位置、传感器、对话、媒体捕捉、通知、设备信息和全球化。当您在 Visual Studio config.xml 编辑器中选择这些插件时,系统会自动将相应的代码添加到您的生成中。
您还可以浏览 Cordova 插件注册表 (plugins.cordova.io) 和其他网站(如 plugreg.com)上第三方插件的健康体系。这些涵盖各种功能,包括广告、Microsoft Azure Mobile Services、蓝牙通信、社交分享等等。由于插件没有义务在一对一基础上简单呈现本机 API,所以插件开发人员经常通过生成更高级别的功能(如条形码扫描和与 Web 服务集成)来提升价值。一个很好的 Cortana 插件示例就是 Windows Phone 的声乐助手。此插件由专注于开源技术的 Microsoft 全资子公司 Microsoft Open Technologies Inc. 开发,在 2014 年 10 月的 PhoneGap Day 这一天受到开发人员的热烈追捧。但是要留意,插件间的平台支持差异甚广。例如,此 Cortana 插件只支持 Windows Phone 8.1。
无论是哪种情况,Visual Studio config.xml 编辑器可帮助您轻松地从源(比如 Cordova 注册表或 GitHub)将插件放到您的项目,此部分内容在 MSDN 库文章“通过 Visual Studio Tools for Apache Cordova 为应用程序生成管理插件”中有介绍(bit.ly/10ov6Fo)。稍后我们将向您演示示例。Visual Studio 可以自动抽取正确的文件,所以可以将适当的方法添加到全局命名空间,而无需显式引用插件的 JavaScript 文件。
总体而言,当考虑本机 API 时,Cordova 的惯例是先寻找一个合适的插件,而不是向您的应用程序添加特定于平台的代码。如果找到了一个接近所需的插件,就可以考虑对其进行扩展,毕竟很多都是要开发人员(比如您)来编写的,欢迎向 GitHub 投稿。另外,也可参阅 Apache Cordova 文档的“插件开发指南”部分,创建一个您自己的插件,然后在 Cordova 社区分享。
完善应用程序
了解我们如何通过插件访问本机 API,如何完善应用程序的功能。对于地理位置,我们抽取 Cordova Geolocation 插件并将此代码添加到我们的 deviceready 处理程序,以初始化位置字段并关联 locate 按钮:
locate();
document.getElementById("btnLocate").addEventListener("click", locate);
然后,我们实现 locate 方法,如图 10 所示。
图 10 实现 Geolocation
function locate() {
navigator.geolocation.getCurrentPosition(function (position) {
App.lastPosition = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
address: "(" + position.coords.latitude + ",
" + position.coords.longitude + ")"
};
// Go translate the coordinates into an address using the Bing Map Web API.
updatePosition();
}, function (error) {
WinJS.log && WinJS.log("Unable to get location: "
+ error.message, "app");
}, {
maximumAge: 3000, timeout: 10000, enableHighAccuracy: true
});
}
等一下,navigator.geolocation 不只是 HTML5 API?嗯,有可能:该插件智能地使用 HTML5 实现(如果其可用),否则其会将相同的函数添加到使用本机 API 实现的全局命名空间(如果没有平台支持则会失败)。以此方式,迁移自网站的代码不会受到重写。
获得了位置之后,我们将坐标存储在 App.lastPosition 中,并创建用于 txtLocation UI 元素和共享的默认 App.address 字符串。然后,我们的 updatePosition 函数(未显示)会在设置 txtLocation 值之前尝试使用 Bing Maps Web API 将这些坐标转换为有意义的地址。请参阅随附的代码下载,以了解详细信息。
对于相机捕捉,我们首先创建一个默认的图像并关联照片区域来进行捕捉:
setPlaceholderImage();
document.getElementById("photo").addEventListener("click",
capturePhoto.bind(photo));
添加 Cordova Camera 插件会将方法 navigator.camera.getPicture 添加到全局命名空间。如果成功,此调用将提供一个到设备本地文件系统中图像的 URI,我们可以将其分配给 img.src 属性。在图 11 中的代码中,分配发生在我们的 scaleImageToFit 函数中,该函数可以进行屏幕宽高比设置来保持图像的纵横比。
图 11 使用 Cordova Camera 插件
function capturePhoto() {
var photoDiv = this;
// Capture camera image into a file.
navigator.camera.getPicture(cameraSuccess, cameraError, {
quality: 50,
destinationType: Camera.DestinationType.FILE_URL,
encodingType: Camera.EncodingType.JPEG,
mediaType: Camera.MediaType.PICTURE,
allotEdits: true
correctOrientation: true // Corrects Android orientation quirks.
});
function cameraSuccess(imageFile) {
// Save for share and enable Share button.
App.lastCapture = imageFile;
document.getElementById("btnShare").disabled = false;
// Do letterboxing and assign to img.src.
scaleImageToFit(photoDiv.querySelector("img"),
photoDiv, App.lastCapture);
};
function cameraError(error) {
WinJS.log && WinJS.log("Unable to obtain picture: " + error, "app");
};
}
若要实现在有图像时可以启用的共享,我们在 plugreg.com 上找到了 Eddy Verbruggen 的 SocialSharing 插件,其适用于文本和图像。在将它作为自定义插件直接从 GitHub 进行添加的时候(如图 12 所示),Visual Studio 会自动下载我们所需的一切。(此进程会从存储库下载所有内容,但唯一重要的部分是插件的 plugin.xml 文件以及 src 和 www 文件夹;其他的一切都可以删除掉。)
图 12 从 GitHub 中添加自定义插件
现在,我们可以关联 Share 按钮,并调用插件的 socialsharing.share API(在 window.plugin 命名空间中),以获得图 13 中所示的可爱 UI,它提供了多种共享选择,类似 Windows 8/8.1 中提供的“共享”超级按钮:
document.getElementById("btnShare").addEventListener("click", App.share);
function share() {
var txtLocation = document.getElementById("txtLocation").value;
plugins.socialsharing.share("At " + txtLocation, "Here My Am!",
App.lastCapture);
}
图 13 在 Android、iOS 和 Windows Phone 8 上进行共享(图像由 SocialSharing 插件提供)
但这有一个问题:SocialSharing 支持 Android、iOS 和 Windows Phone 8,但不支持 Windows8/8.1 和 Windows Phone 8.1。实际上,不少第三方插件的平台支持有限,这就为帮助改进该插件以方便社区使用提供了明确的机会。但是,这篇文章为我们提供了演示使用合并文件夹的机会,Windows 上的 Cordova 应用程序运行在系统主机内,其中我们可以直接从 JavaScript 调用本机 API 并绕过插件。
首先,我们将上述共享函数移至 share.js 文件中,并将其公开为 App.share:
WinJS.Namespace.define("App", {
configurePlatformSharing: function () { },
share: share
});
function share() {
var txtLocation = document.getElementById("txtLocation").value;
plugins.socialsharing.share("At " + txtLocation, "Here My Am!",
App.lastCapture);
}
接下来,在将要替换与平台无关的 share.js 的 merges/windows/share.js 中,我们提供另一个能够调用“共享”超级按钮的 App.share 函数:
function share() {
Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();
}
但是,为了使其工作,我们必须在初始化期间为 DataTransferManager.ondatarequested 事件关联一个处理程序。这是存根方法 configurePlatformSharing 的用途所在,即当我们在 deviceready 处理程序中调用它时,不会在非 Windows 平台上执行任何操作:
App.configurePlatformSharing();
In the Windows-specific share.js, however, we do more:
WinJS.Namespace.define("App", {
configurePlatformSharing: configurePlatformSharing,
share: share
});
function configurePlatformSharing() {
var dataTransferManager =
Windows.ApplicationModel.DataTransfer.
DataTransferManager.getForCurrentView();
dataTransferManager.addEventListener("datarequested", provideData);
}
在上面的代码中,provideData 创建相应的数据包,其结果是在 Windows 8.1 和 Windows Phone 8.1 上提供本机“共享”超级按钮体验,如图 14 所示。
图 14 在 Windows 8.1 和 Windows Phone 8.1 上进行共享
应用程序的最后一部分内容是强制执行仅纵向视图,这为我们提供了一个机会,通过 res/native 文件夹(如必要)查看我们是如何完全控制特定于平台的清单的。在这种情况下,在 config.xml 编辑器中设置“公共”|“纵向”对 Android 来说足矣,但截至本文撰写之日,Windows 和 Windows Phone 并不会受到影响。没问题,我们只是在应用程序清单中做一些自定义项。
为此,运行生成并转到 bld/platforms/windows,您会在其中找到生成的清单,其名为 package.windows.appxmanifest (Windows 8.1)、package.phone.appxmanifest (Windows Phone 8.1) 和 package.windows80.appxmanifest (Windows 8)。将您需要的清单复制到 res/native/windows,然后进行更改。若要强制执行纵向,这就是我们需要在“应用程序”|“应用程序”|“VisualElements 节点”中执行的全部操作(针对 Windows 8.1 显示;使用命名空间前缀 m3:用于 Windows Phone 8.1,在 Windows 8 中没有前缀):
<m2:InitialRotationPreference>
<m2:Rotation Preference="portrait" />
<m2:Rotation Preference="portraitFlipped" />
</m2:InitialRotationPreference>
在生成时,Cordova 将 config.xml 中的起始页设置和个人首选项转换至特定于平台的清单,包括来自插件的特定于平台的详细信息。具体来说,如果查看任何插件文件夹中的 plugin.xml 文件,您会看到类似如下所示的条目:
<platform name="windows">
<config-file target="package.windows.appxmanifest"
parent="/Package/Capabilities">
<Capability Name="picturesLibrary" />
<DeviceCapability Name="webcam" />
</config-file> <!-- ... -->
</platform>
上面代码的含义:对于 Windows 目标,在 package.windows.appxmanifest 文件中,在“程序包”|“功能”节点下添加这些 Capability 元素和 DeviceCapability 元素。所以,很明显,方向插件可以执行我们通过手动完成的相同工作。由此,我们获得了一个功能型应用程序!
调试、部署以及其他的应用程序生命周期问题
作为开发人员,您清楚地知道,编写代码只是生产市场就绪软件整个过程中的一部分,Visual Studio 在此可以充分发挥其作用,如图 15 所示。
图 15 其他适用于 Cordova 应用程序的 Visual Studio 功能
功能 | 说明/注释 |
调试 | 在编写时,以下设备和仿真器支持在 Visual Studio 中使用 JavaScript 控制台和 DOM 资源管理器进行调试:
现在尚不支持在 Windows Phone 8 和 8.1 上进行调试,但您可以使用在 Microsoft Open Technologies 博客 (bit.ly/1y9k0zr) 中介绍的 Web Inspector Remote (weinre)。 当在 Ripple 中运行时,您可能会遇到这个糟糕的消息“I Haz Cheeseburger?!?!”有关信息,请参阅 Visual Studio Tools 常见问题 bit.ly/1x71P0q,有疑问时,只需点击“成功”按钮。默认 index.js 文件中还有一个注释,其中写到在 JavaScript 控制台中运行 window.location.reload 函数调试初始化代码;要记住这会重新加载最新的生成,且不会重新生成该应用程序或向源文件应用任何更改。 |
IntelliSense | Visual Studio 为您提供了用于 HTML、CSS 和 JavaScript 代码的 IntelliSense,包括越来越多的第三方库,如 JQuery、Backbone.js 和 Require.js。 |
测试 | Appium 和 Chutzpah 是流行的开源自动化工具。VChutzpah Test Runner for Visual Studio 可与 Visual Studio Test Explorer 和 Visual Studio Team Foundation Build 进行集成。对于广泛的设备测试,您可以使用服务,如 Perfecto Mobile。 |
应用程序生命周期管理 | Visual Studio ALM 功能为使用其他 IDE 的跨平台项目和团队成员提供了灵活的规划、源控件(托管在 Team Foundation Server 或 GitHub 上)、团队协作和发布管理。 |
在开始生成 Cordova 应用程序时,您在每个平台上都会发现一些古怪行为,了解这一点很有用。 这是目前跨平台开发的自然现象,这意味着您要切实地预料到像为每个目标编写本机应用程序那样对每个平台做出同样多的调试。同样,每个应用商店的部署也是独立进行,使用的是特定于这些平台的工具。Cordova 并不会为这些过程提供捷径。
特定于平台的生成将抽取项目 res 文件夹中的相应资源:请务必阅读这些内容并确认您拥有适用于各个平台的所有正确图形和其他文件。如果要一起获取最终的程序包,还要再次检查清单,以确保您的应用程序和您的公司已获得正确识别并且您没有携带来自默认项目模板的数据。
当应用程序可以交付给真正的客户时,您应该通过及时更新应用程序来应对各种问题。即使在客户可以高效为您提供测试结果的单一平台中,仍存在多种设备种类,因此,请及时更新以对客户表示尊重。
对于即将发布的 Visual Studio 的期待
最后,我们已经看到 Visual Studio Tools for Apache Cordova 对于简化跨平台 Cordova 开发大有帮助。Microsoft Open Technologies 为 Cordova 项目本身做出了重大贡献,Visual Studio Tools 团队致力于使体验更加出色,我们在本文中讨论的内容仅仅只是窥豹一斑!展望未来,团队正在关注研究一些应用程序功能,如推送通知、更强大的 IntelliSense、在更多平台上更好地进行调试、HTML/CSS 设计器、单元测试的改进支持、Team Build 的支持、加快和支持标准 Web 开发人员的工作流程。您还想了解其他哪些功能?请通过 Microsoft UserVoice 网站 (visualstudio.uservoice.com) 或 Twitter 的 @VSCordovaTools 向我们提供您的反馈意见,并加入 StackOverflow (bit.ly/1yCReYa) 上关于工具包的讨论。
提示、窍门和注意事项
移动目标:若要轻松地在目标平台之间进行切换,请按 MSDN 库文章“创建您的第一个 Hello World 应用程序”(bit.ly/1th836k) 中所述将“解决方案平台”控件添加到您的工具栏。
PhoneGap 和 Cordova:Cordova 开始是作为由 Nitobi Software Ltd. 开发的名为 PhoneGap 的移动框架和生成系统,旨在通过抽象化框架背后的差异以在不同移动电话平台之间搭建起一座桥梁。2011 年,Adobe Systems Inc. 收购了 Nitobi,随后将此框架作为开源框架 Apache Cordova 公开至 Apache Software Foundation,Microsoft Open Technologies Inc. 对此做出了重大贡献。Adobe 运行基于云的 PhoneGap Build 系统,该系统从 Web 代码创建本机应用程序包,这样您在自己的计算机上无需本机 SDK。
Android 仿真器:开发人员社区中一个几乎受到普遍认可的观点是,原始的 Android SDK 仿真器需要避免像拨号 Internet 那样,除非您配置了虚拟机 (VM) 加速。Visual Studio 2015 预览版包括基于快速 Hyper-V/x86 的 Visual Studio Emulator for Android (bit.ly/1xlRwFT),该仿真器与 Windows Phone 仿真器兼容(一旦安装,可与 Visual Studio 2013 Update 4 结合使用)。如果您不想安装 Visual Studio 2015 预览版,也可以使用 GenyMotion Emulator for Android。
Cordova 的最大优势:开发人员普遍认识到,在 Cordova 应用程序中运行 HTML、CSS 和 JavaScript 并不会在所有平台上都能带来真实的本机体验。Cordova 应用程序是不需要遵循本机 UI 模式的高品质体验的理想之选,也是不希望有跨平台差异的企业应用程序的理想之选。Cordova 也是一种迅速生成生产应用程序以测试市场中各种想法的高效方法,帮助您了解需要在哪些地方进行更深层次的商业投资。
引用远程脚本:Web 应用程序通常加载来自远程源的 JavaScript 库,这是有道理的,因为用户必须在线才能看到该网站。但是,移动应用程序应提供无需连接的良好体验,所以最好的做法是下载远程脚本并将其直接包含在您的项目中。这对于系统主机不允许执行远程脚本的 Windows 8/8.1 和 Windows Phone 8.1 来说是必要的;加载试图加载其他远程脚本的库在这里是有问题的,您可能需要执行一些手动修补才能使其正常工作。
一次一个平台:使用 Cordova 这样的跨平台工具并不意味着您必须同时将一个应用程序送往多个平台。您可能最初只针对单个平台,后来才知道您的投资也适用于其他平台。这样,您可以一次只针对一个平台优化您的 UI 和 CSS。
Kraig Brockschmidt 是 Microsoft 开发事业部的资深内容开发人员,专注于为开发人员提供 Windows、iOS 和 Android 上的移动云连接应用程序指导。他是 Microsoft Press 出版的《Programming Windows Store Apps with HTML, CSS and JavaScript》(两个版本)的作者,并在 kraigbrockschmidt.com/blog 上分享他的其他见解。
Mike Jones 是一位程序员,10 年来在 Microsoft 一直专注于移动领域,从 Compact Framework、Silverlight for Windows Phone 到 Visual Studio Tools for Apache Cordova 均有涉猎。他曾长期沉浸在 C# 之类的开发工作中,而在过去的几年里,他一直潜心研究 JavaScript 并乐此不疲。
衷心感谢以下 Microsoft 技术专家对本文的审阅:Chuck Lantz、Eric Mittelette、Parashuram Narasimhan、Ryan Salva、Amanda Silver、Cheryl Simmons 和 Priyank Singhal