【51CTO译文】你已完成了为应用程序构建前端的工作,它还有了移动支持功能。现在你想提供用户们可以从应用程序商店下载的原生客户端应用程序。读完该教程后,你会明白如何重复使用现有的HTML5代码,借助Apache Cordova,针对每个目标平台开发原生的移动客户端程序。
你将学会如何:
•对现有的Web应用程序进行改动,好让应用程序可以作为一个混合移动应用程序来部署。
•借助Apache Cordova,开发面向安卓和iOS的原生应用程序。
什么是混合移动应用程序?
混合移动应用程序是用HTML5开发的――不像原生应用程序编译成针对特定平台的二进制代码。客户端代码完全由HTML、CSS和JavaScript组成,包装起来后安装在客户端设备上,完全像任何原生应用程序那样,然后在周围的原生外壳生成的浏览器进程里面执行。
除了封装浏览器进程外,原生外壳还允许访问原生设备功能,比如方向感应器、GPS、联系人名单等,应用程序则可以通过JavaScript库来使用这些功能。
在该例子中,我们使用Apache Cordova部署混合应用程序,该应用程序使用了TicketMonster的现有HTML5移动前端,并与在JBoss A7或JBoss企业应用平台(EAP)上运行的TicketMonster部署环境的充分利用代表性状态传输协议(REST)的服务进行交互。
图1:混合TicketMonster的架构
改动应用程序以便远程访问
在我们让应用程序成为混合应用程序之前,需要对应用程序访问远程服务的方式做一些改变。请注意:这些变化已经实现在用户前端,我们在此为你显示了需要改动的代码。
在Web版本的应用程序中,客户端代码与服务器端代码一起部署,那样模型和集合(还有将执行REST服务调用的任何部分代码)可以使用相对应用程序根目录的URL:所有资源都由同一台服务器来提供,所以浏览器将进行正确的调用。这还尊重浏览器在默认情况下执行的同源策略,以防止跨站脚本攻击。
如果客户端代码与服务分开来部署,REST调用必须使用绝对URL(我们会在后面探讨给同源策略带来的影响)。此外,由于我们希望不必重新构建源代码,就能够将该应用程序部署到不同的主机上,所以它必须是可以配置的。
你已经在用户前端章节大体了解了这方面,我们在那个章节为移动版应用程序定义了configuration(配置)模块。
- src/main/webapp/resources/js/configurations/mobile.js
- ...
- define("configuration", function() {
- if (window.TicketMonster != undefined && TicketMonster.config != undefined) {
- return {
- baseUrl: TicketMonster.config.baseRESTUrl
- };
- } else {
- return {
- baseUrl: ""
- };
- }
- });
- ...
该模块有一个baseURL属性,既可以设置代表相对URL的空字符串,也可以设置成前缀,比如域名,这取决于名为TicketMonster的全局变量是否早已被定义,它拥有baseRESTUrl属性。
我们所有执行REST服务调用的代码都依赖该模块,因而基本REST URL可以在单单一个地方加以配置,并注入到整段代码中,正如下列代码实例所示:
- src/main/webapp/resources/js/app/models/event.js
- /**
- * 事件模型的模块
- */
- define([
- 'configuration',
- 'backbone'
- ], function (config) {
- /**
- * 事件模块类定义
- * 用于对单个事件执行CRUD(创建读取更新删除)操作
- */
- var Event = Backbone.Model.extend({
- urlRoot: config.baseUrl + 'rest/events' // the URL for performing CRUD operations
- });
- // 输出事件类
- return Event;
- });
执行REST服务调用的其他所有模块以相似的方式使用前缀。眼下你没必要做任何事情,因为我们在用户前端教程中编写的代码最初就是这样编写而成的。不过小心,如果你有一个移动Web应用程序使用任何相对URL,就需要对它们进行重构,以便加入某种URL配置。
#p#
安装混合移动工具和CordovaSim
混合移动工具(Hybrid Mobile Tools)和CordovaSim还没有作为JBoss Developer Studio的一部分而安装。它们可以从JBoss Central来安装,如下所示:
1. 想安装这些插件,只需把下面这个链接拖到JBoss Central: https://devstudio.jboss.com/central/install?connectors=org.jboss.tools.aerogear.hybrid。另外在JBoss Central中,选择Software/Update(软件/更新)选项卡。在Find(查找)栏,键入JBoss Hybrid Mobile Tools,或者滚动浏览列表,找到JBoss Hybrid Mobile Tools + CordovaSim。选择相应的复选框,并点击Install(安装)。
图2:通过链接,开始混合移动工具和CordovaSim的安装过程。
图3:在JBoss Central的软件/更新选项卡中找到混合移动工具和CordovaSim。
在安装向导中,确保已为你想要安装的软件选择了复选框,并点击Next(下一步)。建议你安装所有已选择的组件。
仔细查看列出来安装的项目的细节,并点击Next(下一步)。在阅读并同意许可证后,点击I accept the terms of the license agreement(s),即我接受许可证协议的条款,点击Finish(完成)。Installing Software(安装软件)窗口就会打开,报告安装进度。
在安装过程中,你可能会收到警告,提醒要安装未签名内容。如果真是这样,仔细阅读内容细节,如果对内容满意,就点击OK(确定),继续安装。
图4:提示安装的软件含有未签名内容的警告。
一旦安装完成,会提示你重启IDE。点击Yes(确定),即可立即重启;如果你需要保存对所打开项目改动的任何未保存内容,就点击No(不)。注意:IDE重启后,改动才生效。
一旦安装完毕,你必须将安卓SDK的位置告知混合移动工具,之后才能使用涉及安卓的混合移动工具动作。
想设定安卓SDK的位置,点击Window(窗口)→ Preferences(偏好设置),选择Hybrid Mobile(混合移动)。在Android SDK Directory(安卓SDK目录)栏,键入已安装SDK的路径,或者点击Browse(浏览),浏览到相应位置。点击Apply(应用),并点击OK(确定),即可关闭Preferences(偏好设置)窗口。
图5:偏好设置窗口的混合移动面板
#p#
开发混合移动项目
1. 想开发一个新的混合移动项目,点击File(文件)→ New(新建)→ Other(其他),选择“Hybrid Mobile (Cordova) Application Project”,即“混合移动(Cordova)应用程序项目”。
图6:开始开发一个新的混合移动应用程序项目
2. 输入项目信息:应用程序名称、项目名称和程序包。
项目名称
TicketMonster-Cordova
名称
TicketMonster-Cordova
ID
org.jboss.jdf.example.ticketmonster.cordova
图7:开发一个新的混合移动应用程序项目
点击Next(下一步),为该项目选择混合移动引擎。如果你之前在JBoss Developer Studio中从未安装过混合移动引擎,就会提示你下载或搜索可以使用的引擎。我们将点击Download(下载)按钮来执行前一项操作。
图8:头一次安装混合移动引擎
系统会提示一个对话框,你可以下载所有可用的混合移动引擎。
图9:选择要下载的混合移动引擎
我们将选择版本3.4.0的安卓和iOS变种。
图10:为3.4.0选择安卓和iOS
我们已经下载并安装了混合移动引擎,现在不妨将它用在我们的项目中。选择刚配置好的引擎,并点击Finish(完成)。
图11:开发一个新的混合移动应用程序项目
一旦你完成了开发项目的任务,浏览到www目录,该目录里面含有应用程序的HTML5代码。由于我们重复使用TicketMonster代码,你只要把www目录换成TicketMonster的webapp目录的符号链接;config.xml文件和rest目录需要拷贝过去,拷贝到TicketMonster的webapp目录。另外,你可以拷贝TicketMonster的代码,并在那里作所有必要的改动(不过在那种情况下,你在两个地方都需要维护应用程序的代码。)
- $ cp config.xml $TICKET_MONSTER_HOME/demo/src/main/webapp
- $ cp res $TICKET_MONSTER_HOME/demo/src/main/webapp
- $ cd ..
- $ rm -rf www
- $ ln -s $TICKET_MONSTER_HOME/demo/src/main/webapp www
图12:将www与webapp目录链接起来的结果
混合移动工具要求cordova.js文件装入到应用程序的起始页面。由于我们不想把该文件装入到现有的index.html文件中,就要创建一个只由Cordova应用程序才可以使用的新的起始页面。
- src/main/webapp/mobileapp.html
- <!DOCTYPE html>
- <html>
- <head>
- <title>Ticket Monster</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
- <script type="text/javascript" src="resources/js/libs/modernizr-2.6.2.min.js"></script>
- <script type="text/javascript" src="resources/js/libs/require.js"
- data-main="resources/js/configurations/loader"></script>
- </head>
- <body>
- </body>
- </html>
现在不妨修改混合移动项目的配置,使用该页面作为应用程序的起始页面。此外,我们将把我们的REST服务URL添加到config.xml文件中的域白名单(为了简单起见,你在开发过程中还可以使用“*”):
- src/main/webapp/config.xml
- <?xml version="1.0" encoding="utf-8"?>
- <widget xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0"
- id="org.jboss.jdf.example.ticketmonster.cordova" version="2.0.0">
- ...
- <!-- The application start page -->
- <content src="mobileapp.html" />
- <!--
- Add the TicketMonster cloud app to the domain whitelist.
- Domains are assumed blocked unless set otherwise.
- -->
- <access origin="http://ticketmonster-jdf.rhcloud.com"/>
- ...
- </widget>
下一步,我们需要将库装入到应用程序。我们还将构建一个单独的模块。除了装入面向安卓的Apache Cordova JavaScript库外,该模块还将装入移动应用程序的其余部分。我们还需要配置应用程序的基本URL。就这个例子而言,我们将使用部署在云端的TicketMonster的URL。
- src/main/webapp/resources/js/configurations/hybrid.js
- // 为充分利用REST的服务覆盖配置
- var TicketMonster = {
- config:{
- baseRESTUrl:"http://ticketmonster-jdf.rhcloud.com/"
- }
- };
- require(['../../../cordova'], function() {
- var bootstrap = {
- initialize: function() {
- document.addEventListener('deviceready', this.onDeviceReady, false);
- },
- onDeviceReady: function() {
- // 检查是不是iOS 7或更高版本,禁止覆盖状态栏
- if(window.device.platform.toLowerCase() == "ios" &&
- parseFloat(window.device.version) >= 7.0) {
- StatusBar.overlaysWebView(false);
- StatusBar.styleDefault();
- StatusBar.backgroundColorByHexString("#e9e9e9");
- }
- // 装入移动模块
- require (["mobile"]);
- }
- };
- bootstrap.initialize();
- });
注意:我们将使用OpenShift主机托管版的TicketMonster应用程序,因为它在所有环境下访问起来更容易――智能手机模拟器和仿真器也能访问它,基本上不需要什么配置。另一方面,访问本地运行的JBoss EAP实例可能需要一番复杂的网络配置;要是需要向互联网打开实例,以便可以从智能手机访问,更是错综复杂。
上述代码片段含有面向iOS 7的针对特定设备的检查机制。我们将使用Cordova状态栏插件,确保iOS 7上的状态栏并不重叠用户界面。Cordova设备插件将用来获得检测设备时所用的设备信息。我们还将使用Cordova通知插件,向使用原生移动用户界面的最终用户显示提醒和通知。
我们将继续把所需的Cordova插件添加到项目。
选择混合移动项目的plugins目录,通过右击鼠标打开上下文菜单。选择菜单中的Install Cordova Plug-in(安装Cordova插件)选项。这会打开一个对话框,你可以在上面搜索各个位置下的Cordova插件,包括Cordova注册中心、git软件库或你文件系统中的目录。
图13:启动Cordova插件发现向导
现在我们将搜索并添加所需的插件:
图14:添加Cordova设备插件
图15:添加Cordova通知插件
图16:添加Cordova状态栏插件
点击Next(下一步)按钮,核实所要安装的插件版本。点击Finish(完成)按钮,即可下载插件,并安装到项目。
图17:核实所要添加的插件
最后一步需要调整src/main/webapp/resources/js/configurations/loader.js,以便在安卓上运行时装入该模块,使用我们已经在项目中配置的查询字符串。我们还将调整src/main/webapp/resources/js/app/utilities.js,以便使用通知插件,在混合移动应用程序的上下文中显示提醒。
- src/main/webapp/resources/js/configurations/loader.js
- //检测要装入的合适模块
- define(function () {
- /*
- 针对客户端的简单检查。如果是触摸设备或低分辨率屏幕,
- 显示移动客户端。通过启用低分辨率屏幕上的移动客户端,
- 我们允许在移动设备外面进行测试(比如JBoss Tools和
- JBoss Developer Studio中的移动浏览器模拟器)。
- */
- var environment;
- if (document.URL.indexOf("mobileapp.html") > -1) {
- environment = "hybrid";
- }
- else if (Modernizr.touch || Modernizr.mq("only all and (max-width: 768px)")) {
- environment = "mobile";
- } else {
- environment = "desktop";
- }
- require([environment]);
- });
现在我们将仔细检查utilities对象中的displayAlert函数。它被设置成一旦有通知插件,就使用该插件:
- src/main/webapp/resources/js/app/utilities.js
- ...
- // 显示模板的utility函数
- var utilities = {
- ...
- applyTemplate:function (target, template, data) {
- return target.empty().append(this.renderTemplate(template, data));
- },
- displayAlert: function(msg) {
- if(navigator.notification) {
- navigator.notification.alert(msg);
- } else {
- alert(msg);
- }
- }
- };
- ...
由于这类环境中缺少navigator.notification对象,该函数自动适用于非移动环境。
#p#
运行混合移动应用程序
现在你可以准备运行应用程序了。混合移动应用程序可以在使用混合移动工具的设备和模拟器上运行。
在安卓设备或模拟器上运行
注意:
你需要为安卓做什么?
想在安卓设备或模拟器上运行,你就要安装安卓开发者工具,这需要Eclipse实例(可以使用JBoss Developer Studio),可以在Windows(XP、Vista和7)、Mac OS X(10.5.8或更新版本)、Linux(GNU C Library - glibc 2.7或更新版本,已安装运行32位应用程序所需库的64位发行版)上运行。
你必须在自己的系统上安装安卓API 17或更新版本,那样才能使用Run on Android Emulator(在安卓模拟器上运行)这个动作。
想在设备上运行该项目,在Project Explorer(项目资源管理器)视图中,鼠标右击项目名称,点击Run As(运行方式)→Run on Android Device(在安卓设备上运行)。这个选项调用外部安卓SDK来包装工作区项目,如果一个安卓设备已连接上,就在安卓设备上运行。要注意:必须安装安卓SDK,另外必须正确配置IDE以便使用安卓SDK,那样这个选项才会成功执行。
想在模拟器上运行项目,在Project Explorer(项目资源管理器)视图中,鼠标右击项目名称,点击Run As(运行方式)→Run on Android Emulator(在安卓模拟器上运行)。
图18:在安卓模拟器上运行应用程序
这要求你构建安卓AVD(安卓虚拟设备),以便在虚拟设备中运行应用程序。
一旦部署完毕,应用程序现在可以在模拟器中用来交互。
图19:在安卓AVD上运行的应用程序
在iOS模拟器上运行
注意:
你需要为iOS做什么?
使用OS X操作系统时,这个选项才会显示,OS X有iOS模拟器。你必须安装Xcode 4.5+,它包括iOS 6 SDK。你还要安装面向iOS 5.x或更高版本的模拟器,以便在模拟器上运行项目。你可能需要更高版本的模拟器才能运行应用程序,这取决于你可能使用的各种Cordova插件。
在Project Explorer(项目资源管理器)视图中,鼠标右击项目名称,点击Run As(运行方式)→Run on iOS Emulator(在iOS模拟器上运行)。
图20:在iOS模拟器上运行应用程序
该选项调用外部iOS SDK,将工作区项目包装成XCode项目,然后在iOS模拟器上运行。
图21:在iOS模拟器上运行的应用程序
在CordovaSim上运行
CordovaSim让你可以在本地工作区中运行混合移动应用程序。你可以开发应用程序,不需要部署到实际设备上,甚至不需要部署到仿真器和模拟器上,就能实现应用程序的行为。你在使用CordovaSim能实现什么功能方面有一些限制;比如说,有些Cordova插件可能与CordovaSim无法兼容。但总的来说,你得到的是更快的开发周期。
在Project Explorer(项目资源管理器)视图中,鼠标右击项目名称,点击Run As(运行方式)→Run with CordovaSim(与CordovaSim一起运行)。这会在CordovaSim中打开应用程序,它由BrowserSim模拟设备和设备输入面板组成。
图22:在CordovaSim上运行的应用程序
结束语
这篇教程介绍了借助Apache Cordova构建混合应用程序的全过程。你可能看到了我们如何将一个可正常运行的HTML5 Web应用程序改成可以直接在安卓和iOS上运行的应用程序。
英文原文:Creating hybrid mobile versions of the application with Apache Cordova
布加迪编译,转载请注明译者及译文原文出处。