使用 Dojo Mobile 和 PhoneGap 构建移动应用程序

IBMdW 发布于 2012/05/07 13:24
阅读 2K+
收藏 15

简介: 随着移动设备计算能力的日益增强以及无线网络的普及,人们对于移动应用的需求越来越大。由于主流平台的差异, 如 iOS 和 Android,应用程序需要针对不同的平台进行重复开发。为解决这个问题,PhoneGap 提供了基于 Web 的统一编程方式,使得同一程序能够在不同的平台上运行。然而,PhoneGap 并未提供兼容不同平台的统一界面风格。Dojo Mobile 正好弥补这一缺失,将同一程序在不同平台下展现为与平台一致的界面风格。另外,Dojo Mobile 还提供了模块化的组件 Widget,简单有效的数据接口,大大提高了开发的效率。

本文将详细讲述 Dojo Mobile 在 PhoneGap 上的开发过程,并通过一个实例程序进行讲解,能够让读者快速掌握利用 Dojo Mobile 在 PhoneGap 上的开发技术。

背景介绍

PhoneGap 是一款开源且跨平台的移动应用开发框架。它对各个移动平台的本身 API 进行了简化和抽象。开发者仅需要掌握 Web 开发的基本技术,就可以使用 HTML 和 JavaScript 在其上进行开发。所开发的 JavaScript + HTML 代码,经过 PhoneGap 平台的封装,可以导出为 iOS 和 Android 程序。基于 PhoneGap 开发的应用程序兼容性好,可以做到“Write once, run everywhere”而兼容性越强,所需的开发成本越低。目前 PhoneGap 对不同平台提供的功能特性有一定的差别,如图 1 所示。其对于主流平台 Windows Phone 7、Android 及 iOS 4 也能够非常好地支持。


图 1.PhoneGap 在不同平台下的特性
图 1.PhoneGap 在不同平台下的特性

PhoneGap 对于标准化有着非常好的支持,它基于 W3C 标准,现有的 Web 程序甚至无需修改就可以在 PhoneGap 上运行。当与功能强大的 Mobile 框架结合时,能够极大地降低开发成本。

Dojo Mobile 框架是一个移动终端的 Web 应用开发框架,是 Dojo 的一个子项目。它主要面向手持设备上的 Web 富客户端应用开发,提供了 iOS 和 Android 两套主题, 使得基于 Dojo Mobile 的应用具有手机本地应用的外观和效果。Dojo Mobile 具有轻量级、模块化、速度快及封装性好的特点。

Dojo Mobile 经过压缩之后体积只有几百 K,对于移动设备非常适合。

Dojo Mobile 基于 HTML5 和 CSS3 来实现一些特效,比较流畅,响应速度快。

Dojo Mobile 对于 iOS 和 Android 主题封装性好,开发者只需使用统一的布局和 CSS 即可实现不同平台的本地效果。

除此之外,Dojo Mobile 与 PhoneGap 的结合也非常好,基于 Dojo Mobile 的程序可以很简单的被 PhoneGap 转换成本地应用程序。

开发环境搭建

搭建开发环境分为三个步骤:第一步,搭建 Android 开发环境。第二步,配置 PhoneGap,将其集成到 Android 项目中。第三步,在配置好的 Android 项目中加入 Dojo Mobile。

Android 开发环境

Android 开发环境可以配置在 Windows,、Mac OS,、Linux 等操作系统上。本文的示例是在 Windows XP 平台上开发,以下就以 Windows XP 为例进行介绍。Android 开发环境的搭建需要若干软件,详细如下:JDK,、Eclipse、Android SDK, ADT(Eclipse 插件 )。

JDK 的安装配置与 Eclipse 的配置,对于任何 Java 开发者或者用 Eclipse 作为开发平台的开发者来说都是非常熟悉的,在这里就不赘述了。

安装配置好 JDK 与 Eclipse 之后,接下来需要安装 Android SDK 和 ADT。

Android SDK 可以在 http://developer.android.com/sdk/index.html 下载获得压缩包 android-sdk-windows.zip。详细过程如下:

I. 将此压缩包解压到 C:\android( 目录可以修改 ),运行目录下的 Setup.exe 将会弹出窗口如图 2。若出现"Fail to fetch URL..."类似的错误提示,请点选 Settings panel 中的 check box(红色框标记处)。


图 2. HTTP 请求方式设置
图 2. HTTP 请求方式设置

II. 在上面的窗口中选择 Available packages,出现图 3 所示的窗口。请选择开发需要的 API 版本并点击窗口右下方的"Install Selected"按钮。在接下来出现的页面中,请仔细阅读相关的 license,然后选择"Accepted All"和"Install Selected",系统将完成 API 版本的安装。


图 3.安装不同版本的 API
图 3 安装不同版本的 API

III. 安装结束之后,可以在"Installed packages"中看到所有安装成功的 API 版本,如图 4。


图 4. 安装成功的 API 版本
图 4. 安装成功的 API 版本

IV. Android SDK 的配置。类似于 JDK 安装完成后的配置,Android SDK 安装完成之后也需要在系统的环境变量中配置。具体的做法是将 SDK 目录下 tools 文件夹的路径添加到 Path 中。

到此,Android SDK 的安装与配置就完成了。接下来将要进行的是 Android 插件 ADT 在 Eclipse 上的安装与配置。详细过程如下:

I. Eclipse 启动后,选择 Help 菜单中的"Software Updates...",出现如图 5 所示的窗口。点击右边"Add Site..."按钮,出现了图 6 的窗口,将插件 ADT 的安装地址 https://dl-ssl.google.com/android/eclipse 添加至输入框中并点击 OK 按钮。若出现"No repository Found..."的错误提示,请尝试将 https 修改为 http 重新尝试。


图 5. 插件更新窗口
图 5. 插件更新窗口

图 6. 添加站点
图 6. 添加站点

II. 正确选择站点后,窗口中会列出可以安装的插件列表,选择最新的版本并按照提示安装即可。

III. 安装完成后重启 Eclipse。选择 window 菜单项 Preference 窗口,如图 7 所示。选择左边下列表中的 Android 选项,在右边出现的 SDK Location 输入框中配置 SDK 的安装目录并点击"OK"按钮。


图 7.Preference 窗口
图 7.Preference 窗口

IV. 到此 ADT 的安装与配置完成。安装配置成功后,便可以在 Eclipse 工具栏看到象征 Android 的机器人图标及 Window 菜单栏中 ADT 的选项,见图 8。


图 8.ADT 插件选项
图 8.ADT 插件选项

V. Android 的运行创建特定版本的 AVD(android Virtual Device)。在 Android SDK and AVD Manager 窗口左侧选择 Virtual devices,在右边出现的 panel 中点击"New"按钮。


图 9. 创建 AVD
图 9. 创建 AVD

配置 PhoneGap

PhoneGap 是一个使 Web 开发者能够快速开发跨移动平台应用程序的工具。只需要 Web 开发者具备良好的 HTML, JavaScript, CSS 技术就可以通过 PhoneGap 将其封装成适应 iOS、Android、BlackBerry、 Web OS、Symbian 等 5 大平台的应用。配置过程如下:

I. 从 http://phonegap.com 下载 PhoneGap 压缩包,并解压。

II. 在 Android 工程根目录下新建两个文件夹:/libs, /assets/www. 将 PhoneGap 压缩包解压放在目录 D:\PhoneGap 下。将 D:\PhoneGap\android\phonegap.jar 复制到 Android 工程的 libs 目录并添加到工程的 classpath 中。将 D:\PhoneGap\android\phonegap.js 复制到 Android 工程的 www 目录下并将 D:\PhoneGap\android\xml 文件夹复制到 Android 工程的 res 目录下。

III. 调整 Android 工程的配置文件 AndroidManifest.xml。将清单 1 中的内容复制到 <manifest> 的第一个子元素的位置。其中 <uses-permission> 作用是赋予应用程序访问特定设备的权限,如照相机、文件等。若应用程序不需要访问这些设备,可将其对应的访问权限去掉。另外,将属性 android:configChanges="orientation|keyboardHidden" 添加到第一个 <activity> 中,并将清单 2 中的内容添加到第一个 <activity> 之后。


清单 1.添加内容到 androidManifest.xml
				 
 <supports-screens 
 android:largeScreens="true"
 android:normalScreens="true"
 android:smallScreens="true"
 android:resizeable="true"
 android:anyDensity="true" /> 
 <uses-permission android:name="android.permission.CAMERA" /> 
 <uses-permission android:name="android.permission.VIBRATE" /> 
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
 <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> 
 <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
 <uses-permission android:name="android.permission.INTERNET" /> 
 <uses-permission android:name="android.permission.RECEIVE_SMS" /> 
 <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 
 <uses-permission android:name="android.permission.READ_CONTACTS" /> 
 <uses-permission android:name="android.permission.WRITE_CONTACTS" /> 
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
  <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 


清单 2 添加内容到 androidManifest.xml
				 
 <activity android:name="com.phonegap.DroidGap" 
    android:label="@string/app_name"       
    android:configChanges="orientation|keyboardHidden"> 
 <intent-filter> </intent-filter> 
 </activity> 

VI. 在 www 文件夹下创建 index.html 作为显示页面。将继承自 Activity 的类修改为继承于 DroidGap,并将此类的 onCreate 方法中的 setContentView(R.layout.main) 一行修改为 super.loadUrl("file:///android_asset/www/index.html")。最后,将 JS 脚本文件 phonegap.js 导入到 index.html 中,见清单 3。

V. 将清单 3 中的内容复制到 index.html 中,运行 Android 应用程序。若能在 Android 模拟器中出现新页面并显示"Hello, this is my first PhoneGap application."说明 PhoneGap 配置成功,见图 10。


图 10. PhoneGap 配置测试截图
图 10. PhoneGap 配置测试截图

清单 3 PhoneGap 配置测试
				 
 <!DOCTYPE HTML> 
 <html> 
 <head> 
 <title>PhoneGap Test</title> 
 <script type="text/javascript" charset="utf-8" src="phonegap.js"></script> 
 </head> 
 <body> 
 <h1>Hello, this is my first PhoneGap application.</h1> 
 </body> 
 </html> 

加入 Dojo Mobile

Dojo 是一个强大的、跨平台且开源的 JavaScript 框架,提供了丰富的控件方便 Web 开发者使用。Dojo Mobile 是 Dojo 的一部分,为 Mobile 领域提供了一套前台页面技术解决方案。

Dojo 目前官方发布最新版为 1.7 版,可以在 http://dojotoolkit.org/download/ 下载得到。本示例是在 Dojo 1.6 版本测试通过,1.7 版本的配置方法与之类似。将下载得到的 zip 压缩包解压。

在 www 文件夹下创建 libs 文件夹,并在 libs 下创建 Dojo 主目录。在 Dojo 主目录下创建 Dojo 和 Dojox 两个分目录。

  1. 将 Dojo zip 解压包中文件 Dojox/Mobile.js 复制到工程 Dojox 分目录中。
  2. 将 Dojo zip 解压包中 Dojox/Mobile 文件夹及其所有内容复制到工程 Dojox 分目录中。
  3. 将 Dojo zip 解压包中文件 Dojo/Dojo.js 复制到工程 Dojo 分目录中。

清单 4 将 Dojo 引用添加到 index.html 中
				 
 <meta name="viewport" content="width=device-width,initial-scale=1, 
    maximum-scale=1,minimum-scale=1, user-scalable=no"> 
 <meta name="apple-mobie-web-app-capable" content="yes"> 
 <link rel="stylesheet" href="libs/dojo/dojox/Mobile/themes/android/ 
   android.css" type="text/css">        
 <script src="libs/dojo/1.6/dojo/dojo.xd.js" 
    djConfig="parseOnLoad: true"></script> 
 <script> 
    dojo.require("dojox.Mobile.parser"); 
    dojo.require("dojox.Mobile"); 
    dojo.requireIf(!dojo.isWebKit, "dojox.Mobile.compat"); 
 </script> 

至此,开发环境搭建与配置就完成了。

Hello World !

此节是作为整个开发环境搭建是否成功的一个验证。


清单 5 验证环境搭建的 HTML 源码
				 
 <div dojoType="dojox.Mobile.View" selected="true"> 
    <h2 dojoType="dojox.Mobile.Heading" fixed="top">Hello, World!</h2> 
    <h2 dojoType="dojox.Mobile.RoundRectCategory">First Section</h2> 
    <div dojoType="dojox.Mobile.RoundRect"> 
        This is my first dojo Mobile application on android platform. 
    </div> 
    <h2 dojoType="dojox.Mobile.RoundRectCategory">Second Section</h2> 
    <ul dojoType="dojox.Mobile.RoundRectList"> 
        <li dojoType="dojox.Mobile.ListItem">List Item 1</li> 
        <li dojoType="dojox.Mobile.ListItem">List Item 2</li> 
        <li dojoType="dojox.Mobile.ListItem">List Item 3</li> 
    </ul> 
 </div> 

将清单 5 的源码粘贴到 index.html 文件的 body 标签中,并将此 Android 应用部署到模拟器上运行。若出现如图 11 的运行结果,表明配置成功。若出现白屏,很可能的原因是 Dojo 加载失败,详细原因可以参考 LogCat 视图中的错误提示。


图 11.Hello World 截图

图 11.Hello World 截图

BlueVM 设计及实现

此 Mobile 应用程序主要用于远程监控 JVM(Java 虚拟机)的运行状态。基于 Java 技术的服务器端应用程序是运行于 JVM 之上。一个应用程序可能包含若干个服务器端组件,且这些组件都运行于 JVM 上。目前,远程监控多个 JVM 需要切换到不同机器上,且必须要有 PC 或在这些机器附近才能够完成。BlueVM 可以解决这一繁琐的问题。只需要将 BlueVM 服务器端挂载到远端机器并提供机器的网络地址及端口号给 BlueVM 即可。

BlueVM 是典型的 C/S 架构,把 Server 端挂载到对应的服务器端组件上即可在手机等移动设备上监控服务器端 JVM 的运行状态。通过分析 JVM 的运行状态进而推测出服务器端组件的运行状况。BlueVM 架构图如图 12,左边是 Client 端将运行于手机等移动设备上。右端显示有 3 个应用程序服务器组件,这 3 个应用程序服务器组件都运行于 JVM 之上。在 JVM 之上灰色部分表示服务器组件,左边蓝色部分是挂载在此服务器端组件上的 BlueVM 的 Server 端。


图 12. BlueVM 架构图
图 12. BlueVM 架构图

BlueVM Server 端设计与实现

类 ManagementFactory 中实现了若干可以为 Java 平台获取 MXBean 的静态方法。这些 MXBean 代表了 JVM 运行状态的管理接口。这些接口可以提供 JVM 类装载、编译、垃圾回收、内存分配、操作系统、运行平台及线程等运行时信息。其中的每一种运行时的状态信息都有唯一的 MXBean 与之对应,正是这些 MXBean 提供了 JVM 的各种运行时信息。

此 Mobile 应用程序会展示给用户信息列表,用户可以根据自己的需要来选择信息的类型。因此,Server 端设计了若干个类来响应不同类型的请求。然而,由于这些类都要响应用户的请求,设计相同的接口更符合 Java 推荐的设计模式。因此,Server 端设计了一个公共的接口和继承于此接口的五个实体类来分别展示五种不同类型的信息。BaseAction 是公共接口,声明了 handleRequest 方法。类 ClassLoaderAction, GCAction, MemoryAction, ThreadAction 及 VMAction 都实现于 BaseAction 声明的 handleRequest 方法。

以 MemoryAction 为例讲解具体实现,清单 6 是 MemoryAction 的 Java 源码。可以看到,MemoryAction 实现了 BaseAction 接口声明的 handleRequest 方法。调用 ManagementFactory 类的 getMemoryMXBean 方法得到 MemoryMXBean 对象,获取其中堆及非堆的内存分配信息。将这些信息组装到 Json 对象中返回。图 13 中显示的是 JVM 某时刻的内存分配信息。


清单 6 类 MemoryAction 实现
				 
 public class MemoryAction implements BaseAction { 
 @Override 
 public Json handleRequest(Properties params) { 
		 MemoryMXBean bean = ManagementFactory.getMemoryMXBean(); 
		 MemoryUsage heapUsage = bean.getHeapMemoryUsage(); 
		 MemoryUsage nonHeapUsage = bean.getNonHeapMemoryUsage(); 
		
		 /** 
		 * {'heap':{'init':#,'committed':#,'used':#,'max':#},'non-heap':{}} 
		 */ 
		 Json heapJson = new Json(); 
		 heapJson.add("init", heapUsage.getInit()); 
		 heapJson.add("committed", heapUsage.getCommitted()); 
		 heapJson.add("used", heapUsage.getUsed()); 
		 heapJson.add("max", heapUsage.getMax()); 
		
		 Json nonHeapJson = new Json(); 
		 nonHeapJson.add("init", nonHeapUsage.getInit()); 
		 nonHeapJson.add("committed", nonHeapUsage.getCommitted()); 
		 nonHeapJson.add("used", nonHeapUsage.getUsed()); 
		 nonHeapJson.add("max", nonHeapUsage.getMax()); 
		
		 Json json = new Json(); 
		 json.add("heap", heapJson); 
		 json.add("non-heap", nonHeapJson); 
		
		 return json; 
	 } 
 } 


图 13. JVM 的内存分配
图 13. JVM 的内存分配

BlueVM Client 端设计与实现


图 14. Client 端 UI 设计
图 14. Client 端 UI 设计

图 13 及 14 是 Client 端的 UI 设计。图 14 中左边的截图是此 Mobile 应用程序的第一个页面。由图可知,有两种方式查看远端机器上 JVM 的运行时信息。既可以通过手动配置机器网络地址及端口号也可以预配置常用机器地址和端口信息来查看相关信息。图 14 右边的截图是此应用程序的第二个视图。由图可以看出 BlueVM Server 端共提供了五种类型的信息。点击 VM Info 即为图 13,BlueVM 的第三个页面,展示 JVM 的内存分配状况。第二及第三个视图的标题上兼有一个 Back 按钮,点击可以返回上一级页面。

上述的三个页面是由 Dojo Mobile 的 Widget 及 JavaScript 脚本实现。Dojo Mobile 为应用程序提供了非常丰富的组件 (Widget) 以简化页面的开发工作。每一个页面对应于 Dojo Mobile 的一个 View 组件。在 View 组件中存放各种能够容纳页面具体内容的组件,如 Heading(标题)、RoundRect(方框)及 EndToEndList(列表)等组件。清单 7 是图 14 右图 UI 源码。


清单 7.图 14 右图 UI 源码
				 
 <div dojoType="dojox.Mobile.View" id="propertyList"> 
   	 <h1 dojoType="dojox.Mobile.Heading" back="Back" moveTo="query">JVM Status</h1> 
    <ul dojoType="dojox.Mobile.EdgeToEdgeList"> 
        <li dojoType="dojox.Mobile.ListItem" moveTo="vmInfo" transition="slide"
 onclick="flags.vm=true;viewVMInfo();">VM Info</li> 
        <li dojoType="dojox.Mobile.ListItem" moveTo="mmInfo" transition="slide" 
        onclick="flags.mm=true;viewMMInfo();">Memory Info</li> 
        <li dojoType="dojox.Mobile.ListItem" moveTo="thInfo" transition="slide" 
        onclick="flags.th=true;viewTHInfo();">Thread Info</li> 
        <li dojoType="dojox.Mobile.ListItem" moveTo="clInfo" transition="slide"  
        nclick="flags.cl=true;viewCLInfo();">Class Loader Info</li> 
        <li dojoType="dojox.Mobile.ListItem" moveTo="gcInfo" transition="slide" 
        onclick="flags.gc=true;viewGCInfo();">Garbage Collection Info</li> 
    </ul> 
 </div> 

Server 与 Client 通信

由于 BuleVM 的 Client 是一个将 Web 技术封装为本地应用的程序,因此 Client 端可以通过发送 HTTP 请求来获取 Server 端的响应。Server 端使用 ServerSocket 实现了在某个端口上的监听,并等待 Client 的请求。当 Server 端监听到有 HTTP 请求到来的时候,会将此请求解析并调用对应的 Action 的 handleRequest 方法来响应。Client 端获取到 Server 端的响应内容之后解析并显示在页面中。因此,当点击第二个页面上的 Memory Info 会触发 Client 端的一个 Ajax 请求。此请求到达 Server 端时,Server 端调用 MemoryAction 的 handleRequest 方法产生 JSON 对象返回给 Client 端,当 Client 端收到此 JSON 对象后,解析其中的信息并显示在第三个页面上。


清单 8 获取 Memory 信息的 Ajax 请求
				 
 function viewMMInfo() { 
	 var surl = getUrl() + '?action=memoryinfo.do'; 
	 //ajax call 			
	 callHttp(surl,function(req) { 
 var data = eval("(" + req.responseText + ")"); 
 var heapData = data['heap']; 
		 var nonHeapData = data['non-heap']; 
					
		 $('hInit').innerHTML = (heapData['init']/1024/1024).toFixed(2)+'MB'; 
 $('hCommit').innerHTML = (heapData['committed']/1024/1024).toFixed(2)+'MB'; 
		 $('hUsed').innerHTML = (heapData['used']/1024/1024).toFixed(2)+'MB'; 
		 $('hMax').innerHTML = (heapData['max']/1024/1024).toFixed(2)+'MB'; 
				
 $('nhInit').innerHTML = (nonHeapData['init']/1024/1024).toFixed(2)+'MB'; 
 $('nhCommit').innerHTML=(nonHeapData['committed']/1024/1024).toFixed(2)+'MB'; 
 $('nhUsed').innerHTML = (nonHeapData['used']/1024/1024).toFixed(2)+'MB'; 
 $('nhMax').innerHTML = (nonHeapData['max']/1024/1024).toFixed(2)+'MB'; 
 }); 
	 // loop to refresh info 			
	 if(flags.mm){ 
		 window.setTimeout("viewMMInfo()",2000); 
	 } 
 } 

调试

Mobile 应用程序有与 Web 应用程序相似的技术。与此同时,又有很多不同于 Web 应用程序的方法及技术。若能及时发现与掌握相关的开发技巧必定能够事半功倍,调试便是其中基本技巧之一。

DDMS 前景图是 ADT 插件带来的,是 Android 应用者开发必备的工具。LogCat 是此前景图的一个视图,会输出程序中各类调试及错误信息。因此,在开发过程中除了需要关注控制台的提示信息外,LogCat 也能提供有用的调试信息。另外,在程序中可以嵌入特定的调试语句,运行时这些语句会产生相应的信息输出到 LogCat 中供开发者使用。


图 15. LogCat 视图

图 15. LogCat 视图

文章出处:IBM developerWorks

加载中
0
vancoud
vancoud
收藏之
0
左风雨
左风雨
dw大哥,你好,我是一名大学生,最近开发几个Android小程序,遇到了困难,这几个程序对我来说很重要,关系到我的学业,不知您肯不肯实施援手帮帮我,事成之后,定有重谢。我叫左风雨(手机号码13260539491)
0
MUTEX
MUTEX
Dojo Mobile 表现力不错。
0
GenericVal
GenericVal

为什么这么丑。。。

返回顶部
顶部