使用 Windows Mobile 5.0+ 进行 GPS 定位






4.60/5 (20投票s)
使用带有 GPS 接收器的 Windows Mobile Professional 手机,创建一个简单的基于 SMS 的位置追踪程序。
引言
这个程序是我计划构建的更大系统的概念验证。最终,我希望有一个系统允许用户选择加入或退出位置的公开。位置信息将通过运行在 Windows Mobile 5.0(或更高版本)设备上的应用程序获取。这样的系统既有商业应用(例如,知道送货员或服务人员的位置),也有个人应用(例如,您正前往朋友家,朋友想知道您还有多远)。在这个原型中,我的目标是触及该系统的部分基础技术。
对于这个概念验证,我希望能够通过 GPS 辅助驱动程序获取 GPS 信息,并希望有一种方式让手机根据手机所有者或其联系人的请求发送这些信息。因此,这里使用的基本技术是:
- GPS 辅助驱动程序 - 以不干扰其他 GPS 应用程序的方式获取 GPS 信息。
- MessageInterceptor - 等待位置请求,并在收到请求时启动应用程序。
所需工具
要运行此代码,您需要安装 Visual Studio 2005,以及 Windows Mobile 5.0 SDK 和 Windows Mobile 6 Professional SDK。需要 5.0 SDK 是因为我将项目设置为面向 5.0 设备。用于访问 GPS 设备的代码是 6.0 SDK 的一部分(尽管它在 5.0 设备上也能很好地运行)。我已经在我的项目中包含了 GPS 包装器的已编译程序集,但没有源代码。要查看此包装器的源代码,您必须拥有 Windows Mobile Professional 6.0 SDK。
我建议您也准备一台 Windows Mobile 5.0 设备来测试该应用程序。您可以使用模拟器来测试程序。该程序使用 SMS 消息。根据您与手机公司的服务套餐,您可能需要为每条发送和接收的消息支付费用。我属于这一类,因为目前,美国境内的运营商不允许许多手机在同一手机线上拥有无限短信订阅和无限数据订阅。因此,对于程序的初步测试,模拟器可能更可取。您可以将模拟的 Windows Mobile 设备的 COM 端口重定向到连接到 PC 的外部 GPS 接收器,或者您可以使用 Windows Mobile 6.0 SDK 中可用的“FakeGPS”程序来模拟 GPS 接收器。
缺失的 GPS 设置图标
在运行 Windows Mobile 5 Professional 及更高版本的手机(触摸屏手机)上,设置菜单中有一个图标,允许用户设置 GPS 接收器通信的硬件端口。在一些非常流行的 Windows Mobile 手机上,这个图标不见了。它并没有被删除。而是,一些 OEM 厂商认为应该隐藏该图标。通过删除注册表项 [HKEY_LOCAL_MAHINE\ControlPanel\Settings\GPS Settings\Hide] 和 [HKEY_LOCAL_MAHINE\ControlPanel\Settings\GPS Settings\Redirect],可以恢复该图标。如果您没有注册表编辑器,可以通过运行本文附加的 GPS 图标恢复程序来删除这些项。只需将其复制到您的手机并运行即可。它会显示一个消息框,告知您操作成功或这些项不存在。您可能需要在运行此程序后重置您的手机,以便更改生效。
该程序如何工作
首次运行时,手机所有者可以输入一个用于标识位置请求消息的 PIN 码。当收到 SMS 消息时,如果消息包含用户选择的 PIN 码,该程序将被启动(如果尚未运行),并将消息传递给程序。所有其他消息将像平常一样在手机上处理。收到消息后,程序会读取手机的当前 GPS 坐标,并回复发送者一个指向 local.live.com 的地图链接,该链接显示手机所有者的当前位置。
使用 MessageInterceptor 类捕获 SMS 消息
顾名思义,MessageInterceptor
类用于捕获传入的 SMS 消息,并允许您的代码在收到消息时进行响应。您无需手动检查所有消息,而是为感兴趣的消息类型设置消息规则。在此程序中,该类只有一个我们感兴趣的属性:MessageCondition
。
MessageCondition
成员属于同名类 MessageCondition
。MessageCondition
允许您指定一个将在消息中搜索的字符串。您可以指定该字符串必须出现在消息的开头、结尾或任何位置,并且可以指定搜索是否区分大小写。对于此程序,我已将 MessageCondition
类设置为仅在消息正文中搜索您的 PIN 码的出现。
_messageInterceptor.MessageCondition = new MessageCondition();
_messageInterceptor.MessageCondition.CaseSensitive = false;
_messageInterceptor.MessageCondition.ComparisonType =
MessagePropertyComparisonType.Contains;
_messageInterceptor.MessageCondition.ComparisonValue = this.txtPin.Text;
_messageInterceptor.MessageCondition.Property = MessageProperty.Body;
设置好条件后,只需启用 MessageInterceptor
,并为其提供一个事件处理程序。
_messageInterceptor.EnableApplicationLauncher(ruleName);
_messageInterceptor.MessageReceived += _messageInterceptorEventHandler;
用户可能自 MessageInterceptor
创建以来已退出程序。如果在程序退出后收到消息,并且用户将程序保留在启用状态,则程序将自动启动。要捕获导致程序启动的消息,我们必须在程序的 Load
事件中创建 MessageInterceptor
类。在加载期间,程序会检查应用程序是否已注册为在收到消息时自动加载。如果是这种情况,程序将创建一个新的 MessageInterceptor
并为其提供一个事件处理程序。然后,应用程序将通过事件处理程序接收到该消息的通知。
if (MessageInterceptor.IsApplicationLauncherEnabled(ruleName))
{
_messageInterceptor = new MessageInterceptor(ruleName);
_messageInterceptor.MessageReceived +=
new MessageInterceptorEventHandler(_messageInterceptor_MessageReceived);
txtPin.Text = _messageInterceptor.MessageCondition.ComparisonValue;
this.chkFindMeEnabled.Checked = true;
}
else
{
this.chkFindMeEnabled.Checked = false;
}
获取当前位置
辅助 GPS 驱动程序为我们处理了与 GPS 硬件的接口细节。我使用的是 Windows Mobile 6 SDK 中包含的一个包装器,它简化了驱动程序的使用。该代码工作良好,易于使用,因此我建议您考虑使用它,而不是创建自己的 GPS 读取代码。初始化 GPS 对象只需几行代码即可完成:
gps = new Gps();
gps.LocationChanged +=
new LocationChangedEventHandler(gps_LocationChanged);
gps.Open();
从 LocationChanged
事件收到的 EventArgs
包含的信息比您可能从 GPS 接收器中获得的要多。我只是保存了 EventArgs
中的 Position
成员,并更新了 _currentLocation
对象。
void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
if (args.Position.LatitudeValid && args.Position.LongitudeValid)
{
currentPosition = args.Position;
UpdatePosition();
}
}
当程序不再需要使用 GPS 接收器时,会调用 Gps.Close()
来结束对象的辅助线程。如果不这样做,可能会导致程序永远无法终止。
发送消息
发送消息很简单。对于 SMS 消息,会创建一个新的 SMSMessage
对象,其构造函数参数是接收者的号码和消息文本。然后,调用该对象的 Send()
方法来发送消息。由于 SMS 消息不能超过 160 个字符,因此 SMS 消息中发送的链接仅包含用户的坐标和图钉。
在手机上接收包含地图链接的 SMS 消息不切实际,所以您可能会想知道为什么程序具有此功能。您必须记住,计算机也可以通过其他应用程序(如 Live Messenger)或内置硬件(如 GMS 调制解调器或 CDMA 调制解调器)发送 SMS 消息。
public void SmsSendCoordinates(string to,GpsPosition pos)
{
string message = String.Format(responseTemplate,
pos.Latitude, pos.Longitude);
SmsMessage sms = new SmsMessage(to, message);
sms.Send();
this.eventLog.Add(DateTime.Now, to, pos);
}
发送电子邮件消息同样简单。创建一个新的电子邮件对象,填充主题和正文,将地址添加到“收件人”集合中,然后调用其 Send()
方法。电子邮件的 Send()
方法需要一个 SMS 发送时不需要的参数,即要使用的邮件帐户的名称。在我的手机上,可用的帐户名为“ActiveSync”和“MMS”。我自然不愿使用 MMS,因为我的手机服务提供商对我通过 MMS 发送消息收费过高。
由于电子邮件不受 160 个字符的限制,我可以将更多信息放入链接中。因此,在发送电子邮件时,程序可能会(取决于用户选择的选项)包含自定义文本和用于表示用户的图像。
public void EmailSendCoordinates(string emailAddress, GpsPosition pos)
{
string avatarUrl = string.Empty;
string displayName = string.Empty;
string customMessage=string.Empty;
if(((_Settings.OptionFlags&OptionChangedFlags.Avatar)==
OptionChangedFlags.Avatar)&& (_Settings.Avatar.Length>0)
)
avatarUrl=_Settings.Avatar;
displayName = optionsUI.DisplayName;
customMessage = optionsUI.CustomMessage;
string message = String.Format(detailedResponseTemplate,
pos.Latitude, pos.Longitude,
Utility.UrlEncode(avatarUrl), Utility.UrlEncode
(displayName), Utility.UrlEncode(customMessage));
EmailAccount account =
(new OutlookSession()).EmailAccounts[_Settings.EmailAccount];
EmailMessage msg = new EmailMessage();
msg.To.Add(new Recipient(emailAddress));
msg.Subject = "My location";
msg.BodyText = message;
msg.Send(account);
this.eventLog.Add(DateTime.Now, emailAddress, pos);
}
下一步
我希望为这个程序添加相当多的功能。在下一个版本中,我计划添加一个地图控件,以便用户可以在手机上看到彼此的位置。我也可能增加对 Windows Mobile 5 Standard Edition(无触摸屏设备)的支持。要实现这一点,需要一个 Web 服务器。一旦这两部分都正常工作,我计划使用 Windows Live Search 和 MapPoint API 提供查找兴趣点和获取路线的功能,以便用户可以相互见面。
历史
- 2007 年 8 月 15 日 - 文章发布。