作为一名热衷于远程徒步的爱好者,每年最期待的活动之一就是在荷兰尼梅亨举行的“四日行军”。已经参加了五次,每次都非常有趣。对于留在后方的“支持者”来说,一个常见的问题是不知道参与者的位置。他们可能会一天打好几次电话询问:“在哪里?”和“还有多久到终点?”。幸运的是,拥有一部带有GPS和互联网连接的移动电话可以很容易地解决这个问题。
要实现这个功能,需要以下工具:
不会深入讨论PC端应用程序的细节,因为这并非本文的主题。只需知道该程序托管了一个WCF网络服务,能够接收一组坐标。这些坐标随后用于调用Google静态地图API,生成表示坐标位置的地图。
网络服务的端点是:
http://yourhost:xxx/services/positionservice
程序运行一次后,会创建一个名为AppConfig.xml
的配置文件。在该文件中,可以输入主机名、端口号和Google API密钥等详细信息。
移动应用程序只是一个EXE文件,可以通过ActiveSync的常规机制将其放置在移动设备上。没有安装程序,所以需要手动操作。安装在设备上后,运行程序一次。在放置EXE的文件夹中,现在会找到AppConfig.xml
,它包含了配置信息。
使用应用程序:
PositionTrackerPC
程序。确保配置文件中的配置正确无误。可能需要编辑防火墙设置以打开将使用的端口,并且可能需要编辑调制解调器的NAT规则以使其工作。无法帮助配置这些,因为每个调制解调器/防火墙都不同。所以现在PC上的位置跟踪器已经准备好运行了。在应用程序的第一个标签页上,可以输入运行位置跟踪PC应用程序的主机名,以及使用的端口号。同时,还需要在这里输入Google API密钥(它将在第二个标签页上使用)。如果已经准备好输入配置信息,请确保保存它,否则将不得不再次输入!在文本框中,可以输入一条备注,它也会在PC应用程序中显示。除此之外,还会显示一些有关GPS信息,包括卫星数量和当前位置。
按下底部的“发送”按钮将调用PC上的网络服务,然后,位置就会显示出来!
在应用程序的第二个标签页上,作为额外功能,还可以获得当前位置的地图。如果GPS不工作或不存在,将显示location
位置的地图...
移动应用程序并不复杂,它只是一个简单的表单,上面有一个标签控件,包含两个表单。有三个主要技术值得解释:
回想一下PC应用程序中的网络服务端点:
http://yourhost:xxx/services/positionservice
现在,假设它是:
http://acme.com:8080/services/positionservice
现在,出现了两个问题:Visual Studio没有提供创建对网络服务的引用的工具,.NET 3.5 CF没有ChannelFactory
类的实现。那么,该怎么做呢?
需要安装Power Toys for .NET Compact Framework 3.5
。这些工具包括一个名为netcfSvcUtil.exe
的命令行工具。这个工具允许为网络服务生成代理,在情况下,使用如下:
netcfSvcUtil.exe /language:cs http://acme.com:8080/services
这个命令将生成两个文件:PositionService.cs
和CFClientBase.cs
。这两个文件都应该添加到项目中。在PositionService.cs
中,必须为PositionServiceClient
添加一个构造函数,以允许传入一个端点URI:
public PositionServiceClient(string endPointAddress) : this(CreateDefaultBinding(), new System.ServiceModel.EndpointAddress(endPointAddress))
现在,可以使用从配置信息中动态构建的端点地址创建PositionServiceClient
。
使用Microsoft提供的类来实现这一点非常简单,这些类包装了WM6中的原生GPS API。已经将这些类包含在应用程序中,并更改了命名空间以匹配应用程序的命名空间。没有错误:所有荣誉都归Microsoft,这些类非常容易使用!
初始化部分在表单的Load
处理程序中:
private void PositionSenderForm_Load(object sender, EventArgs e)
调用Gps.Open
会打开GPS(如果尚未打开)并开始寻找卫星。如果位置发生变化,将调用事件处理程序以更新坐标。就是这么简单!
最后一部分涉及使用GPS坐标显示地图。Google提供了一个API,可以获取以一组纬度/经度值为中心的地图图像,并指定缩放值。必须使用以下格式构建URL:
String.Format(CultureInfo.InvariantCulture, "http://maps.google.com/staticmap?center={0},{1}&size={5}x{6}&markers={0},{1},greenc&zoom={2}&maptype={3}&key={4}", _coordinate.Latitude, _coordinate.Longitude, _zoomLevel, _mapType, _apiKey, _xSize, _ySize);
为此,使用了MapUrlBuilder
类。
检索图像的代码如下:
MapUrlBuilder builder = new MapUrlBuilder(); builder.CenterCoordinate = coordinate; builder.MapType = "mobile"; builder.ZoomLevel = 15; builder.XSize = mapPictureBox.ClientRectangle.Width; builder.YSize = mapPictureBox.ClientRectangle.Height; builder.GoogleMapsAPIKey = _configuration.GoogleMapAPIKey;
LocationMap map = new LocationMap(builder.MapUrl); mapPictureBox.Image = map.Map;
LocationMap
类以如下方式检索图像:
private Bitmap FromUrl(string url) { WebRequest request = HttpWebRequest.Create(url); WebResponse response = request.GetResponse(); Bitmap bmp = new Bitmap(response.GetResponseStream()); return bmp; }