在本文中,将探讨如何利用Windows Live SearchAPI开发一个可以在Windows Mobile通信设备上使用的定位电话簿应用。这个项目的核心是利用电话搜索功能,创建一个基于位置的电话簿。
为了充分利用这个程序,需要两个硬件组件:一个运行至少Windows Mobile2003操作系统的Windows Mobile设备和一个GPS接收器。虽然Windows Mobile 5设备也可以使用,但可能会收到关于代码未签名的警告。此外,可以使用Visual Studio .NET中包含的Windows Mobile模拟器,但需要记住将虚拟端口映射到主机机器上的GPS端口,并确保它可以连接到互联网。GPS接收器可以是内置的或外置的,只需要映射到一个COM端口。Windows Mobile设备必须能够通过WiFi或通过电话服务提供商的数据订阅访问互联网。
如果没有GPS接收器,程序仍然可以工作,但需要选择一个城市作为所有搜索的参考点。
使用Visual Studio .NET 2005来开发这个项目。虽然过去10年的首选开发语言是C语言,但本文附带的示例是用VB.NET编写的。Windows Mobile设备还需要安装2.0 Compact Framework。如果这个框架不存在,Visual Studio将在部署时安装它。如果GPS接收器映射到COM9以上的端口,那么2.0 Framework with SP2将是更好的选择。
要开发针对Microsoft Live Search web服务的项目,需要为项目请求一个应用程序ID。获取它既快速又简单,而且是免费的。只需访问来请求一个ID。
对于这个项目,首先创建了一个新的“Smart Device”项目,目标是“Pocket PC 2003”设备。这将是一个“Device Application”项目。由于这个项目依赖于Microsoft Live Search web服务,下一步是添加对该web服务的引用。一旦添加了web服务,执行搜索就只是构建一个搜索请求对象并提交它的问题。
Live SearchAPI允许在单个请求中搜索多个数据源。每个数据源将由一个“SourceRequest”对象描述。虽然一个搜索请求可以包含几个“SourceRequest”对象,但只搜索电话号码,所以搜索总是有一个单一的“SourceRequest”对象。
Dim searchRequest As SearchRequest = New SearchRequest
Dim sourceRequest() As SourceRequest = {New SourceRequest()}
searchRequest.Requests = sourceRequest
必须为搜索设置一些通用设置。这包括应用程序ID、搜索的语言/文化、想要返回的结果数量、搜索类型,以及希望在搜索结果中填充的字段。
searchRequest.AppID = "__YOUR_APP_ID_GOES_HERE__"
searchRequest.CultureInfo = "en-US"
sourceRequest(0).Count = 50
sourceRequest(0).Source = SourceType.PhoneBook
sourceRequest(0).SortBy = SortByType.Distance
sourceRequest(0).ResultFields = ResultFieldMask.Phone Or _
ResultFieldMask.Address Or ResultFieldMask.Location Or ResultFieldMask.Title
当然,需要在这段代码中放置自己的应用程序ID。剩下的就是指定正在搜索的内容以及希望搜索的地点周围的位置:
searchRequest.Location = currentLocation
searchRequest.Query = txtName.Text
这里的“currentLocation”对象包含一个位置(纬度、经度和半径)。稍后将对此字段进行评论。“txtName.Text”是对用户输入他们正在搜索的内容的文本字段的引用。
提交搜索很简单。创建一个对MSNSearchService对象的引用,调用它的search方法与搜索请求,并保存响应。单个搜索结果位于名为Responses的集合中。这个集合中的对象的字段是自解释的(电话、地址等)。
Dim searchService As MSNSearchService = New MSNSearchService()
Dim searchResponse As SearchResponse
searchResponse = searchService.Search(searchRequest)
NMEA GPS设备传统上使用RS232接口(串行端口)进行通信。因此,将通过使用SerialPort对象来读取GPS设备。这类设备输出了很多有趣的数据,包括UTC时间、速度等。只需要知道位置。实现了一个极简的GPS读取类。它读取GPS接收器输出的每一行,寻找包含经度和纬度的消息,并使用以下正则表达式提取信息:
Dim gpsExpression As Regex = New Regex( _
"\$GPRMC,\d*(\.\d*)?,\w,(?\d+)_" + _
"(?(\d{2}\.\d+)?),(?N|S)," + _
"(?\d+)(?(\d{2}\.\d*)?),_" + _
"(?E|W)")
这个类有自己的线程。一旦实例化,它就开始不断地从GPS接收器读取当前位置,并通过一个事件传递新的坐标。对这个对象要特别小心。由于它有自己的线程,它可以防止程序从内存中卸载,如果主窗体关闭但这个线程没有停止。调用对象的Dispose方法将导致线程被中止。
搜索结果包含结果的地理坐标,但不包含到结果的距离。距离是在表单代码中计算的。这个方程基本上是计算一个球体上大圆弧的长度。该函数将计算以公里或英里为单位的距离(尽管函数调用只请求英里)。如果想使用其他单位的距离,只需要知道地球在那个单位中的半径,并将该值设置为“earthRadius”变量。
简化了这个程序以便于本文的编写,但已经开始了下一组功能,希望它能够拥有。这里实现的GPS读取类将不复存在,将被一个插件系统取代,允许使用不同类型的定位服务(例如辅助GPS)或来自其他服务的位置信息。希望用户的搜索查询能够被保存,以便频繁的搜索可以从下拉列表中选择。最终,希望能够将结果显示在地图上,并可能提供驾驶方向。虽然这可能最终成为另一个项目的一部分,但也希望运行这个程序的同事能够使用它来找到彼此。