随着智能手机和平板电脑的普及,越来越多的互联网 IT 企业把注意力集中到了移动平台上。目前市场上主流的移动平台有 Apple 的 iOS, Google 的 Android, 微软的 Windows Phone, BlackBerry 以及 Nokia 的 Symbian 等。这些移动平台的开发环境和编程语言都不尽相同。同时,一个平台又有多个版本,例如 Android2.3 和 Android3.0 分别支持智能手机和平板电脑。正是由于这些多样性,使得移动应用的开发存在成本高、周期长和维护困难等问题。
Worklight 是 IBM 收购的一套用于移动应用开发和基础平台整合的企业级解决方案。它支持多种移动平台的本地应用开发,同时也支持基于 HTML5 和 JavaScript 的跨平台应用。
本文主要介绍 Worklight 的 RuntimeSkin 特性以及如何使用该特性开发针对不同移动终端的跨平台应用。
开发环境安装与配置
Worklight 提供的是一整套移动应用的开发环境,涵盖了从开发到集成,到管理、部署、监控行等软件开发生命周期的各个方面。它主要由四个部分组成,Worklight Studio、 Worklight Server、Device Runtime 和 Worklight Console:
- Worklight Studio 是基于 Eclipse 的集成开发环境,用户可以很方便地创建、开发、部署和测试不同平台的本地应用或者混合型应用。
- Worklight Server 是一个基于 Tomcat 的服务器,用于部署开发好的移动应用程序。同时它还提供适配器 (Adapter) 组件来进行用户登录验证、后台数据交互、消息推送等企业级应用操作。
- Device Runtime 是 Worklight SDK 中包含一个组件,它主要提供了可以调用移动平台本地资源的多种接口,开发者可以使用 JavaScript API, 操作系统本地库和第三方库来调用这些接口,充分利用了本地应用的优点。
- Worklight Console 可以让用户通过浏览器来监控、管理当前部署在 Worklight Server 上的应用程序和适配器组件。Worklight Console 同时还负责消息推送管理以及报表分析。
Worklight 开发环境的下载与安装步骤可以从 developerWorks IBM Worklight 学习资源上获得。
什么是运行时皮肤(Runtime Skin)
运行时皮肤是指 Worklight 的应用程序可以为已经创建好的手机平台环境(Worklight Environment)添加多个皮肤,每一个皮肤是平台环境的一个子集,所有的皮肤作为应用程序的一部分打包在安装文件中。当应用程序运行时会根据具体 的移动设备动态地决定使用哪一个皮肤。运行时皮肤的应用场景有很多,比如不同的手机尺寸,不同的手机平台版本,是否支持 HTML5 等等。
下面我们以一个新闻浏览的应用程序为例,具体介绍如何应用 Worklight 的 Runtime Skin 特性。
创建 Worklight 工程和应用程序
- 我们创建一个 Worklight 工程。在 Eclipse 中选择 File->New->Worklight Project, 如图 1 所示。
图 1. 创建 Worklight 工程
- 输入工程名称 Mobile News。接着我们创建一个 Worklight 应用程序,选择 File->New->Worklight Application,如图 2 所示。
图 2. 创建 Worklight 应用程序
- 在弹出的窗口中选择***步新建的工程,然后输入应用程序的名称 NewsApp,如图 3 所示。
图 3. 在工程中创建应用程序
- 创建完工程和应用程序以后,Worklight 会自动生成如下的目录结构,如图 4 所示。
图 4. 应用程序目录结构
我们看到在 apps 目录下包含刚刚创建的应用程序 NewsApp,初始情况下每一个应用程序会有一个 common 的运行时环境,它会被不同手机平台环境(例如 iOS, Android, BlackBerry 等)所共用。在 common 文件夹下有三个文件夹 css, images 和 js,分别存放了程序相关的 css 文件,图片和 JavaScript 文件。NewsApp.html 是程序自动创建的主 html 文件。
在工程中引入 Dojo Mobile
在这个例子中,我们使用 Dojo Mobile 做为手机界面开发的 JavaScript 框架。Dojo Mobile 是 Dojo JavaScript 的一个 mobile 版本扩展,专门为手机移动开发提供很多丰富的控件和不同的 css 主题。
打开 NewsApp.html,在 head 中引用 dojo.js 文件,这里我们使用 CDN 的方式,如清单 1 所示。读者也可以从 dojo 的官方网站上下载 dojo toolkit 包,拷贝到工程里,然后在 html 文件中引用 dojo.js。
清单 1. 引用 dojo.js
- <script type="text/javascript"
- data-dojo-config="isDebug: false, async: true, parseOnLoad: true"
- src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js">
- </script>
- 在 js/NewsApp.js 的 wlCommonInit() 初始化函数中添加相应的 dojo mobile 模块,这里我们用到的是 AMD 方式,当 require 方法加载完所需的 dojo mobile 模块以后,会调用 init 这个初始化函数,函数具体的实现放在运行时皮肤。
清单 2. 用 AMD 方式加载 dojo mobile 模块
- require([
- "dojo",
- "dojox/mobile/parser",
- "dojox/mobile",
- "dojox/mobile/compat",
- ], function(dojo) {
- dojo.ready(function() {
- init();
- });
- });
定义视图
这个示例程序一共分为两个视图:***个视图是列表视图,展示多条新闻的标题。第二个视图是正文视图,显示新闻的正文。两个视图的交互方式分为两种, ***种方式是首页显示列表视图,当用户点击某一个新闻标题后,转到正文视图。点击正文视图左上角的返回按钮,返回到列表视图,如图 5 左侧所示。这种方式适合小屏幕的手机。
第二种方式是把列表视图和正文视图显示在同一个页面中,如图 5 右侧所示。页面左侧是新闻列表视图,页面右侧是正文视图。用户可以在列表视图中选择新闻标题,相应的新闻正文就会在右侧显示。这种方式适合在平板电脑这种屏幕较大的移动设备上。
图 5. 两种显示方式
在新建皮肤之前,我们需要把不同皮肤共用的代码放在 common 环境中。
- 首先在 common 环境下新建一个 data 文件夹来存放两个视图的模版,分别命名为 list.html 和 detail.html.
清单 3. 列表视图代码 - <h1 id="listHead" data-dojo-type="dojox.mobile.Heading" label="News"></h1>
- <ul id="newsList" data-dojo-type="dojox.mobile.EdgeToEdgeList">
- <li data-dojo-type="dojox.mobile.ListItem" moveTo="detailView"
- label="news 1 title"></li>
- <li data-dojo-type="dojox.mobile.ListItem" moveTo="detailView"
- label="news 2 title"></li>
- </ul>
清单 4. 正文视图代码- <h1 id="detailHead" data-dojo-type="dojox.mobile.Heading" label="News title"></h1>
- <div data-dojo-type="dojox.mobile.RoundRect" data-dojo-props='shadow:true'>
- <p>This is news body</p>
- </div>
- 在 common/js 中添加通用的 javscript 方法。
清单 5. loadView 方法- function loadView(id, url) {
- var view = new dojox.mobile.ScrollableView({
- id: id,
- selected: true
- });
- var contentPane = new dojox.mobile.ContentPane({
- href: url
- });
- view.addChild(contentPane);
- return view;
- }
loadView 方法主要工作是把列表视图(list view)和正文视图(detail view)分别加载到一个 ScrollableView 当中。接下来我们开始创建两个不同的皮肤以及皮肤相关的代码。
创建运行时皮肤
首先我们需要新建一个 Worklight 环境,右键 NewsApp 工程选择 New ->Worklight Environment, 如图 6 所示。
图 6. 创建 Worklight 环境
Worklight 提供了多种手机平台环境,包括:iPhone/iPad, Android, BlackBerry 和 Windows Phone 等。在这里我们选择 Android phones and tablets,如图 7 所示。
图 7. 添加 Android phone and tablet 环境
接下来我们创建两套运行时皮肤,一套针对 Android 手机,另外一套针对 Android 平板电脑。
右键 NewsApp 项目,选择 New -> Worklight Application Skin, 然后选择 Skin 对用的手机环境为之前创建的 Android phones and tablets, 输入 skin 的名字 android.phone, 如图 8 所示。
图 8. 添加 Android Phone 皮肤
同样地,我们创建另外一个皮肤,名称为 android.tablet. Worklight 会自动地将创建完的皮肤在 application-descriptor.xml 中注册,如清单 6 所示。这里需要注意一点,当我们删除某一个 skin 的时候,需要在 application descriptor 中手动删除该 skin 标签。
清单 6. application-descriptor.xml 中注册的 skin 信息
- <android version="1.0">
- <skins>
- <skin name="default">
- <folder name="common"/>
- <folder name="android"/>
- </skin>
- <skin name="android.phone">
- <folder name="common"/>
- <folder name="android"/>
- <folder name="android.phone"/>
- </skin>
- <skin name="android.tablet">
- <folder name="common"/>
- <folder name="android"/>
- <folder name="android.tablet"/>
- </skin>
- </skins>
- </android>
每一个皮肤包含了各自的 css 文件,image 图片和 javascript 方法。我们需要为两个皮肤创建不同的初始化函数,把列表视图和正文视图按照特定的方式加载到主 html 文件中。
- 在 android.phone 的 js 文件夹下新建一个与 common/js 下同名的 js 文件:NewsApp.js,在这个文件里添加初始化函数。
清单 7. phone 皮肤的初始化函数 - function init() {
- var listView = loadView("listView", "data/list.html");
- dojo.place(listView.domNode, dojo.body());
- var detailView = loadView("detailView", "data/detail.html");
- dojo.place(detailView.domNode, dojo.body());
- }
初始化函数把两个视图按顺序添加到主页面中,当程序启动时,显示***个页面,也就是列表视图。当用户点击列表视图中的某一项,就会转到正文视图。
- 同样地,我们在 android.tablet 的 js 文件夹下也新建一个 NewsApp.js,它的初始化函数如下:
清单 8. tablet 皮肤的初始化函数 - function init() {
- var fixedSplitter = new dojox.mobile.FixedSplitter({
- orientation: "H"
- }, dojo.create("div", null, dojo.body(), 'first'));
- fixedSplitter.startup();
- var listView = loadView("listView", "data/list.html");
- var leftPane = new dojox.mobile.ContentPane({
- id: "leftPane",
- content: listView.domNode
- });
- fixedSplitter.addChild(leftPane);
- var detailView = loadView("detailView", "data/detail.html");
- var rightPane = new dojox.mobile.ContentPane({
- id: "rightPane",
- content: detailView.domNode
- });
- fixedSplitter.addChild(rightPane);
- }
在这个初始化函数中,我们用到了 FixedSplitter 这个 dojo mobile 控件,它可以把 mobile 页面分为多个区域,每个区域可以加载不同的视图。这里我们把整个页面分成左右两块 leftPane 和 rightPane,分别加载列表视图和正文视图。
当我们完成不同皮肤的初始化函数之后,需要在 skinLoader.js 的 getSkinName 方法中添加根据移动设备屏幕大小动态选择皮肤的代码。如图 9 所示。
图 9. skinLoader.js
清单 9. getSkinName 方法
- function getSkinName() {
- var skinName = "android.phone";
- var screenHeight = screen.height;
- var screenWidth = screen.width;
- if (screenHeight >= 1000 || screenWidth >= 1000) {
- skinName = "android.tablet";
- }
- return skinName;
- }
这个方法根据屏幕的大小来选择应用哪一个皮肤。注意 skinName 的值要跟创建的皮肤名称保持一致。
皮肤应用效果
我们把 NewsApp 工程部署到 Worklight Server 上,然后分别在不同手机尺寸的模拟器上运行。图 10 所示的是运行在小屏幕手机上的效果。图 11 所示的是运行在大屏幕平板电脑上的效果。
图 10. 手机显示效果
图 11. 平板电脑显示效果
结束语
运行时皮肤是 Worklight 的一个重要特性,它可以方便地在同一个应用程序中添加多个皮肤外观,在程序运行时动态地选择适合移动终端设备的皮肤。本文从一个具体的实例出发,帮助读者了解运行时皮肤的具体使用方法。