使用 HTML 5 创建移动 Web 应用程序,第 1 部分: 联合使用 HTML 5、地理定位 API 和 Web 服务来创建移动混搭程序

查找并跟踪位置坐标以用在各种 Web 服务中

在这个由五个部分所组成的系列的第一部分中,您将接触到移动 Web 应用程序中最流行的新技术:地理定位。高端智能手机都内置 GPS,现在您将了解 Web 服务如何使用它。在本文中,您将学到如何使用各种地理定位标准,以及如何使用流行的 Web 服务来创建有趣的移动混搭程序。

Michael Galpin, 软件架构师, eBay

/developerworks/i/p-mgalpin.jpgMichael Galpin 是 eBay 的一名架构师。他经常为 developerWorks 撰写文章,同时在 TheServerSide.com 和 Java Developer 期刊上发表文章,他还有自己的 博客。他从 1998 年开始做职业程序员,并拥有加州理工学院数学专业的学士学位。



2010 年 6 月 07 日

关于本系列

常用缩略语

  • API: 应用程序编程接口
  • CSS: 层叠样式表
  • GPS: 全球定位系统
  • HTML: 超文本标记语言
  • JSONP: 带填充的 JSON
  • SDK: 软件开发工具包
  • UI: 用户界面
  • W3C: 万维网联盟

HTML 5 是一项让人振奋的技术,这有着充分的理由。这将会是一次技术突破,因为它可以将桌面应用程序功能带入浏览器中。除了传统浏览器外,对于移动浏览器,其潜力甚至更大。不仅如此,最流行的移动浏览器甚至已经采用并实现了 HTML 5 规范中很多重要部分。在这个由五个部分组成的系列里,您将仔细了解 HTML 5 中的一些新技术,它们对移动 Web 应用程序开发具有重大影响。在本系列的每一部分中,您将动手开发一个展示 HTML 5 新特性的移动 Web 应用程序,这些特性可用于最新的移动 Web 浏览器上,如那些基于 iPhone 和 Android 的设备。


先决条件

本文中,您将使用最新的 Web 技术开发 Web 应用程序。这里大多数代码是 HTML、JavaScript 和 CSS — 所有 Web 开发的核心技术。您最需要的东西是用来测试的浏览器。对于本文,强烈建议您使用 Mozilla Firefox 3.5+,因为它是支持地理定位的桌面浏览器。当然,您还需要在移动浏览器上测试,还需要最新的 iPhone 和 Android SDK。在本文中使用的是 iPhone SDK 3.1.3 和 Android SDK 2.1。查看 参考资料 部分中的链接。


基础知识:了解一下

地理定位本身就是一项新技术。它能让您知道用户在哪。但是仅仅知道这点并报告给用户并不是十分有用。难道所有人都关心自己所在的确切经纬度?这时可以结合其他数据和服务,让这个位置信息变得有用,可以产生一些有趣的结果。这些服务都需要用户的经度和纬度作为输入。这就是所需要的,让我们看看是如何获得的。清单 1 显示的是这方面的标准 JavaScript API。

清单 1. 找到用户: getCurrentPosition
navigator.geolocation.getCurrentPosition(successCallback, 
errorCallback, options);

这是地理定位中重要的 API。对于一大类应用程序,只需用到这个 API。地理定位对象是标准导航器对象的一部分,它有几个方法,最常用的是 getCurrentPosition。访问用户位置是耗时的操作(就像在太空中找个卫星一样!),它还要取得用户的同意。因此这是一个异步操作。它的参数是回调函数:一个用于成功,一个用于失败。

成功函数将通过一个单独的 Position 类型的参数传递。这个对象有两个属性:一个时间戳的属性和称为坐标的 Coordinates 类型的属性。一个 Coordinates 对象有几个属性:

  • latitude
  • longitude
  • altitude
  • accuracy
  • altitudeAccuracy
  • heading
  • speed

这些参数不是在所有设备上都可用,除了 latitude、longitude 和 accuracy。如果支持地理定位 API,并且设备可以解析位置,就可以获取 latitude、longitude 和 accuracy。

失败 callback 函数将传递一个 PositionError 类型参数。PositionError 实例有两个参数:code 和 message。message 是设备特定的,可用于调试。code 有以下三个取值:

  • PERMISSION_DENIED (1)
  • POSITION_UNAVAILABLE (2)
  • TIMEOUT (3)

应用程序将根据 code 向用户友好显示失败消息。

请注意,W3C 规范还允许选择第三个参数。这包含花费多长时间取得用户位置的超时时间。尽管如此,像 iPhone 这样的设备目前还不支持,因此不建议使用。既然已经详细看过 API,看看实际如何使用的例子吧。

与 Twitter 集成

现在 hello world 混搭程序可通过某种方式使用 Twitter。在第一个例子中,将使用 Twitter 的搜索 API。它支持根据位置范围搜索微博。清单 2 显示的是本地 Twitter 搜索。

清单 2. 本地 Twitter 搜索
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width"/>
<title>Local Twitter Search</title>
<script type="text/javascript">
    function startSearch(){
        var gps = navigator.geolocation;
        if (gps){
            gps.getCurrentPosition(searchTwitter, 
                   function(error){
                alert("Got an error, code: " + error.code + " message: " 
+ error.message);
             });
        } else {
            searchTwitter();
        }
    }
    function searchTwitter(position){
        var query = "http://search.twitter.com/search.json?callback=showResults&q=";
        query += $("kwBox").value;
        if (position){
            var lat = position.coords.latitude;
            var long = position.coords.longitude;
            query += "&geocode=" + escape(lat + "," + long + ",50mi");
        }
        var script = document.createElement("script");
        script.src = query;
        document.getElementsByTagName("head")[0].appendChild(script);
    }
</script>
</head>
<body>
    <div id="main">
        <label for="kwBox">Search Twitter:</label>
        <input type="text" id="kwBox"/>
        <input type="button" value="Go!" onclick="startSearch()"/>
    </div>
    <div id="results">
    </div>
</body>
</html>

用户可以在文本框输入搜索条目。单击按钮调用 startSearch 函数。此处就使用地理定位 API。首先检查其是否可用。如果可用,就调用 getCurrentPosition API。如回调成功,就使用 searchTwitter 函数。如果 callback 函数失败,就传递一个显示失败信息的终止参数。

如果浏览器成功找到位置,就调用 searchTwitter 函数。这里使用传递给函数的位置来向 Twitter 搜索查询添加 geocode 参数。清单 2 搜索指定位置 50 英里内的帖子。为了调用 Twitter,要使用动态脚本标签,这是一项常称为 JSONP 的技术。Twitter 搜索 API 对此提供支持,它允许直接从浏览器调用 Twitter 搜索,不需要服务器。这由查询中的 callback 参数指出。请注意它设置成 showResults。这是所要调用的函数名称。在 清单 2 中未显示,因为这只是用来创建 UI,但在本文的源代码中已有包含(查看 下载)。 图 1 显示的是 清单 2 中代码的屏幕截图,这是在 iPhone 上运行的。

图 1. 从 iPhone 上搜索 Twitter
截屏显示iPhone 50 英里以内帖子的搜索结果

本应用程序和其他位置感知应用程序一样,只要一次获得位置。尽管如此,其他应用程序在用户移动时要保持追踪。这些应用程序需要使用其他更高级的地理定位 API。


更高级的内容:追踪

有时候应用程序不只需要知道用户的当前位置,还需要在用户每次改变位置时及时更新。有个用于此目的的 API,是 watchPosition。它与 getCurrentPosition 很相似,接收同样的参数。最大的不同是它返回 ID。这个 ID 可与最后的地理定位 API clearWatch 联合使用。该函数会用到从 watchPosition 获得的 ID。当您调用 watchPosition,浏览器将会一直向您传入的成功回调函数发送更新,直到调用 clearWatch。持续不断获取用户位置信息将会耗尽设备资源,所以请谨慎使用这些 API。现在看看例子。

与 Google 地图集成

本例中,您将使用 Google 地图 API。这些 API 已对使用移动设备进行了优化,尤其是对 iPhone 和 Android 平台。这使得它们对移动 Web 开发人员很有吸引力,尤其是位置感知应用程序。以下的应用程序示例将会在地图上显示用户位置,并且在每次用户改变位置时更新。清单 3 是映射代码。

清单 3. 使用 Geolocation 映射应用程序
<html> 
<head> 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
<title>I'm tracking you!</title> 
<script type="text/javascript" src="http://maps.google.com/maps/api/js?
     sensor=true"></script> 
<script type="text/javascript">
    var trackerId = 0;
    var geocoder;
    var theUser = {};
    var map = {};
    function initialize() {
        geocoder = new google.maps.Geocoder();
        if (navigator.geolocation){
            var gps = navigator.geolocation;
            gps.getCurrentPosition(function(pos){
                var latLng = new google.maps.LatLng(pos.coords.
latitude,pos.coords.longitude);
                var opts = {zoom:12, center:latLng, mapTypeId: 
google.maps.MapTypeId.ROADMAP};
                map = new google.maps.Map($("map_canvas"), opts);
                theUser = new google.maps.Marker({
                    position: latLng,
                    map: map,
                    title: "You!"
                });
                showLocation(pos);
            });
            trackerId = gps.watchPosition(function(pos){
                var latLng = new google.maps.LatLng(pos.coords.latitude,pos.
coords.longitude);
                map.setCenter(latLng);
                theUser.setPosition(latLng);
                showLocation(pos);
            });
        }
  }
</script> 
</head> 
<body style="margin:0px; padding:0px;" onload="initialize()"> 
    <div id="superbar">      
        <span class="msg">Current location: 
              <span id="location"></span>
          </span>
          <input type="button" value="Stop tracking me!" 
onclick="stopTracking()"/>
      </div>
  <div id="map_canvas" style="width:100%; height:90%; float:left; 
border: 1px solid black;">
  </div> 
</body> 
</html>

一旦文档主体加载,就调用 initialize 函数。该函数检查浏览器是否支持地理定位。如果支持,就调用 getCurrentPosition,与 清单 2 中的前个例子一样。当它获取位置,就使用 Google 地图 API 创建地图。请注意如何使用纬度和经度来创建 google.maps.LatLng 实例。该对象用于使地图居中。下一步,创建地图上的标记来表示用户当前位置。该标记再次用到从地理定位 API 接收到的纬度和经度。

创建地图并放置标记后,开始追踪用户。捕获从 watchPosition 中返回的 ID。无论何时接收到新的位置,都将地图在新位置重新居中,并将标记移到新位置。清单 4 显示了需要了解的另两个函数。

清单 4. 地理编码和取消追踪函数
function showLocation(pos){
    var latLng = new google.maps.LatLng(pos.coords.latitude,pos.coords.longitude);
    if (geocoder) {
        geocoder.geocode({'latLng': latLng}, function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            if (results[1]) {
                $("location").innerHTML = results[1].formatted_address;
            } 
          } 
        });
      }        
}
function stopTracking(){
    if (trackerId){
        navigator.geolocation.clearWatch(trackerId);
    }
}

清单 3 中,当地图初始绘制及接收到用户位置更新时,调用 showLocation 函数。该函数如 清单 4 所示。它使用的是 google.maps.Geocoder 实例(在 清单 3initialize 函数开始处创建)。这个 API 可执行地理编码或者接收地址将其转换为映射坐标(纬度和经度)。它还执行逆向地理编码 — 将映射坐标转换成实际位置。本例中,使用了地理定位 API 生成的坐标,并使用 Google 地图 API 对其逆向编码。结果显示在屏幕上。

清单 4 中最后一个函数是 stopTracking 函数,当用户单击 清单 3 的 HTML 生成的按钮时调用。此处当首次调用 watchPosition 函数时得到 trackerId。只要简单地将其传递给 clearWatch 函数,浏览器/设备就会停止获取用户位置并停止调用 JavaScript。图 2 显示的是正在使用的追踪应用程序的屏幕截图。

图 2. 追踪应用程序
屏幕截图显示的是追踪应用程序创建的地图和位置标记。

当然,要实际测试追踪,需要改变位置。可以使用 Google App Engine,因为它能将您的 Web 应用程序上传到公共可达位置。然后可以直接在连接良好的移动设备中测试。一旦完成,您可以乘坐公共交通工具,或者是让别人开车带您四处走走,看看您的 Web 应用程序对不断改变的位置做出的响应。


结束语

本文演示了如何在移动 Web 应用程序中使用地理定位 API。GPS 听上去很吸引人,但相当复杂。尽管如此,如您所见,地理定位的 W3C 标准提供了很简单的 API。它直接获取用户位置并随时间变化追踪位置。并由此将坐标传递给很多支持位置的 Web 服务,或者是您自己正在开发的位置感知服务。在本系列关于 HTML 5 和移动 Web 应用程序的第 2 部分中,您将看到如何利用本地存储提升移动 Web 应用程序性能。


下载

描述名字大小
文章源代码geo.zip3KB

参考资料

学习

  • Create Ajax applications for the mobile Web(Michael Galpin,developerWorks,2010 年 3 月):探索如何使用 Ajax,这是所有 Web 应用程序的重要部分。
  • HTML 5 中的新元素(Elliotte Rusty Harold,developerWorks,2007 年 8 月):HTML 5 不仅跟 JavaScript 有关。阅读关于 HTML 5 中新标记的内容。
  • Android 和 iPhone 浏览器之战,第 1 部分:WebKit 成援兵(Frank Ableson,developerWorks,2009 年 12 月):您是否喜欢使用 HTML 5 的移动 Web 应用程序方法,但还想您的应用程序进入 iPhone App Store 和 Android Market?在这个两部分文章系列的第 1 部分看看如何能两全其美。
  • Dive Into HTML 5:查阅本书,广泛了解 HTML 5 检测技术及 HTML 5 的其他很多特性。
  • Safari Reference Library:如果开发 iPhone 的 Web 应用程序,请将它放在手边。
  • W3C HTML 5 Specification(Working Draft,2010 年 3 月):参考 HTML 5 的权威来源。
  • 本文作者的更多文章(Michael Galpin,developerWorks,2006 年 4 月至今):阅读关于 XML、Eclipse、Apache Geronimo、Ajax、更多 Google API 及其他技术的文章。
  • My developerWorks:个性化您的 developerWorks 体验。
  • IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 和相关技术的开发人员。
  • XML 技术库:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书。
  • developerWorks 技术活动网络广播:随时关注这些活动中的技术。
  • developerWorks 播客:收听面向软件开发人员的有趣访谈和讨论。

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML, Open source
ArticleID=494535
ArticleTitle=使用 HTML 5 创建移动 Web 应用程序,第 1 部分: 联合使用 HTML 5、地理定位 API 和 Web 服务来创建移动混搭程序
publish-date=06072010