二、PhoneGap 入门
PhoneGap 入门指南(全)
原文:Beginning PhoneGap
协议:CC BY-NC-SA 4.0
零、简介
这本书是给谁的
这本书是为任何想要开始跨多个移动平台开发移动应用的人准备的。该书提供了关于 PhoneGap 的介绍和详细教程,并在以下方面为读者提供了帮助:
确定哪种 JavaScript UI 框架最适合他们
介绍 JavaScript UI 框架及其与 PhoneGap 的集成
解释插件的概念以及如何使用它来进行 OAuth 身份验证和云推送
解释如何编写自定义插件
这本书的结构
这本书首先解释了移动操作系统世界的碎片化以及它如何影响我们。它进一步讨论了如何弥合由于这种碎片化造成的差距,以及如何编写一次代码并跨移动平台部署它。
在 PhoneGap 背后的概念被弄清楚之后,这本书继续解释 PhoneGap 在 Android 上的用法,然后给出了如何在其他剩余的移动平台上做同样事情的说明。
接下来介绍了如何在 PhoneGap 上使用 JavaScript UI 框架,还讨论了在什么场景中使用哪个 JavaScript UI 框架。
最后,这本书将重点转移到插件上。它展示了几个如何用社区插件扩展 PhoneGap 框架的例子。然后解释了如何在 iOS、Android 和 BlackBerry 上构建这些插件。
下载代码
本书中提到的所有源代码都可以在[bitbucket.org/rohitghatol/apress-phonegap](https://bitbucket.org/rohitghatol/apress-phonegap)获得。这些章节本身就说明了这一点。也可在 Apress 网站[Apress.com](http://apress.com)上获得。
联系作者
可以通过作者的 LinkedIn 个人资料联系到他们:
Rohit Ghatol—[in.linkedin.com/in/rohitghatol](http://in.linkedin.com/in/rohitghatol)
Yogesh Patel—[www.linkedin.com/profile/view?id=19911394](http://www.linkedin.com/profile/view?id=19911394)
一、了解跨平台移动应用开发
这本书是关于移动应用开发的;更确切地说,是关于减轻移动应用开发的痛苦。市场上有许多智能手机平台:安卓、iPhone、黑莓、诺基亚、Windows 7 手机和 WebOS。更新的平台也在增加,比如三星的 Bada 和 Meego。
移动应用开发平台的数量之多似乎令人应接不暇。在处理移动应用开发时,这是你必须记住的第一点。
在 2000 年,我们在台式机领域看到了类似的情况。我们有微软的 Windows,苹果的 Mac,以及各种版本的 Linux 和 UNIX。那时,很难构建能在所有这些平台上运行的产品。由此产生的碎片通常通过内部解决方案来解决,方法是用 C++构建框架,抽象出特定于操作系统(OS)的模块。幸运的是,Sun 的 Java 拯救了我们,为我们提供了一个通用的构建平台。有了 Java 的“一次构建,随处运行”策略,构建桌面产品变得轻而易举。
在 2004 年到 2008 年之间,开发者社区看到了一种不同的分裂;这一次,它发生在浏览器世界。这是一场涉及非常流行的 Internet Explorer 6 与 Firefox 和 Safari 的分裂——然后,Chrome 和其他浏览器突然出现,导致了进一步的分裂。
然而,这种碎片化的本质是不同的,更温和一些:这主要是由于浏览器没有遵循万维网联盟(W3C)概述的规范。通常,这种分裂是通过写“如果浏览器是 IE,那么做这个做那个”或者“如果特性存在,那么做这个做那个”来解决的。
许多 JavaScript 库来帮忙编写跨浏览器的 web 应用。事情已经改善到这样的程度,所有的浏览器都在努力工作,越来越符合 W3C 规范。浏览器作为一个平台,现在是一个强有力的竞争者。
这本书是关于移动世界的碎片化。移动操作系统碎片化非常严重,因为在这个开发领域没有规范或标准。
2007 年,苹果和谷歌推出了他们的移动平台。2008 年,两家公司都推出了移动应用商店,允许智能手机用户下载移动应用。移动应用的时代已经开始;从此,再也没有回头。智能手机用户数量呈指数级增长。
公司开始专注于在新的智能手机平台上提供服务和内容。企业意识到他们需要将注意力转移到智能手机用户身上。不仅用户数量增加,智能手机的使用频率也增加了。
想象一下,您的开发人员日以继夜地在 iPhone、Android、BlackBerry、WebOS 和 Symbia 上发布相同的产品——现在,让我们将 Samsung Bada 添加到这个列表中!你可以看到这里的挑战。操作系统平台,从它们的开发环境开始,是如此的分散。对于 iPhone,你将需要 Mac 机,对于黑莓,你将需要 Windows。本章将更详细地讨论这些事情。
现在,对于那些刚接触移动应用开发的人来说,我们将从关注创建一个移动应用是什么样子开始。我们将回答诸如“移动应用与传统的基于网络或基于桌面的应用有何不同?”我们将研究为各种平台开发移动应用的挑战。
移动应用的类型
了解不同类型的移动应用非常重要。我将根据他们的工作把他们分为两类。
独立移动应用
移动应用(基于 web 服务)
独立移动应用是诸如闹钟、电话拨号器和离线游戏之类的应用。支持 Web 服务的移动应用包括电子邮件、日历、Twitter 客户端、在线游戏以及与 web 服务交互的应用。
这种移动应用之间的区别是本书上下文中所独有的。虽然 PhoneGap 可以用来实现独立的移动应用,但是基于 PhoneGap 的移动应用的本质通常属于“服务支持的移动应用”的范畴
了解 Web 服务
作为一名开发人员,当你看互联网上的 web 应用时,你需要考虑两种 web 开发。
可通过浏览器访问的 Web 应用(用于人机交互)
可以通过 RESTful Web 服务之类的协议访问的 web 服务(用于编程接口)
所有流行的网络应用,如谷歌、脸书、Twitter、LinkedIn、MySpace、Flickr 和 Picasa,都为它们的服务提供了 RESTful 界面。这类网站有很多在线词典。如果你访问[www.programmableweb.com](http://www.programmableweb.com),你会看到一个相当大的列表,列出了所有为编程接口提供此类服务的网络应用(见图 1–1)。
图 1–1。 可编程 Web API 目录
许多想要为多个平台开发移动应用的公司要么拥有自己的 web 服务,要么依赖于其他 web 服务。虽然 PhoneGap 可以用于独立的移动应用,但它非常适合使用 web 服务的移动应用。原因是 PhoneGap 应用主要是增加了设备功能的 web 应用。想象一下,一个 Flickr web 应用可以访问设备的摄像头或 Google Maps 应用,而后者又可以访问 GPS。另一个例子是 Foursquare,它可以访问你的 GPS,以及你手机的通讯录。
这或多或少意味着大多数基于 PhoneGap 的应用将使用 JavaScript 访问 web 服务。这使得使用 PhoneGap 的开发人员掌握使用 web 服务变得非常重要。
对于读过这本书后想要编写 PhoneGap 应用的开发人员,我建议在 ProgrammableWeb.com 上找到一些 web 服务,并为这些服务编写一个 PhoneGap 客户端作为练习。
这本书将提供一个这样的服务的例子;也就是 AlternativeTo.Net。
移动应用概述
虽然你们中的许多人至少有一些使用移动应用的经验,但你们中的许多人更熟悉非移动平台(例如,web 平台)。因此,这本书明确论述了移动应用的本质以及与之相关的挑战。如果您来自非移动背景,这将有助于您理解开发移动应用意味着什么。
移动应用功能
图 1–2。 移动应用不是 web 应用。
首先要注意的是,移动应用不是 web 应用。区别在于特性的性质和所提供的特性数量(参见图 1–3)。
移动应用的功能可能会更少。
您可以期待您的移动应用看起来与您的 web 应用非常不同。首先,智能手机的屏幕大小与桌面不同。在 web 应用中,屏幕越大,你就有越多的空间来放置菜单、工具栏和小部件。
考虑到智能手机的屏幕尺寸限制,你会看到更多仪表板类型的主屏幕。
智能手机用户需要通过不同级别的导航来找到他或她想要使用的功能。
智能手机用户和网络用户有不同的意图。智能手机用户希望在旅途中使用应用,以最少的努力获得最大的生产力,而网络用户可能会花更多的时间使用网络应用。
由于上述差异,您将看到智能手机上最具生产力(或最常用)的功能被突出显示。无论移动应用提供所有的功能,还是其中的一个子集,这些小的生产(和最频繁使用的)功能集将在移动应用上以最容易访问的方式进行组织。
图 1–3。 移动功能与网络应用功能不同。
用户互动
相对于传统的 web 应用,用户与移动应用交互的方式非常不同(参见 Figure 1–4)。
随着智能手机的触摸屏功能和更加生动的用户交互,基于加速度计和指南针,移动应用必须以不同的方式构建。
想象一个汽车游戏应用,通过向左或向右倾斜手机来操纵汽车。这是基于加速度计。想象一个地图应用,当用户改变他或她的方向时,它总是指向北方。这是基于一个指南针。
虽然与应用交互的新方式增强了用户体验,但新的移动平台上缺少物理键盘给 power keyboard 用户增加了一些额外的限制。在详细阐述移动应用需求时,需要考虑到这一点。
除此之外,智能手机有两种显示模式:布局和纵向;这些在早期的浏览器中是闻所未闻的。记录需求规格的一个重要部分是定义当设备处于纵向或横向模式时应用的外观、感觉和行为。
图 1–4。 智能手机和网络应用有不同的用户输入界面。
位置感知
位置感知是智能手机与生俱来的功能。谷歌地图、本地搜索、Foursquare 和许多其他移动应用都利用了智能手机的精密 GPS。Web 应用也使用位置感知;然而,这些应用使用相对更粗粒度的 GPS 系统(例如,国家级)(见图 1–5)。
图 1–5。 与网络应用相比,智能手机应用的位置感知能力
推送通知
应用用户喜欢收到有用事件的通知,比如收到的电子邮件和消息。智能手机是最好的通知平台,因为它几乎无时无刻不在用户身边。
除了收到电子邮件或信息等通知,任何服务都可以向智能手机用户发送通知(见图 1–6)。考虑一个组织的工作流程。用户不必总是登录 web 应用来完成涉及他或她的工作流,应用通知用户他或她需要执行某个操作来完成工作流会更有效率。这样,无论用户是否靠近笔记本电脑或台式机,他/她都可以始终高效地工作。
图 1–6。 智能手机的推送通知功能(移动通知)
跨平台移动应用开发的挑战
虽然移动应用的开发令人兴奋,但考虑到移动操作系统(OS)数量的不断增长,开发移动应用会面临许多挑战。
让我们来看看这些挑战。
OS 碎片化
碎片化增加的趋势与移动平台数量的增长相一致(参见图 1–7)。首先是黑莓和塞班智能手机,然后是强大的 iPhone 和 Android 平台。可以肯定的是,移动平台并没有就此止步。惠普随 WebOS 而来;微软推出了 Windows 7 手机;而现在,三星要出 Bada 了。
这意味着公司必须不断推出新产品,让所有移动平台都能感受到它们的存在。
图 1–7。 由于移动操作系统数量的增长而导致的碎片化
假设你想开发一个移动应用,目标是 iPhone,Android,BlackBerry 等。由于每个移动平台的操作系统不同,请考虑以下因素:
首先,你必须为每个平台设置不同的环境。
第二,你需要对每个操作系统有一点专业知识。对于移动开发者来说,学习曲线可能会很长。
不同的移动平台需要不同的编程语言。
你需要熟悉每个移动平台支持的特性;参见图 1–10。
表 1-1 描述了移动应用开发所需的设置(针对各种移动平台)。
过去,我们已经看到过类似的操作系统碎片化,从 Windows、Linux 和 Mac 的跨桌面碎片化开始,随着 Sun 推出 Java,这一问题得到了解决。在更近的过去,我们面临浏览器碎片,这是通过跨浏览器 JavaScript 框架如 jquery、YUI 和 Google Web Toolkit 解决的。
移动操作系统碎片是所有碎片中最糟糕和最多样化的。这为在所有移动平台上启动移动应用增加了相当大的技术挑战。
多个团队/产品
如果我们选择使用多个团队为每个平台构建一个移动应用,我们会面临许多问题;增加团队会增加项目交付的风险;增加产品意味着产品管理团队承担更多责任(参见图 1–8)。由于所有移动平台上的功能也是分散的,产品管理人员必须对每个平台上的产品提出具体要求。
最终,增加更多的团队,增加多个团队之间的协调,以及增加多个产品将导致管理和开发团队的额外开销。
图 1–8。为不同的移动操作系统增加多个团队带来了新的问题。
一致的用户体验
鉴于您希望您的应用在多个移动平台上保持一致,您的应用需要在所有平台上提供相似且一致的用户体验(参见 Figure 1–9)。这也与您的最终用户可能从一个平台迁移到另一个平台有关,或者他们可能存在于多个平台上。考虑一个拥有 Android 智能手机和 iPhone iPad 的用户。用户可以在家或在办公室使用 iPad,也可以在外出时使用 Android 智能手机。
这是你的应用必须提供跨移动平台的相似用户体验的众多原因之一;当然,由于设备特性和功能的分散,用户体验会因移动平台而有所不同。
图 1–9。 为跨平台的应用最终用户提供统一的用户体验
特征碎片化
设备特性和功能因平台而异(参见图 1–10)。这意味着,虽然一些机器人和 iPhones 有嵌入式指南针来显示方向,但其他智能手机没有。这可能意味着其他智能手机上的导航应用可能无法像 Android 或 iPhone 应用那样旋转地图。
总的来说,同一个应用在一些移动平台上会关闭一些功能,这是事实;应用的逻辑需要以这种方式编写。
图 1–10。 针对不同移动操作系统的特性碎片化
开发环境碎片化
开发环境是一个特别重要的片段。如果您想开发一个面向以下平台的移动应用,您至少需要两个操作系统:Windows(最好是 Windows 7)和 Mac(最好是 Leopard ):
ios
机器人
黑莓
WebOS
智能移动终端操作系统
Windows 7
此外,您将不得不使用各种 ide 和编程语言,如 Java、C++和 Objective C。此外,您将使用许多 ide,如 Xcode 和 Eclipse。
表 1-1 显示了开发环境的要求(针对各种移动平台)。
PhoneGap 的跨平台移动应用战略
PhoneGap 之所以成为可能,是因为所有移动平台之间的共性。如果没有这个通用组件,PhoneGap 就不可能存在。
浏览器组件作为通用平台
直到几年前,浏览器世界还很分散。当时,不同的浏览器在不同程度上遵循 W3C 标准。Firefox 和 Safari 浏览器在遵守标准方面走在了前列,而其他浏览器则落在了后面。
从那以后,很多事情都变了。现在,浏览器在遵守标准方面看起来更好了(在移动平台上更是如此)。这也是事实,因为大多数现代移动平台都有相同的基于 webkit 的浏览器。
此外,桌面和智能手机上的新浏览器已经开始遵循 HTML5/CSS3 等新标准。这为浏览器世界增加了更多功能,减少了移动平台之间的碎片化(参见图 1–11)。
图 1–11。 手机浏览器
我们来看表 1-2 ,表中列出了移动平台及其对应的浏览器平台。如你所见,除了 Windows 7 手机,所有的移动平台都使用基于 webkit 的浏览器。虽然 Windows 7 手机有自己的浏览器,但好消息是,这里列出的所有浏览器都已经遵守 HTML5/CSS3 标准,随着时间的推移,它们的遵守程度将继续提高。
PhoneGap 使用这些现代浏览器作为构建基于 HTML5/CSS3 的应用的平台。把所有 PhoneGap 应用想象成具有嵌入式浏览器并运行这些基于 HTML5/CSS3 的应用。
移动应用网页浏览量
所有这些移动平台都支持在应用中嵌入浏览器。这意味着移动应用的一个屏幕实际上可以是一个显示 HTML 页面的浏览器。
这些嵌入式浏览器通常被称为网络视图。这意味着您可以将应用的一个屏幕定义为 webview。
假设您的应用有一个名为“关于我们”的屏幕“关于我们”屏幕显示贵公司的信息。现在,让我们假设,例如,关于贵公司的“关于我们”的信息经常改变。您的移动应用的要求之一是显示最新的“关于我们”的信息。因此,您可以显示一个指向贵公司“关于我们”页面的 webview,而不是显示一个硬编码的“关于我们”屏幕(最好是网页的移动版本)。它将从网上加载“关于我们”页面。此外,webview 可用于加载和显示本地存储在移动设备上的 HTML 页面。我们可以进一步发展这个概念:我们可以显示与 web 服务交互的基于 Ajax 的 web 页面,而不是静态 web 页面。
本机挂钩暴露设备能力
既然我们知道浏览器可以嵌入到 web 应用中,让我们把注意力转移到通过这些嵌入式浏览器来公开设备功能上。
假设您正在开发一个基于 Flickr API 的 Flickr 应用。在这些 API 的帮助下,你可以登录 Flickr,列出图库,下载和展示你的图片。
虽然这对于 web 应用来说是一个好主意,但是当我们在手机上显示相同的应用时,请记住手机通常有一个摄像头。允许 Flickr 应用从相机中拍摄一张照片并上传到 Flickr 是非常合理的。
为了做到这一点,我们可以让嵌入式浏览器(或 webview)公开 JavaScript API,当调用该 API 时,它会让相机拍摄一张照片,并将该照片的二进制数据返回给我们(参见图 1–12)。
图 1–12。 JavaScript 到本地通信,反之亦然
从技术上讲,所有这些平台都支持在 webview 中将本机模块暴露给 JavaScript。这意味着,从程序上讲,所有这些平台都允许 JavaScript 代码调用本地 Java/C++/Objective C 代码,反之亦然。
让我们看一个例子。我们的 webview 有一个 HTML 页面,显示的是谷歌地图。我们希望根据手机的 GPS 位置将地图居中。为了做到这一点,我们需要编写一个本地组件,向设备查询 GPS 位置。
然后,我们编写代码,从 webview 中公开这个本机模块。webview 中的 JavaScript 代码调用此代码来访问 GPS 坐标。一旦代码获得了 GPS 坐标,它就相应地将地图居中。这是 PhoneGap 框架背后的主要原则。
HTML5 和 CSS3:编写应用的标准
HTML5 和 CSS3 是新兴的 web 技术。他们使网络应用更具交互性,功能更丰富。
HTML5 不仅为更强大的多媒体支持增加了新的标记;它还增加了一些特性,比如用于后台处理的 web worker、离线支持、数据库支持等等。
CSS3 是无缝、丰富的用户界面(UI)的新标准。设计师被要求在按钮或边框上制作简单的圆角或渐变的日子已经一去不复返了。有了 CSS3,事情变得更容易、更快、更好。
有了对动画的支持,CSS3 站点现在可以与基于 flash 的站点竞争了。不仅如此,只需更改 CSS 文件,门户网站就可以轻松地转换为移动网站。此外,打印预览现在可以实现不同的 CSS 文件。
众所周知,移动浏览器是 W3C 标准的早期采用者。这意味着手机是 HTML5/CSS3 应用的合适平台。
单一原产地政策不适用
对于那些使用过基于 Ajax 的应用的人来说,你知道托管在“abc.com”上的 web 应用不能对托管在“xyz.com”上的 web 服务进行 Ajax 调用。这意味着如果有人正在开发一个基于 Ajax 的应用,比如托管在 myphotobook.com 上,他或她将不能对 flickr.com 进行 Ajax 调用。
这被称为单一原产地政策——你可以在[en.wikipedia.org/wiki/Same_origin_policy](http://en.wikipedia.org/wiki/Same_origin_policy)进一步了解单一原产地政策。
对于 PhoneGap 应用来说,情况并非如此。PhoneGap 应用捆绑了所需的 HTML、JavaScript 和 CSS 文件,PhoneGap 应用没有像“abc.com”这样的域。这使得 PhoneGap 成为一个易于开发混搭的平台,可以自由地对各种其他站点进行 Ajax 调用。
想象一下,您的 PhoneGap 应用将脸书、Twitter 和 Flickr 集成到一个 mashup 中,只需要几行 JavaScript 代码。
这使得 PhoneGap 成为为在 programmableweb.com 上市的网络服务创建移动应用的理想平台。
这些限制在图 1–13 中说明:
图 1–13。 单一原产地政策
结论
PhoneGap 使用 HTML5、JavaScript 和 CSS3 来开发移动应用。这些是网络世界的标准技术。通过使用 PhoneGap,很少或没有母语背景的开发人员可以开始为所有流行的移动平台开发移动应用。
尽管 PhoneGap 提供了对移动应用标准原生功能的访问,但它的插件框架足够灵活,可以根据需要扩展和添加新功能。
PhoneGap 是一项正在发展的技术,用于开发跨移动平台应用。
二、PhoneGap 入门
PhoneGap 是一个 HTML5 应用框架,用于通过 web 技术开发本地应用。这意味着开发人员可以利用他们现有的 HTML、CSS 和 JavaScript 知识开发智能手机和平板电脑应用。有了 PhoneGap,开发人员就不必为 iPhone 学习像 Objective-C 这样的语言了。
使用 PhoneGap 开发的应用是混合应用。这些应用不完全基于 HTML/JavaScript,也不是本地的。应用的各个部分,主要是 UI、应用逻辑和与服务器的通信,都是基于 HTML/JavaScript 的。与设备(手机或平板电脑)进行通信和控制的应用的另一部分基于该平台的本地语言。PhoneGap 提供了从 JavaScript 世界到平台本地世界的桥梁,允许 JavaScript API 访问和控制设备(手机或平板电脑)。
PhoneGap 本质上为 JavaScript API 提供了对设备(手机或平板电脑)功能的访问,如摄像头、GPS、设备信息等。这些 API 将在第四章中详细介绍。
本章首先为您提供理解 PhoneGap 整体架构的适当信息。然后,我们将在 PhoneGap 示例中应用这些信息。在本章的最后,我们将使用 PhoneGap 编写一个小的 Hello World 应用。
注: PhoneGap 是一个框架;它没有为编码提供任何 ide 或特殊的开发环境。您将需要使用 Eclipse 和 Android SDK 来为 Android 开发 PhoneGap 应用;您需要使用 Xcode 为 IPhone 开发 PhoneGap 应用。
PhoneGap 架构
图 2–1。 PhoneGap 应用架构
PhoneGap 框架主要是一个 JavaScript 库,允许 HTML/JavaScript 应用访问设备功能。PhoneGap 框架也有一个本地组件,它在幕后工作,并在设备(手机或平板电脑)上完成实际工作。
请参考图 2–1 了解 PhoneGap 的整体架构。使用 PhoneGap 构建的应用主要由两部分组成:
JavaScript 业务逻辑部分,驱动 UI 及其功能。
JavaScript 部分,用于访问和控制设备(手机或平板电脑)。
考虑一个脸书应用。该应用的主要部分将是登录页面,并下载照片库。现在你想添加一个你可以拍照并上传到脸书的模块。为了做到这一点,您可以调用 PhoneGap 的相机 API 来访问手机的相机,拍摄照片,并获取图片文件。下一步是对脸书服务器的 AJAX 调用,以便上传图片。另一个可以应用的例子是使用 PhoneGap 在数据库中存储朋友列表,这样我们就可以搜索当地的朋友。
前面的描述给人的印象是,在 PhoneGap 中开发移动应用需要编写更多的业务逻辑和 UI,而很少访问设备的功能,这是正确的。这本书不仅解释了 PhoneGap APIs,也是创建基于 HTML5/CSS3 的移动应用的指南。
在 Android 上设置环境
创建 PhoneGap 应用的第一步是设置一个移动开发环境。我们将从 Android 开始,因为 Android 应用是用 Java 开发的,Java 基于 Eclipse,支持 PhoneGap 的几乎所有功能。
您需要下载并安装 Android 的以下必备软件:
JDK 1.6 以上
Eclipse 3.4 到 3.6
采用 Android 2.2 平台的 Android SDK
Eclipse 的 Android ADT 插件
Android 2.2 版的 Android AVD
Android 版 PhoneGap SDK 1.1.0
由于 Android 是用 Java 编程的,所以我们需要 JDK 1.6+和 Eclipse 3.4+。然后我们将安装 Android SDK。Android SDK 是一个通用的 SDK,不支持任何平台。一个平台就是一个操作系统版本,例如 2.2 版的 Froyo、2.3 版的津嘉·布雷德和 3.0 版的蜂巢。为了创建、构建和运行 Android 项目,需要下载这些平台。这个插件叫做 Android ADT 插件。
一旦 Eclipse、Android SDK 和 Android ADT (Eclipse 插件)都设置好了,我们就需要为 Android 创建一个模拟器环境。这被称为准备 Android AVD (Android 虚拟设备)。如果我们正在为 Android 开发一个针对 2.2 Froyo 的 PhoneGap 应用,我们需要一个相同 Android 平台的 AVD。
以下步骤将解释如何创建一个 Android 项目并将 PhoneGap 库注入到 Android 中。
PhoneGap Android 项目的必需安装
安装 Eclipse 的 3.4 版本。
安装 Android SDK。
为 Eclipse 安装 Android ADT 插件。
为模拟器创建 AVD。
安装 PhoneGap 库。
第一步:安装 Eclipse
这一步假设您已经安装了 Java SDK 1.6。安装完成后,从[www.eclipse.org/downloads/](http://www.eclipse.org/downloads/)下载 Eclipse。参见图 2–2 查看 eclipse 下载页面。我们需要一个支持 JDT (Java 开发环境)的 Eclipse IDE 版本 3.4+。您应该为 Java 开发人员安装 Eclipse IDE。
图 2–2。 月食下载页面
第二步:安装 Android SDK
设置 Android 开发环境的一些步骤是依赖于平台的。为了避免任何混淆,我们将解释如何以特定于平台的方式执行每个步骤。
从[developer.android.com/sdk/index.html](http://developer.android.com/sdk/index.html)开始下载 Android SDK(参见图 2–3)。
图 2–3。 Android SDK 下载页面
针对 Windows 的说明
使用 Android 安装程序,安装程序 r11-windows.exe 安装 Android SDK。这是推荐的 Windows 安装技术。另一种方法是下载 android-sdk r11-windows.zip 文件,并将其解压缩到一个文件夹中。我们假设 Android SDK 被提取到 c:\android_sdk。
【Linux 操作说明
下载 Archie Android-dk _ r11-Linux _ x86 . tgz 归档文件并解压到一个文件夹中。
Mac OSX 英特尔指令
下载存档 android-sdk_r11-mac_x86.zip 文件,并将其解压缩到文件夹中。
这个 Android SDK 可以支持目前已经发布的所有 Android 平台。这些平台包括 Android 1.1 平台到最近的 Android 3.0(蜂巢)平台。由于没有人需要所有的平台,Android SDK 没有预装任何平台。
对于本书,我们将只关注 SDK 平台:Android 2.2、API 8 和 revision 3。
由于没有预装平台,下一步是安装您感兴趣的平台。转到 Android SDK 位置(在我们的例子中是 c:\android_sdk),在 tools 文件夹中打开一个名为 Android 的可执行文件。如果您有带宽限制,不要下载所有平台,只下载 Android 2.2 平台(SDK 平台 Android 2.2、API 8 和修订版 3)。
这将打开在图 2–4 中看到的以下屏幕。选择可用的包选项,检查 Android 存储库,然后单击 Install。
图 2–4。 可以安装的可用平台包
既然您已经下载了平台,那么您就拥有了为目前已经发布的所有 Android 版本创建应用的必要工具。
建议您安装所有可用的包,这样您就可以有工具为已经发布的任何 Android 平台创建 Android 项目。
如果你想开发一个适用于 Froyo (Android 2.2)的移动应用,你需要有 Froyo (Android 2.2。)列在已安装的软件包中。
步骤 3:为 Eclipse 安装 Android ADT 插件
启动 Eclipse 并点击 Help->Install New Software 打开可用软件对话框。
在“使用”文本框中,输入 URL [dl-ssl.google.com/android/eclipse](https://dl-ssl.google.com/android/eclipse),如图 2–5 所示。
当您看到安装开发人员工具的选项时,单击它,选中开发人员工具复选框中的所有复选框,然后单击下一步。
图 2–5。 为 Eclipse 安装 Android ADT 插件
用之前安装的 Android SDK 的位置配置 Android ADT 插件。通过单击 Windows-> Windows 的首选项和 Eclipse-> Mac 的首选项打开 Eclipse 的首选项。如果您收到未签名内容警告对话框,您可以安全地忽略它。
In the Preferences pane, click and expand the Android option. You will see Android Preferences pane as shown in Figure 2–6. In the Android Preferences pane, put in the location of the Android SDK in the SDK Location text box, and hit Apply.
如果 Android SDK 的位置是正确的,您应该在 Target Name 下看到许多选项,包括 Android 2.2。
图 2–6。 在 Android 首选项屏幕中设置 Android SDK 的位置。
步骤 3:为 Android 2.2 平台创建 Android AVD
Open Eclipse and create a workspace for the Android PhoneGap. The next step is to create an emulator for Android. Since Android comes with many platform versions, we have to create an Android Virtual Device (AVD) for each platform that is targeted. In Figure 2–7, you will see your eclipse as depicted in the screen.
请注意,Android 模拟器运行的是 Android 虚拟设备(AVD)。
图 2–7。 带 ADT 插件的 Eclipse。
Click on the button on the toolbar to open the Android SDK and the AVD Manager. Choose the Virtual Devices option as depicted in Figure 2–8.
图 2–8。Android SDK 和 AVD 管理器
点击新建按钮创建一个新的 AVD。选择 Android 2.2 平台,也就是 Froyo。选择 128 MB 的 SD 卡大小,并选择皮肤内置为 HVGA。填写完所有内容后,单击 Create AVD。参见图 2–9 查看“AVD 屏幕”的样子。
图 2–9。 创建一个新的 Android 虚拟设备(AVD)在 Android 模拟器中运行
您将看到创建的 AVD,如图 2–10 所示。
图 2–10。 安卓 2.2 平台的 AVD(Froyo)
步骤 4:安装 PhoneGap SDK
Download the PhoneGap SDK 1.1.0 from the following link, [phonegap.googlecode.com/files/phonegap-1.1.0.zip](http://phonegap.googlecode.com/files/phonegap-1.1.0.zip). After this zip is extracted you should see a directory structure, as seen in Figure 2–11.
图 2–11。 PhoneGap SDK 1.1.0 目录结构
选择 Android 目录,你会看到 phonegap-1.1.0.jar 和 phonegap-1.1.0.js 文件(见图 2–12)。
图 2–12。PhoneGap SDK 内的 Android 文件夹。
这就完成了 Android PhoneGap 的设置。
创建新项目
本书中的第一个应用是 Hello World 应用。加载 PhoneGap 框架后,Hello World PhoneGap 移动应用会在屏幕上显示 Hello World。
第一步:创建一个 Android 项目
打开 Eclipse,点击文件->新建项目->Android 项目。这将打开一个 Android 项目对话框,如图 2–13 和图 2–14 所示。这显示在以下步骤中:
将 PhoneGap-helloworld 作为项目名称。
确保您已经选择了 Android 2.2 作为构建目标。
输入 Helloworld 作为应用名称。这是应用的可读名称。
输入org.examples.phonegap.sample作为包名。Android market 中的一个应用是由包名唯一标识的。Android market 上不能有两个具有相同包名的 Android 应用。
选中“创建活动”复选框,并输入 helloworld 作为活动名称。Android 中的活动是一个屏幕。并且活动名也是活动的类名。
在 min SDK 版本中放 7。这意味着您将允许所有 Android 2.1 设备平台(也称为 clair Android 手机)搜索和安装该应用。
图 2–13。 安卓项目创建
图 2–14。 Android 项目创建。
步骤 2:将 PhoneGap 库添加到项目中
一旦创建了 Android 项目,就该将 PhoneGap 框架注入到 Android 项目中了。正如我们之前提到的,PhoneGap 有三个主要组件:原生组件、XML 插件和 JavaScript 文件。
要在 Android 中安装原生组件,在项目中创建一个名为 lib 的目录,并将 PhoneGap jar 复制到其中。您可以将phonegap-1.1.0.jar拖放到 lib 文件夹中,也可以将其复制并粘贴到 Eclipse IDE 的 lib 文件夹中。接下来,通过右键单击 Build Path - > Add to Build Path,将 PhoneGap jar 添加到类路径中。这在图 2–15 中突出显示。
Copy the XML directory from the PhoneGap’s Android Directory into the res folder.
图 2–15。 突出显示 Android 项目中 PhoneGap jar 的位置
一旦 PhoneGap Jar 被添加到 Android 项目中,就该将 PhoneGap 的 JavaScript 文件注入到项目中了。我们将在 Android 项目的 Assets 文件夹下创建一个 www 文件夹。Assets 文件夹类似于 Android 应用的 media 文件夹。在我们的例子中,我们将把基于浏览器的应用的所有文件放在 www 文件夹中。首先,将 PhoneGap JavaScript 文件添加到 www 文件夹中,该文件夹位于 Assets 文件夹中。这在图 2–16 中突出显示。
图 2–16。 突出显示 PhoneGap JavaScript 文件在 Android 项目中的位置
第三步:修改 Android 权限
在 Android 应用中,主文件是 Android 清单文件。在这个文件中有许多特定的东西,比如包名,它们唯一地标识了市场上的应用。主文件包含一个名为 permissions 的部分。Android 使用这一部分来通知用户应用将使用手机的某些功能。假设一个应用打算使用互联网获取数据;需要获得许可才能安装应用。当用户安装应用时,Android market 会向他显示该应用将被允许使用互联网。
对于 PhoneGap,需要添加以下权限:
向 Android 清单 XML 添加以下权限:
我们还需要在清单文件中添加 supports-screen 选项,如下所示:
将android:configChanges=orignetation|keyboardHidden添加到 Android 清单中的活动。这告诉 Android 当用户翻转手机,屏幕从纵向切换到横向时,不要取消和重新创建活动,反之亦然。
通过应用以下 XML 片段,在前一个活动之后添加第二个活动:
一旦您按照前面的说明修改了 Android Manifest,就会出现一个 Android Manifest XML。将会看到如下内容:
`
package="org.examples.phonegap.helloworld" android:versionCode="1" android:versionName="1.0"> android:normalScreens="true" android:smallScreens="true" android:resizeable="true" android:anyDensity="true" /> android:configChanges="orientation|keyboardHidden"> android:configChanges="orientation|keyboardHidden"> ` 第 4 步:修改主活动 在 Android 中,一个名为 activity 的类代表一个屏幕。为了让我们在 Android 中使用 PhoneGap,我们将把屏幕从活动更改为 DroidGap。DroidGap 是一个特殊的活动,它允许我们显示 HTML 页面。该类如 HelloWorld 类的图 2–17 所示。 注意:我们告诉 DroidGap 在 Android 资产中加载 index.html 文件。 `package org.examples.phonegap.helloworld; import android.os.Bundle; import com.phonegap.DroidGap; public class HelloWorld extends DroidGap { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.loadUrl("file:///android_asset/www/index.html"); } }` 图 2–17。 扩展 DroidGap 类的活动 编写 HelloWorld 应用 PhoneGap 应用是一个 HTML/JavaScript 应用。参见图 2–18。下面是 index.html。 在 HTML 页面中包含 PhoneGap JavaScript 库版本 1.1.0。 用主体的 onload 事件注册init()方法。 在init()函数中,用 DeviceReady 事件注册 JavaScript 回调函数 onDeviceReady。 在 onDeviceReady 回调函数中,将 ID 为“helloworld”的h1元素的内容更改为文本“hello World!已加载 PhoneGap 框架!” 这里列出了完整的源代码: ` PhoneGap ... `  图 2–18。PhoneGap 项目的 Index.html?? 你可以从[bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-Helloworld](https://bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-Helloworld)下载本章的完整源代码 部署到模拟器 为了运行 Android 应用,右键单击 PhoneGap-helloworld 项目,选择 Run As,然后选择 Android 应用。 这将启动带有我们之前创建的 AVD 的模拟器。当应用加载时,您将看到以下屏幕。随着应用的启动,您将在屏幕上看到…,如图图 2–19 所示。 图 2–19。PhoneGap 应用加载了…几秒钟。 加载 PhoneGap 框架后,您会看到应用显示一条消息,如图 Figure 2–20 所示。 图 2–20。PhoneGap 框架加载部署到设备应用后,PhoneGap 应用显示一条消息。 到目前为止,我们已经看到了如何在模拟器上测试应用。但是,有些功能不能在模拟器上测试。为了测试 GPS、相机、加速度计、罗盘和实际用户感知,需要测试实际设备。 部署到设备 将 Android 应用部署到设备需要两个步骤: 第一步:准备好设备。 Unlock your device and press the Menu key. This will give you a view that looks like Figure 2–21. 图 2–21。 进入安卓手机的设置 Click on the Settings and the screen in Figure 2–22 will appear. Choose the Applications option. 图 2–22。 进入应用设置 Now we must ensure that we can deploy non-Market applications on our device. This is done by clicking the Unknown sources, seen in Figure 2–23. 图 2–23。 点击未知来源,我们可以添加非市场应用 下一步是进入开发选项(见图 2–24)并启用 USB 调试(见图 2–25)。这允许你将 USB 线的一端插入你的 Android 设备,另一端插入你的 PC 或 Mac。使用 Eclipse 调试设备上运行的应用。 图 2–24。 进入开发选项 图 2–25。启用 USB 调试 现在,您的设备已经准备好部署应用。 Android ADT 插件为 Android 提供了一个 Dalvik 调试监控服务器(DDMS)。DDMS 有许多功能,例如列出当前可用于部署和调试 Android 应用的设备/仿真器,允许用户查看部署在设备/仿真器上的应用的日志消息,以及浏览设备/仿真器的文件系统。 步骤 2:在应用启动类型中,提供我们打算部署到设备的信息。 Plug the USB cable into your device, and plug the USB end into your development machines. Now open Eclipse and go into the DDMS perspective (Go to Eclipse->Windows->Open Perspective->DDMS). You will see a screen like Figure 2–26. This screen depicts that we have an Android emulator running, and that we also have an Android device plugged into the machine’s USB input. 图 2–26。DDMS 显示我们有一个仿真器在运行,一个设备插入了 USB。 当您点击您的 Android 项目的任何 Android 应用的 Run As 时,您将看到图 2–27 中的屏幕。您看到这个屏幕是因为您有一个仿真器和一个可用的设备。这里 Eclipse 会询问您将应用部署到哪里。如果你只有一个设备插入,没有模拟器运行,这个屏幕将不会出现。 图 2–27。 如果有多个设备或仿真器,DDMS 会提示用户选择部署应用的位置。 探索 PhoneGap 功能 本节将探索 PhoneGap 的更多特性。 下面是 PhoneGap 支持的功能的简短总结: PhoneGap 的加速计 API 使应用能够感知设备方向的变化,因此,它能够相应地采取行动。这在创建具有气泡水平仪的应用时很有用(确保手机与地面水平对齐)。可以选择读取一次器件方向的变化读数,或者连续接收器件方向的变化。 PhoneGap 的相机 API 允许应用从相机中检索图片(这对脸书和 Picasa 应用非常有用),或者从现有的照片库中获取图像。 PhoneGap 的 compass API 帮助应用了解手机的方位。这被证明对于地图和导航应用是有用的,因为地图随着用户改变电话的方位而旋转,存在获取设备航向变化的一个读数或连续接收设备航向变化的选项。 PhoneGap 的联系人 API 是应用读写联系人的一种方式。许多社交应用可以从同步手机联系人和社交频道上的联系人中受益。 PhoneGap 的文件 API 允许应用读取、写入和列出目录和文件系统。如果应用计划更改手机文件系统中的文件内容,这将非常方便。这个 API 也可以帮助编写文件浏览器应用。 地理位置 API 有助于检索设备的地理位置。这对许多应用都有好处,包括基于地图的应用,以及像 foursquare 这样的应用,用户可以通过使用他们的 GPS 位置来签到。可以选择读取一次设备地理位置的变化,或者连续接收设备地理位置的变化。 媒体 API 允许应用控制设备上的媒体传感器和应用。这个 API 允许应用记录和回放音频和视频记录。 PhoneGap 的网络 API 为应用提供了查看网络状态的能力。这种状态不只是在线和离线,而是告诉应用设备是在 2G/3G/4G 网络上还是在 Wi-Fi 网络上。这些信息通常有助于应用决定何时检索某些类型的信息。 通知 API 允许应用通过发出哔哔声、振动或提供可视警报来通知用户发生了什么事情。 PhoneGap 的存储 API 为应用提供了一个内置的 SQL 数据库。应用可以通过 SQL 语句插入、检索、更新和删除数据。应用可以查询数据库中的数据,并在本地存储的电子邮件列表中搜索特定的电子邮件。 PhoneGap 教程 并非所有的 PhoneGap 教程都可以在 Android 模拟器上完成,因此我们将解释以下检查教程的方法: 可以在 Android 模拟器上完成的教程。 需要安卓手机才能工作的教程。 仿真器示例 获取设备信息 PhoneGap 允许以编程方式读取设备信息。为此,您需要确保 PhoneGap 框架已经加载。一旦加载了框架,就可以使用 JavaScript 提取设备信息。设备信息的所有属性在表 2–1 中列出。 下面的代码将让您访问设备的信息。同样参见图 2–28。 ` PhoneGap Device Info Device NamePhoneGap VersionMobile PlatformPlatform VersionUUID `  图 2–28。??【PhoneGap 设备信息】HTML 源代码 运行这段代码时,图 2–29 中的屏幕应该出现在您的 Android 模拟器上。 图 2–29。在模拟器上运行 PhoneGap 的设备信息 您可以从[bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-DeviceInfo](https://bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-DeviceInfo)下载这个例子的完整源代码。 可以参考[docs.phonegap.com/en/1.1.0/phonegap_device_device.md.html#Device](http://docs.phonegap.com/en/1.1.0/phonegap_device_device.md.html#Device)的设备 API 官方文档。 抓取设备的联系人 我们将使用 PhoneGap 来获取设备的地址簿联系号码。在我们在 Android 模拟器上做这些之前,我们需要用一些联系信息来设置 Android 模拟器。 Click on the dialer application icon seen in Figure 2–30. 图 2–30。 点击 Android 模拟器上的 PhoneGap 应用。 This will open up the dialer application. Click on the Contacts tab, seen in Figure 2–31. 图 2–31。 在手机应用中添加联系人 Click Menu and choose New Contact. In the new contact add the first name, last name, and phone number. Refer to Figures 2–32 and 2–33. 图 2–32。点击菜单中的和点击新增联系人 图 2–33。 添加联系人,点击完成。 输入所需的值后,点击完成,您应该会在联系人列表中看到一个联系人(如图 Figure 2–34 所示)。 图 2–34。 联系人列表 为了使用 PhoneGap 访问联系人列表,我们需要使用以下 API: navigator.service.contacts.find(contactFields, contactSuccess, contactError, contactfindOptions); Table 2–2 提供了每个参数的描述。 下面提供了生成获取联系人的完整代码的步骤: 创建 ContactFindOptions 对象。通过使 options.filter 等于"",我们说我们想要获取所有联系人。如果 options.filter 是 Bob,这意味着我们希望过滤我们的搜索,以便所有结果都必须在 contact 字段的某个位置包含关键字 Bob。var options = new ContactFindOptions(); options.filter=""; 我们需要定义想要获取的联系人字段。当我们搜索联系人时,会出现一个联系人列表。接触本身是接触字段的关联数组。这意味着,如果我们指定只获取姓名和电话号码联系人字段中的联系人,我们将只获取这些信息。var fields = [“name”,”phoneNumbers”]; 定义成功和失败的回叫方法。当我们调用方法 navigator . service . contacts . find()时,我们需要提供两个回调。这是因为 find()方法是一个异步方法。function onSuccess(contacts) { for(var index=0;index Use Android Linkify to allow us to dial numbers. While we list the contacts in the address book as a part of the HTML list (as seen in the following code), ` Rohit Ghatol we can make the listing more useful by using a link for the contact. This is depicted as follows: Rohit Ghatol ` 当用户点击链接 Rohit Ghatol 时,Android 会读取要成为 tel 的 URL,并打开拨号器拨打该号码。 这在图 2–36 和图 2–37 中有所描述,它们显示了应用在 Android 模拟器上的外观。 使用下面的代码来应用我们到目前为止所学的内容。参考图 2–35 获取 index.html 源代码。 ` PhoneGap Contacts `  图 2–35。 PhoneGap 联系人应用 HTML/JavaScript 源代码 图 2–36。 清单联系人 图 2–37。 点击联系人打开电话拨号器。 您可以从[bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-Contacts](https://bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-Contacts).下载这个例子的完整源代码 可以参考[docs.phonegap.com/en/1.1.0/phonegap_contacts_contacts.md.html#Contacts](http://docs.phonegap.com/en/1.1.0/phonegap_contacts_contacts.md.html#Contacts)的 Contacts API 官方文档。 获取 SD 卡列表 本节将解释如何列出 Android 设备的 SD 卡。本节结合使用了 W3C 标准和 PhoneGap API。 列出 Android 设备的 SD 卡有两个步骤。这些步骤如下: 我们解析目录file:///sdcard并获得对目录条目的访问权。 当我们访问 directoryentry 时,我们可以从 directoryentry 创建一个 directoryreader,并获取目录(SD 卡)的内容。 在步骤 1 中,我们调用以下函数: window.resolveLocalFileSystemURI("file:///sdcard", onResolveSuccess, onError); 为了响应前面的函数,onResolveSuccess 回调将被激活。onResolveSuccess 回调可以在下面的代码中看到。一旦我们获得了对 fileEntry 的访问权,我们就从它创建一个 directoryReader,并在这个 directoryReader 上调用 readEntries。 `function onResolveSuccess(fileEntry){ var directoryReader = fileEntry.createReader(); directoryReader.readEntries(onSuccess,onError); }` 当路径file:///sdcard被成功解析时,onSuccess 方法被调用。onSuccess 方法如下: function onSuccess(entries){ document.getElementById("loading").innerHTML=""; var ul = document.getElementById("file-listing"); for(var index=0;index 部署到模拟器 以下代码提供了如何部署到模拟器的完整示例: ` PhoneGap List SDCard Contents Loading .. ` 该代码如图 2–38 所示。 图 2–38。sd 卡上的清单文件 您可以从[bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-DirectoryListing](https://bitbucket.org/rohitghatol/apress-phonegap/src/67848b004644/android/PhoneGap-DirectoryListing)下载本章的完整源代码。 可以参考[docs.phonegap.com/en/1.1.0/phonegap_file_file.md.html#File](http://docs.phonegap.com/en/1.1.0/phonegap_file_file.md.html#File)的 File API 官方文档。 写入和读取文件 这一节将向您展示如何使用 PhoneGap APIs 来操作文件系统。 注意: PhoneGap 实际上正在实现和支持在[www.w3.org/TR/file-system-api/](http://www.w3.org/TR/file-system-api/)提到的 W3C 的文件系统规范。 让我们熟悉一下文件系统 API 中的一些关键概念。这些关键概念是: 本地文件系统 文件系统 文件入口 目录项 本地文件系统 LocalFileSystem 为我们提供了对本地文件系统及其文件和目录的访问。有两种类型的文件系统: 本地文件系统。PERSISTENT :在没有用户明确授权的情况下,除了响应删除 API 调用之外,存储在持久性文件系统中的数据不应被 UA 删除。 本地文件系统。临时:UA 可以自行删除临时文件系统中存储的数据,无需应用或用户干预。 localFileSystem 方法是从 window 对象中访问的。这是通过以下方式完成的: window . request file system()–用于获得对根文件系统的访问权限。 window . resolvelocalfilesystemuri()–用于直接访问 FileEntry 或 DirectoryEntry 对象,前提是 URI 可用于该目录或文件。 文件系统 文件系统代表文件系统。它有两个主要属性: 名称–在两个选项“永久”或“临时”之间选择。如果您希望文件即使在应用被终止时也能持久保存,请选择“持久保存”。 Root—文件系统的根目录(DirectoryEntry)。 您需要使用以下 API 来访问文件系统: void requestFileSystem ( short type, // LocalFileSystem.PERSISTENT or //LocalFileSystem.TEMPORARY long long size, //Size for TEMPORARY FS FileSystemCallback successCallback, //Success Callback optional ErrorCallback errorCallback); // Failure Callback 获得文件系统访问权限的代码片段如下: window.requestFileSystem(LocalFileSystem.PERSISTENT ,0 //size ,function(fileSystem){ // success callbac alert(“Got FileSystem “+fileSystem); }, function(err){ //failure callback alert(“Got Error requesting FileSystem”); } ); 您需要使用以下 API 来访问 fileEntry 或 directoryEntry 对象(代表文件或目录的对象): void resolveLocalFileSystemURL ( DOMString url, //url of file or directory on //filesystem EntryCallback successCallback, //Success Callback optional ErrorCallback errorCallback); //FailureCallback 档案输入 为了操作一个文件,你需要一个 fileEntry 对象。有许多方法可以获得 fileEntry,但是假设您知道文件的 URI,您可以如下获得该对象: window.resolveLocalFileSystemURL( “file:///sdcard/read-write.txt”, function(fileEntry){ }, function(err){ } ); 为了查找 fileEntry 的所有属性和方法,您需要访问 fileEntry 的附录。有两种方法可以获得这种访问权限: createWriter():创建可用于写入文件的 FileWriter 对象。 file():创建一个包含文件属性的 File 对象,包括读取其内容。 导演 为了列出目录中的文件,您需要一个 directoryEntry 对象。有许多方法可以获得 directoryEntry,但是假设您知道目录的 URI,您可以如下获得该对象: window.resolveLocalFileSystemURL( “file:///sdcard/mydir/”, function(directoryEntry){ }, function(err){ } ); 为了查找 directoryEntry 的所有属性和方法,您需要访问 directoryEntry 的附录。有一种方法可以获得这种访问:getFile():在给定目录中创建文件,或者从给定目录中获取文件。 程序布局 我们的文件读写程序很简单。它包含一个文本区域,我们可以在这里读取文件内容,也可以将文本区域的内容写入文件。我们使用两个按钮 Read 和 Write 来读/写一个名为 read-write.txt 的文件。 下面是程序的代码。 ` PhoneGap Read Write File /sdcard/read-write.txt Read Write ` 运行时的该代码在图 2–39 中说明。 图 2–39。 读写文件。 现在,让我们实现 readFile()方法来读取文件并在 TextArea 中显示其内容。步骤非常简单: 第一步:解析网址file:///sdcard/read-write.txt。 步骤 2: 如果解决了,使用 fileEntry.file()方法创建一个读取器。 步骤 3: 如果没有解决,向用户显示一条消息,告诉用户他需要先写文件,然后才能读取它..参见图 2–40。 `function readFile(){ window.resolveLocalFileSystemURI( //filename to be read filePath, //success callback function(fileEntry){ fileEntry.file( function(file){ var fileReader = new FileReader(); fileReader.onloadend = function(evt){ document.getElementById("textarea").value = evt.target.result; }; fileReader.readAsText(file); }, function(error){ alert("Got error while reading "+filePath); }) }, //error callback function(error){ alert(filename + " not present, please add content and click Save first"); } ); }` 图 2–40。 由于没有写入文件,无法读取。 让我们实现 writeFile()方法读取 TextArea 中的文本,并将其写入file:///sdcard/read-write.txt。 步骤 1: 访问文件系统根目录。 步骤 2: 从文件系统根目录 Entry 创建文件 read-write.txt,如果它还不存在的话。 第三步:创建 fileWriter,将 TextArea 的内容写入文件。这显示在以下代码中: `function saveFile() { window.requestFileSystem( LocalFileSystem.PERSISTENT, 0, //Success Callback function (fileSystem) { var sdcardEntry = fileSystem.root; sdcardEntry.getFile( filename, //Flag telling create file { create: true }, //Success callbacks function (fileEntry) { fileEntry.createWriter( function (fileWriter) { fileWriter.onwrite = function (evt) { alert("Write was successful!"); document.getElementById("textarea").value = ""; }; fileWriter.write(document.getElementById("textarea").value); }, //Error callback function (error) { alert("Failed to get a file writer for " + filename); }); }, //Error Callback function (error) { alert("Got error while reading " + filename + " " + error); }); }, function (error) { alert("Got Error while gaining access to file system"); }); }` 当用户在文本区域中键入文本并点击 Write 时,内容被写入文件并显示一条警告消息,提示 Write 成功。你会注意到当你点击 Write 时,程序会清空文本区。参见图 2–41 查看文件写入成功时的信息。 图 2–41。 写成功了 现在,点击 read 按钮,尝试读取您写入文件的内容。你写的内容应该出现在文本区。参考图 2–42 查看当读取成功时,文本区域是如何填充的。 图 2–42。 阅读成功 您可以从[bitbucket.org/rohitghatol/apress-phonegap/src/62c45e339662/android/PhoneGap-FileReadWrite](https://bitbucket.org/rohitghatol/apress-phonegap/src/62c45e339662/android/PhoneGap-FileReadWrite)下载这个例子的完整源代码。 可以参考[docs.phonegap.com/en/1.1.0/phonegap_file_file.md.html#File](http://docs.phonegap.com/en/1.1.0/phonegap_file_file.md.html#File)的 File API 官方文档。 写入和读取数据库 本节将解释如何读取、存储和操作数据库。我们将使用在数据库中存储联系人列表(名字和姓氏)的例子,然后读取它,并删除条目。 有三个表:一个用于标题列,一个用于内容,还有一个允许用户向联系人列表添加条目。 以下是从数据库中读取和写入的 index.html 代码: ` PhoneGap DB Read Write DB First Name Last Name Action Add ` 如果运行该程序,您应该会看到类似于图 2–43 所示的布局 图 2–43。 读写数据库 现在,让我们添加一些代码来读取、写入和删除数据库中的联系人条目。第一步是访问数据库对象。这是按如下方式完成的: `var firstNameBox = null; var lastNameBox = null; var db = null; var dataTable = null; /** Called when phonegap javascript is loaded */ function onDeviceReady(){ var addButton = document.getElementById("add"); firstNameBox = document.getElementById("firstName"); lastNameBox = document.getElementById("lastName"); dataTable = document.getElementById("data-table"); db = window.openDatabase("contactDB", "1.0", "Contact ** Database", 1000000);** //name,version,display name, size }` 让我们把重点放在创建数据库对象的 API 上。这是按如下方式完成的: window.openDatabase( databaseName, versionNumber, displayName, sizeInBytes); 现在让我们看一下代码(参考下面的 addButton.addEventListener ),它解释了单击 Add 按钮并向数据库中的 contacts 表添加条目的过程。 为了向 contacts 表添加条目,我们将在数据库对象上使用 transaction()方法。下面是这个方法的 API: db.transaction( function(tx){ //Function to execute the sql statements //Use tx to execute sql statements }, function(err){ // Error callback //Use err.code and err.message to understand the error }, function(){ //Success callback // Update the UI, log a message } ); 我们希望在用户点击按钮时添加新条目。因此,我们的添加功能位于添加按钮的 click 事件侦听器中。这可以在下面的代码中看到: `addButton.addEventListener( "click", function(){ db.transaction( //function sql statements function (tx){ ensureTableExists(tx); var firstName = firstNameBox.value; var lastName = lastNameBox.value; var sql = 'INSERT INTO Contacts ( firstName, lastName ) VALUES ("' + firstName + '","' + lastName + '")'; tx.executeSql(sql); }, //error callback function (err){ alert("error callback "+err.code); }, //success callback function (){ loadFromDB(); } ); },false); function ensureTableExists(tx){ tx.executeSql('CREATE TABLE IF NOT EXISTS Contacts (id INTEGER PRIMARY KEY, firstName,lastName)'); }` 我们使用一个名为 ensureTableExists(tx)的方法,它确保我们在数据库中执行 DB CRUD 操作之前拥有数据库表。 我们在数据库事务的 SQL 函数中使用 SQL insert 语句,以便在数据库中创建一个条目。 注意:默认情况下,SQLite 中的主键是自动递增的,因此,我们只写名字和姓氏,数据库实际上是递增 ID。 一旦数据库成功添加了操作,我们就调用 loadFromDB()方法从数据库表中填充 HTML 表。 请参考 Figure 2–44 查看添加联系人功能的 UI 屏幕。 图 2–44。 添加条目 现在,让我们来看看 loadFromDB()方法。这里我们使用相同的 tx.executeSql,但是在这种情况下,我们期望得到一些不同的结果,所以我们使用下面版本的 tx.executeSql: tx.executeSql( sqlStatement, options, successCallbackWithResultSet, errorCallback); successCallbackWithResultSet 是一个接收两个内容的函数: 税 结果集 `function loadFromDB(){ db.transaction( //function sql statements function (tx){ ensureTableExists(tx); tx.executeSql('SELECT * FROM Contacts', [], //success callback function(tx, results){ var htmlStr=""; for(var index=0;index var item = results.rows.item(index); htmlStr = htmlStr +""+ item.firstName+"" +item.lastName +" jQuery HTML 操作的完整列表可以在[www.w3schools.com/jquery/jquery_ref_html.asp](http://www.w3schools.com/jquery/jquery_ref_html.asp)找到。 jQuery Ajax 调用 jQuery 为 Ajax 调用提供了许多有用的方法。 下面是一个对 URL 进行 Ajax GET 调用的例子。这是“少写多做”的经典例子。以下代码执行 Ajax GET 调用 service/employee/details.txt,并将内容放入 id 为“details”的 div 中: $.get("service/employee/details.txt", function (result) { $("div#details").html(result); }); 以下是对 URL 进行 Ajax POST 调用的示例,发布数据{name:employeeName}: $.post("service/employee/details", { name: employeeName }, function (result) { alert("Post successful"); }); jQuery HTML 操作的完整列表可以在 [www.w3schools.com/jquery/jquery_ref_ajax.asp](http://www.w3schools.com/jquery/jquery_ref_ajax.asp)找到。 熟悉 jQueryMobile jQueryMobile 通过提供一个通用的 UI 平台来开发跨许多流行的移动平台的移动应用,将 jQuery“少写多做”的概念推向了一个新的高度。 jQueryMobile 建立在非常流行和健壮的 jQuery 和 jQuery UI 框架之上。jQueryMobile 提供了现成的、可触摸的移动小部件,比如列表视图、带有后退按钮的标题、导航动画等等。这些小部件具有专业而精致的外观和感觉,使得开发现成的应用变得更加容易。 jQueryMobile 的主页是[jquerymobile.com/](http://jquerymobile.com/)。 而且,jQueryMobile 提供了五种开箱即用的主题供你选择。下面的示例展示了按钮在不同主题中的外观。总的来说,我们有五个主题——主题 a、主题 b、主题 c、主题 d 和主题 d——如图图 4–1 所示。 图 4–1。 jQueryMobile 主题 此外,jQueryMobile 还为表 4–1 中列出的平台提供坡度支持。 在移动应用中包含 jQueryMobile 从[jquerymobile.com/download/](http://jquerymobile.com/download/)下载 jquery.mobile-1.0rc2.zip 并解压。解压缩后,您会看到如图图 4–2 所示的文件夹结构。它包含两对 jQueryMobile JavaScript 和一个 CSS 文件。顾名思义,您可以使用。最小化生产中的 JavaScript 和 CSS 文件,因为它们是缩小的 JavaScript 和 CSS 文件。 除此之外,你还需要在手机应用中包含图片文件夹。 图 4–2。 jQueryMobile 文件夹结构 以下是 jQueryMobile 示例的 HTML 模板: ` jQuery Mobile Demo … ` jQueryMobile 声明式用户界面 声明式 UI 构建是 jQueryMobile 最好的部分。您不需要编写复杂的 JavaScript 代码来构建 UI。UI 构建就像添加带有一些 jQueryMobile 特定属性及其值的普通 HTML 元素一样。 页面和对话框 您在上一节中看到了 HTML 模板。现在,您将向其中添加 jQueryMobile 布局和小部件。 您可以在 body 标记内的 div 元素中使用数据角色属性来声明页面。因此,在 body 标记中,您可以通过声明以下内容来声明许多页面: 同样,您可以通过将数据角色声明为“页眉”、“内容”和“页脚”来声明页面的组件以下是 jQueryMobile 中的一个页面示例: ` ` 此处显示了一个完整的页面示例。 ` Page Title Page content goes here. Page Footer ` 在浏览器中运行该 html 时,会显示一个如图 4–3 所示的屏幕。 图 4–3。 jQueryMobile pages 现在,您已经了解了 jQueryMobile 中页面的概念,让我们来看一个拥有多个页面或对话框的场景。 典型的应用有多个页面和对话框。jQueryMobile 最棒的一点是,您可以在同一个 HTML 页面中定义所有这些不同的页面和对话框。 下面是怎么做的。在一个 HTML 页面中定义多个 div,并赋予它们以下内容: 一个名为 data-role 的属性设置为 page。这看起来像这样:data-role="page " 一个名为“id”的属性,用于在代码中标识它们 您可以使用链接和按钮导航到这些页面和对话框。最简单的方法是执行以下操作: 将 href 定义为#+ <> 给该链接一个 data-role="button " 注意,页面和对话框的声明是相同的。事实上,没有什么叫做对话框,但是你可以在弹出窗口中加载一个页面作为对话框。 下面是一个页面链接的示例。当单击此链接时,会转换到 id 为“page2”的页面。还要注意,因为链接被赋予了 data-role="button ",所以它看起来像一个按钮。 将页面作为对话框打开与导航到页面非常相似。您只需要向链接添加两个属性: data-rel="dialog " data-transition="pop "(这是动画效果) 这里有一个完整的例子供你尝试。图 4–4 显示的是“主”页面,图 4–5 显示的是“第二页”页面,图 4–6 显示的是“对话 1”页面,相当于一个对话框: ` jQuery Mobile Demo Main Page Page Nav and Dialog Example Page Navigation Open Dialog Main Page Footer Second Page Second Page Click back to go back to main page Dialog Title v Dialog body Click close button to go back to main page `  图 4–4。jquerymobile page navigation 图 4–5。jquerymobile page navigation 图 4–6。 jQueryMobile 对话框 工具栏和按钮 在 jQueryMobile 中,有两种类型的工具栏: 标题栏 页脚栏 一般来说,创建工具栏就像在标题栏或页脚栏中声明一些按钮一样简单。这在图 4–7 中进行了描述。 ` jQuery Mobile Demo Cancel Edit Contact Save Header Footer Toolbar Example Remove Add Up Down `  图 4–7。 jQueryMobile 工具栏和按钮 表格元素 jQueryMobile 中的表单元素是典型的 HTML 表单元素——它们只是看起来不同。这意味着您可以使用您的 HTML JavaScript 技能来呈现好看、精美的 jQueryMobile 小部件,并使用传统的事件处理技术来快速编写您的移动 web 应用。 让我们看几个表单元素的例子。在第一个例子中,我们使用了一个输入文本、一个文本区域和一个搜索框。对于所有这些,都分配了一个标签。它们被包装在一个字段集中,形成一组标签和相关的小部件。请参见 Figure 4–8 以了解表单元素在 jQueryMobile 中的外观。 ` jQuery Mobile Demo Cancel Edit Contact Save Simple Form Elements Text Input: Textarea: Search Input: Remove Add Up Down `  图 4–8。 jQueryMobile 表单元素 在第二个例子中,HTML select 被包装在一个好看的开/关开关中。请注意,当您以编程方式从中获取值时,您将把它用作 HTML 选择框。您还用滑块包装了一个文本框。滑块的值放在文本框中。这相当于用户在文本框中填写一个数字,但是使用 jQueryMobile,用户可以使用滑块在给定的范围内选择一个值。参见 Figure 4–9 来看看这个 HTML 是如何呈现的。 ` jQuery Mobile Demo Cancel Edit Contact Save Simple Form Elements On/Off Switch: Off On Range Slider: Remove Add Up Down `  图 4–9。 jQueryMobile 表单元素 在下面的例子中,你可以看到将 HTML 单选按钮和复选框包装成好看的小部件是多么容易。这是通过使用数据角色“控制组”和数据类型“水平”来完成的请参见图 4–10 了解单选和多选表单元素的外观: ` jQuery Mobile Demo Cancel Edit Contact Save Single and MultiSelect Form Elements Choose a base: Thin Crust Double Cheese Burst Class Hand Tossed Choose Pizza toppings Jalepeno Olives Cheese Capsicum Non Veg topping: Pepperoni Ham Turkey Payment Type: Cash Coupons Credit Card Remove Add Up Down `  图 4–10。 jQueryMobile 表单元素 列表视图 到目前为止,您已经看到了用带有数据角色和 CSS 类的简单 HTML 元素来声明各种 UI 小部件是多么容易。在 jQueryMobile 中,列表视图也不例外。下面的例子将向你展示如何将一个 HTML 列表转换成一个移动可滚动列表。 ` USA UK Russia ` 下面是如何在 HTML 中声明列表的完整代码示例。对于动态数据,您所要做的就是在运行时将 li 元素追加到 ul 元素中。请参考 Figure 4–11 查看 jQueryMobile 中的列表视图。 ` jQuery Mobile Demo Header USA UK Russia Footer `  图 4–11。 jQueryMobile 列表视图 您可以在 jQueryMobile 网站上了解更多相关信息。点击此链接查看演示和文档:jquerymobile.com/demos/1.0a4.1/。 jQueryMobile 事件处理 在 jQueryMobile 中,事件处理可以分为两个方面: 非 jQueryMobile 小部件生成的事件。例如文本框、文本区域、按钮、单选按钮等等。 jQueryMobile 小部件和框架生成的事件。这些事件的例子是触摸事件、方向改变事件、滚动事件和页面生命周期事件。 正常事件 普通事件应该像 jQuery 通常做的那样处理。在 jQuery 中,jQuery 选择器提供了一个通用方法 bind,它允许我们绑定到任何事件。 ` … mybutton $("#mybutton").bind("click",function(event){ alert("clicked mybutton"); }); jQuery also provides many convenience method for events like a short hand of above method is click method, which binds the callback to click event. $("#mybutton").click(function(event){ alert("clicked mybutton"); });` 您可以在以下网站上阅读有关 jQuery 事件的更多信息: api.jquery.com/category/events/ 现在,转到 jQueryMobile 生成的事件。请注意,所有事件,无论其来源如何,都需要以上述方式处理。这同样适用于下面记录的事件。 下一节将讨论由 jQueryMobile 框架和小部件生成的各种事件。 触摸事件 手机或平板电脑上的触摸事件与点击或双击等传统鼠标事件有很大不同。以类似的方式,在传统的鼠标事件中,手势是不可能的。jQueryMobile 提供了一组用于触摸手势的新事件。这些事件在表 4–2 中描述。 以下是 jQueryMobile 如何处理触摸事件的示例。参见图 4–12 中的示例。 ` jQuery Mobile Touch Events Demo Touch Events Touch Events example Tap here Tap and hold here Swipe in this area. Swipe Left <-- in this area. Swipe Right -- > in this area. Footer `  图 4–12。 jQueryMobile 触摸事件。 方位变化事件 移动设备和平板设备都可以检测方位变化并做出反应。这非常有用,因为在纵向模式和横向模式下,移动设备或平板电脑的长宽比是不同的。jQueryMobile 允许开发人员使用这种方向更改来在两种模式下充分利用屏幕空间。为此,您需要侦听窗口元素上的“orientationchange”事件。下面的示例显示了这一点。参见图 4–13 和 4–14。 ` jQuery Mobile Touch Events Demo \((document).ready(function(){ \)(window).bind('orientationchange', function(event){ $("#placeholder").html("Orientation changed to "+event.orientation); }); }); Touch Events Orientation Events example Footer `  图 4–13。 jQueryMobile 方向改变事件 图 4–14。 jQueryMobile 定向变更事件 滚动事件 移动设备的一个重要方面是滚动和滚动时在后台做事情的能力。想想惰性加载列表,它在用户滚动列表时获取数据。 为此,您需要滚动事件(参见 Table 4–3)。jQueryMobile 提供滚动事件。请注意,当 scrollstart 事件在 iOS 上不按预期工作时,我们建议不要依赖 iOS 上的 scrollstart 事件。 页面事件 jQueryMobile 有页面的概念。jQueryMobile 中的页面被创建、显示和/或隐藏。jQueryMobile 提供了事件,这样开发人员可以在页面创建之前、创建之后以及页面显示和隐藏之前和之后进行适当的处理。所有这些事件都记录在表 4–4 中。 PhoneGap jQueryMobile 集成 既然您已经了解了 jQueryMobile 的工作原理,那么让我们来集成 PhoneGap 和 jQueryMobile 的特性来创建应用。 请注意,当您将 jQueryMobile 与 PhoneGap 一起使用时,有三个 JavaScript 框架,每个框架都有自己的引导。 PhoneGap 框架 jQuery 框架 jQueryMobile 框架 虽然所有框架都提供了自己的引导机制,但最好按照以下顺序引导这些框架: 语音间隙 框架 jQueryMobile(如果真的需要的话)。 这显示在以下示例中: `` 使用 jQueryMobile 和 PhoneGap 进行本地搜索 让我们来测试一下 jQueryMobile 和 PhoneGap。您将构建 PhoneGap geo、compass 和数据库特性的混搭,并结合使用 jQueryMobile 构建的 UI 和 Google Maps Places API。参见图 4–15。 这种混搭被称为本地搜索。这个混搭具有以下特性: 允许用户在他/她的当前位置的给定半径内搜索感兴趣的地方。 允许用户查看该地点的详细信息并访问该地点的网站。 允许用户将地点保存为收藏夹,并将其从收藏夹中删除。 允许用户浏览他保存的收藏夹。 允许用户在谷歌地图上查看所有的搜索结果。 图 4–15。使用 jQueryMobile 和 PhoneGap 的本地搜索 该屏幕中最重要的两个特征如下(参见图 4–16): 搜索按钮用于搜索用户位置 5 公里半径内的比萨饼 收藏夹按钮向用户显示所有标记为收藏夹的地方 图 4–16。使用 jQueryMobile 和 PhoneGap 的本地搜索 搜索结果可以在地图上显示为列表或标记。Figure 4–17 显示了结果如何在中显示为列表。 图 4–17。本地搜索结果 当用户单击其中一个搜索结果时,他会被带到企业详细信息页面。该页面显示了详细信息,如名称、地址和电话号码,以及企业附近。它还允许用户将业务条目添加到他/她的收藏夹中,或者从收藏夹中删除它。这显示在图 4–18 中。 图 4–18。本地搜索业务明细 当用户将企业添加到他的收藏夹时,他可以从主页导航到收藏夹页面。在这里,用户将看到保存为收藏夹的地点/企业。这些条目实际上存储在应用的内部数据库中(由 PhoneGap 提供)(参见图 4–19)。 图 4–19。本地存储的收藏夹。 同样,当用户点击其中一个条目时,他会被带到详细信息页面。如果您能观察到,我们现在可以看到“移至收藏夹”按钮,因为该企业/地点已经是收藏夹的一部分。参见图 4–20。 图 4–20。最喜欢的细节。 最后,但并非最不重要的是,整个搜索结果绘制在谷歌地图上。为此,您需要进入主页,点击搜索,然后点击地图选项卡。您将看到如图图 4–21 所示的屏幕。 图 4–21。地图上的本地搜索结果 引导 PhoneGap 和 jQuery 引导按以下顺序完成: 当调用 PhoneGap JavaScript 库时,PhoneGap 被引导来调用 onDeviceReady()函数 在 onDeviceReady 中,jQuery 被引导,以便在加载 jQuery 时调用匿名函数 安装必要的 JavaScript 库 对于这个项目,您将需要以下 JavaScript 库 jQuery: [docs.jquery.com/Downloading_jQuery#Download_jQuery](http://docs.jquery.com/downloading_jquery#download_jquery) jQueryMobile: [jquerymobile.com/download/](http://jquerymobile.com/download/) jQuery ui 映射:??] 语音间隙:[www.phonegap.com/download/](http://www.phonegap.com/download/) 假设您的应用 JavaScript 名为 app.js,应用 CSS 名为 app.css,您的 www 文件夹应该如图 Figure 4–22 所示。注意,images 文件夹属于 jQueryMobile 库。 图 4–22。本地搜索项目结构 本地搜索的布局 本地搜索页面是应用中的主页面。进行本地搜索需要三个输入。 PhoneGap 的地理位置 从搜索文本框中搜索关键字 jQueryMobile 滑块的搜索半径 一旦完成,它将获取搜索结果并显示在搜索结果页面中。 ` Local Search Local Search Search Range(kms): Search Favorites About us ` 寻找当地企业 为了搜索感兴趣的地方,我们使用谷歌地图的位置 API。可以通过对 Google Maps Places 服务端点进行 restful 调用来搜索感兴趣的地方。进行这个 restful 调用需要很多参数;这些显示在表 4–5 中。 此处显示的 URL 带有每个参数的填充符: https://maps.googleapis.com/maps/api/place/search/json?location={latitude,longi tude}&radius={radius}&types=food&name={search_keyword} &sensor=false&key={api_key}. 对于以下 URL,会出现 JSON 响应: https://maps.googleapis.com/maps/api/place/search/json?location=- 33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=true&key=< JSON 的回应如下: { "html_attributions": ["Listings by \u003ca href=\"http://www.yellowpages.com.au/\"\u003eYellow Pages\u003c/a\u003e"], "results": [{ "geometry": { "location": { "lat": -33.8719640, "lng": 151.1985440 } }, "icon": "http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png", "id": "aefbc59325ffd5f3e93d67932375d20d143289de", "name": "Toros Restaurant Darling Harbour", "reference": "CoQBdgAAAE6oRybc13OZYNH0WeuwKzTfzjYXO8nuWyGqCqSTBogR_BZxE30fgXsybOl_wIR0s_uuHLZqq- 17DTgpGHZoSehSbOG73dfIxO3rpQak2OmNuBb5Kg63rPN_afbH_PnbILiofw6WSODYOCkqhFl38qSXyujAPkQKZU 76NJypgT6mEhCg1MhyNAuyark4X8YfRg4YGhTn_MXr0gelHUHPe3JMCic-cHlu3A", "types": ["restaurant", "food", "establishment"], "vicinity": "Darling Dr, Sydney" }, …] } 注意,在前面的 JSON 中,有一个 id 和引用。您需要更好地理解这些,以便能够构建您的应用。 Id 是一个地方的唯一标识符。当您在数据库中存储地点/企业时,您将使用 id 作为主键。但是,id 不能用于获取最新信息。 Reference 是一个键,用于从 Google Places 服务器获取一个地点/企业的详细信息。但是,请注意,引用在多个搜索结果中不是唯一的。 因此,您将在数据库中存储 id(作为主键)和 reference(作为字符串),这样您就可以唯一地标识一个地点/企业(使用 id ),并随时使用 reference 从 Google Places 获取信息。 HTML 中的整体布局 下面是应用的总体布局。在应用的所有五个页面中: 搜索页面 id 为“列表”的搜索结果页面 id 为“详细信息”的详细信息页面 id 为“收藏”的收藏列表页面 id 为“Map”的地图页面 ` PhoneGap Local Search Local Search Search Range(kms): Search Favorites About us Result List Maps Map List Maps Favorites Business Details Business Details Remove to Favorite Add to Favorite Visit HomePage Name … Address … Phone … Rating … ` 获取并显示搜索结果 函数启动的搜索将搜索按钮事件与实际执行搜索的函数绑定在一起。 以下是搜索的事件流程: 向用户显示加载图标,让他/她知道正在进行长时间操作。这是通过调用$ .mobile.showPageLoadingMsg()来实现的;。 使用 PhoneGap 函数 navigator . geolocation . getcurrentposition(success callback,failureCallback)获取用户的当前位置。 在上述调用的 successCallback 中,使用以下参数完成了对 Google Places 的 JSON 请求: 地理定位 搜索关键字 地理位置的搜索半径 Google Places 的开发者 Api 密钥 var jQuery 的\(。getJSON()用于对 Google Places 进行 Ajax 调用,以获取 JSON 响应。请注意,由于 PhoneGap 应用没有域名,因此您不会受到浏览器单一来源政策的限制。用\)注册 successCallback 和 failureCallback。getJSON()函数。 在上述调用的 successCallback 中,获取位置响应并将其附加到 id 为“result-list”的 ul 元素中。这个 ul 元素在 HTML 代码中被注释为 jQueryMobile 列表视图。一旦您将必要的 li 元素添加到 ul 元素中,我们将调用$(“结果列表”)。listView(“refresh”)将 ul 元素重绘为 jQueryMobile 列表。 注意,您将每个地方的 JSON 响应的引用部分作为链接的 id(一个元素)。这样做是为了当用户点击这个条目时,他会被带到详细信息页面。注意,这个链接的 href 部分实际上是“#details” 最后,您将一个 click 处理程序与 place 上的 click 事件绑定在一起,这样您就可以实际调用 Google Places 服务器,在将用户导航到详细信息页面之前获取企业/地点条目的详细信息。 最后一步是通过调用$.mobile.hidePageLoadingMsg()移除加载图标;。 `/** * Binding Search button handler to go and fetch place results */ function initiateSearch(){ \(("#search").click(**function**(){ **try** { \).mobile.showPageLoadingMsg(); navigator.geolocation.getCurrentPosition(function(position){ var radius = $("#range").val() * 1000; mapdata = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); var url = "https://maps.googleapis.com/maps/api/place/search/json?location=" + position.coords.latitude + "," + position.coords.longitude + "&radius=" + radius + "&name=" + \(("#searchbox").val() + "&sensor=false&key=AIzaSyC4vCfT_Knq1SGuNMahZqyrmZFiTuBsdlY"; \).getJSON(url, function(data){ cachedData = data; \(("#result-list").html(""); **try** { \)(data.results).each(function(index, entry){
class="ui-bar-a
ui-footer ui-footer-fixed fade ui-fixed-overlay" role="contentinfo" style="top: -
1263px; ">