代码改变世界

为Windows Mobile设备创建位置感知的应用程序

2010-12-17 23:11  MagicKing110  阅读(2425)  评论(6编辑  收藏  举报

概要

为你的应用程序添加位置感知并在当前位置呼叫Web服务,不仅为在线商务应用也为其他各种各样的消费者应用程序增加了许多潜在价值。你可以根据本文介绍的技术通过GPS检索或蜂窝站点检索获取当前位置从而开发具备位置感知的应用程序。

本文主要讨论为Windows Mobile应用程序添加位置感知功能的技术细节。涵盖了诸如定位对电池寿命的影响等问题,并提供了相关的代码和示例。

适用于

  • Windows Mobile 5.0
  • Windows Mobile 5.0 SDK
  • Windows Mobile 6 Professional
  • Windows Mobile 6 SDK

索引

简介

位置感知需要获得你的Windows Mobile设备的当前位置。所以你必须使你的应用程序能够感知位置。应用程序应该被设计为不依赖于位置检索方式。这个白皮书向你展示了怎样通过GPS检索和蜂窝站点检索取得你的位置信息。你也将学习到如何在Windows Mobile 设备中使用位置信息。

通过GPS检索位置信息

在Windows Mobile设备中有几种不同的方式检索位置信息,各自有着不同的优势。Windows Mobile 5.0和Windows Mobile 6.0设备中都包含了GPS中间驱动(GPSID)。尽管从名字来看它似乎是一个设备驱动,但实际上它并不是一个真正的设备驱动。GPSID是介于控制GPS接收器的设备驱动与要使用GPS信息的应用程序之间的一个抽象层。应用程序和GPS硬件之间GPSID的存在给了Windows Mobile 5.0及Windows Mobile 6设备比以前本版本更大的优势。通过GPSID,多个应用程序可以使用同一个GPS硬件,而在Windows Mobile 5.0中这是不可能的。在那些先前版本的Windows Mobile设备中同一时间只能有一个应用程序访问GPS硬件。为了使一个应用程序通过GPS接收器获得位置信息,原来正在使用GPS硬件的应用必须关闭,至少必须停止使用GPS硬件。GPSID解决了这个问题,因为它扮演了从底层使用GPS硬件的唯一应用程序。同时,GPSID也扮演了多个应用程序的位置提供者。

GPSID公开了几个本地API来检索位置信息。当然,这个白皮书重点关注托管应用程序开发。托管应用开发者可以通过包含在Windows Mobile 5.0和Windows Mobile 6 SDK中的简单代码来访问一系列基于本地GPSID APIs的托管包。假设你已经安装了Windows Mobile 6 SDK在默认文件夹的话,你可以在以下路径找到这些托管包:

C:\Program Files\Windows Mobile 6 SDK\Samples\PocketPC\CS\GPS

这个路径和Windows  Mobile 5.0 SDK是不同的。

使用GPSID托管包

打开Windows Mobile 5.0 或Windows Mobile 6 SDK 中的GPS示例,你会看到一个包含完整源代码的项目。为了使用GPSID托管包,你必须首先编译这个示例项目。因为Windows Mobile SDKs实在Visual Studio 2008之前发布的,所以在用Visual Studio 2008编译示例项目之前必须先进行转化。Visual Studio 2008会处理项目的转换。在示例项目编译之后,你会看到一个可执行文件和一个类库。类库的名字为Microsoft.WindowsMobile.Samples.Location.dll 。它包含了这个GPSID托管包。为了使用这些托管包,你必须在你的项目中添加对这个类库的引用。

下面的示意图展示了GPSID托管包中的类。

Dd938890_695aad9d-2944-4806-aa7a-1217f1477695(en-us,MSDN_10)

如果你想在你的托管应用程序中使用GPSID,在添加了对GPSID托管包的引用之后,首先必须创建一个Gps类的示例。然后你需要在项目中调用Open以获取位置信息。你可以用同步或异步的方式来获取位置信息。在稍后的案例中,你将会在GPS接收器数据变化时获得持续更新的数据。你必须意识到GPS通信,作为一个附加通信,是很消耗电池的。因此,如果你不再需要在应用程序中获取位置信息时,请确保调用Gps对象的Close方法。忽略调用Close方法会使Gps通讯保持工作状态,即使你不在需要获取位置信息。

下面的屏幕展示了一个同步和异步获取GPS位置信息的示例应用程序。在调用同步方法GetPosition后,位置信息被取回,并且通过注册LocationChanged 事件而持续更新。

Dd938890_4770c85c-ded9-4bd5-9029-95805bd52404(en-us,MSDN_10)

为了同步获取位置,如以下的示例代码展示的一样,你必须在调用Gps对象的Open方法之后调用另外一个一个方法。在这个代码示例中,一个Gps类的实例在MainForm的的构造方法中被创建,并立即调用了它的Open方法以启用GPS硬件。当用户选择了My Location菜单后menuLocation_Click事件处理程序中的代码就会执行。在这个事件处理程序中,你会看到程序通过GetPosition方法获取到了当前位置。直到GPSID返回从底层硬件获得的位置后,这个方法才会中断。在位置信息可用后,纬度、经度和头信息的读取就会生效并在一个Label空间中显示出来。简而言之,在读取生效前任何操作都是不可用的。GetPosition方法有两种可用的风格。以下第一个示例代码中用的方法是一直等待,直到GPS硬件返回新的读取信息;换句话说,就是在收到来自一个或多个卫星的位置信息之前,程序会一直等待。同时还有一个以时间戳对象为参数的重载方法可用。用这个方法,可以返回一个缓存的只要不比指定时间戳老的位置信息,从而更高效得获取位置。当你知道设备的位置从上次读取之后没有变化时,这个版本的GetPosition方法对初始化位置读取是很有用的。

如下的代码展示了如何通过GPSID同步获取位置。

public partial class MainForm : Form
{
	private Gps gps;

	public MainForm()
	{
		InitializeComponent();
		gps = new Gps();
		gps.Open();
	}

	private void menuExit_Click(object sender, EventArgs e)
	{
		gps.Close();
		Close();
	}

	private void menuLocation_Click(object sender, EventArgs e)
	{
		GpsPosition position = gps.GetPosition();
		LatLong location = new LatLong();
		
		if (position.LatitudeValid)
			location.Latitude = position.Latitude;
		if (position.LongitudeValid)
			location.Longitude = position.Longitude;
		if (position.HeadingValid)
			location.Heading = position.Heading;

		StringBuilder sb = new StringBuilder();
		sb.AppendLine();
		sb.Append("Latitude = ");
		sb.AppendLine(location.Latitude.ToString());
		sb.Append("Longitude = ");
		sb.AppendLine(location.Longitude.ToString());
		sb.Append("Heading = ");
		sb.AppendLine(location.Heading.ToString());

		label1.Text = sb.ToString();
	}
}

为了异步获取位置,如下一个示例代码所示,你必须注册LocationChanged事件。在这个示例中GPS对象的初始化被省略了,因为它和第一个代码示例是一样的方式。无论应用程序有没有注册LocationChanged事件,用户都可以选择Location Updates菜单(参看GPS Lookup屏幕)。当应用程序注册了这个事件时,在gps_LocationChanged事件处理程序中就会接收到持续更新的位置信息。与同步方式取得的位置信息相同,这个信息在GpsPosition对象中也是可用的。然而,异步更新是在不同的线程中获取的,甚至对GPSID用户来说是透明的。因为除了用户界面控件的创建者进程之外其他进程都不允许更新用户界面,所以要更新用户界面还必须做一些其他的工作。就像你在下面代码中gps_LocationChanged处理程序中看到的一样,控件必须通过Control.Invoke方法来更新。

如下代码展示了如何通过GPSID一步获取位置。

        
private void menuLocationUpdates_Click(object sender, EventArgs e)
{
	if (menuLocationUpdates.Checked)
	{
		menuLocationUpdates.Checked = false;
		gps.LocationChanged -= gps_LocationChanged;
	}
	else
	{
		menuLocationUpdates.Checked = true;
		gps.LocationChanged += new
			LocationChangedEventHandler(gps_LocationChanged);
	}
}

private delegate void UpdateLocationInfo();

void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
	GpsPosition position = args.Position;
	LatLong location = new LatLong();

	if (position.LatitudeValid)
		location.Latitude = position.Latitude;
	if (position.LongitudeValid)
		location.Longitude = position.Longitude;
	if (position.HeadingValid)
		location.Heading = position.Heading;

	StringBuilder sb = new StringBuilder();
	sb.AppendLine();
	sb.Append("Latitude = ");
	sb.AppendLine(location.Latitude.ToString());
	sb.Append("Longitude = ");
	sb.AppendLine(location.Longitude.ToString());
	sb.Append("Heading = ");
	sb.AppendLine(location.Heading.ToString());

	label2.Invoke((UpdateLocationInfo)delegate()
	{
		label2.Text = sb.ToString();
	});
} 

GPSID与电池

在上面的第二段代码示例中,位置信息仅仅是更新并提供给用户。在某些情况下,合理的做法是添加代码使应用程序工作于前台时更新位置信息(例如在地图中显示位置信息的更新),而在应用程序转到后台时停止位置信息的持续更新。限制工作于后台的应用程序的运行以节省电池电量。在这样的情况下你甚至可以通过在应用程序转到后台时关闭GPSID连接,而在程序转到前台时重新打开的方式来节省更多的电量。下面的代码演示了如何优化应用程序以维持电池的寿命。应用程序通过对MainForm对象引发的Activated事件作出反应,从而在每次应用程序转到前台时注册LocationChanged事件。通过对MainForm对象引发的Deactivate事件作出反应,在每次应用转到后台时解除LocationChanged事件的绑定。

下面的代码示范了如何在应用程序转到后台时节省电池电量。

private void MainForm_Activated(object sender, EventArgs e)
{
	if (menuLocationUpdates.Checked)
	{
		gps.LocationChanged += new
			LocationChangedEventHandler(gps_LocationChanged);
	}
}

private void MainForm_Deactivate(object sender, EventArgs e)
{
	if (menuLocationUpdates.Checked)
	{
		gps.LocationChanged -= gps_LocationChanged;
	}
}

尽管你可以通过GPSID轻易得取得你的当前位置,并且卫星返回的位置非常精确,然而使用GPSID却未必是获取位置信息最高效的方法。从开始到第一个位置信息被返回给设备可能花费很长时间。依赖于物理硬件设备,你的当前位置,卫星的可见性,以及最后一次通过GPSID的位置读取,取得位置信息可能会花费几分钟的时间。如果你不需要达到GPS传输的精确度,但同事又需要更快的定位速度,可以考虑以下的选择。

通过蜂窝基站检索位置信息

大部分的Windows Mobile设备当然都是手机。依赖于你所使用的移动运营商,你的手机可以以编程方式取得蜂窝基站的信息。信息中包含一个蜂窝基站代码、一个地区代码和一个国家代码。根据这些信息,你可以取得你的手机当前连接的蜂窝基站的位置,从而为你提供不同精确度的位置信息。通过蜂窝基站检索位置的优势在于可以不使用额外电量而快速得取得你的当前位置。其缺点是假如你不使用蜂窝基站三角测量法的话,精确度是不确定的。另一个缺点是你必须创建额外的代码来获取位置。蜂窝基站信息的获取可以通过Windows Mobile设备中的无线接口层(RIL)来实现。然而,仅仅有蜂窝基站代码、国家代码及移动运营商的信息是不够的。所有这些信息都必须最终转化为位置。你可以把取得的蜂窝基站信息传递给第三方Web服务。

在Windows Mobile设备中访问蜂窝基站信息

为了在你的应用程序中取得蜂窝基站信息,你必须要访问设备的无线接口层(RIL)。OEM RIL的推荐设置禁止不受信任的应用程序访问RIL功能。因此,你必须用一个有效的证书为你的应用程序签名,或者在你的应用程序内部限制对TIL功能的访问。为了取得为蜂窝基站信息,你主要要调用一个独立的RIL函数。但是,你必须调用其他的函数作为RIL的处理程序,并且必须在结束使用RIL功能时清楚这些处理程序。

你可能对通过访问Windows Mobile的底层功能取回蜂窝基站信息还不是很熟悉。但是这不是什么大问题,因为无线接口层被实现为划分成两个独立层次的驱动程序和一个从应用程序内部访问信息的代理。MDD(模型设备驱动)层是独立于无线通讯堆栈的。它包含了与RIL代理通信的代码,和RIL驱动中所有无线通讯功能的实现。发布在MDD层中的代码是使用安全、文档良好的,并且为你提供了对所有种类无线通讯功能的高层访问。另一方面,RIL的底层,PDD(平台依赖驱动)层是依赖于无线通信层的。每个OEM对它的实现都是不同的。

RIL公开了几个以“RIL_”为前缀的API.这些API都是用本地代码编写的,因此想要在托管程序中访问必须使用P/Invoke。你必须使用以下的API来获取蜂窝基站信息:

  • RIL_Initialize.初始化无线接口层以提供应用程序使用。
  • RIL_Deinitialize.在应用程序结束使用RIL时正确地关闭并清除资源。
  • RIL_GetCellTowerInfo.获取Widows Mobile设备所使用的蜂窝基站信息。

正如你在下面的代码示例中看到的一样,从托管代码中访问这些API是相当简单的。以下代码展示用以访问RIL的P/Invoke的声明。

public delegate void RILRESULTCALLBACK(uint dwCode,
        IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam);
public delegate void RILNOTIFYCALLBACK(uint dwCode,
	IntPtr lpData, uint cbData, uint dwParam);

[DllImport("ril.dll")]
public static extern IntPtr RIL_Initialize(uint dwIndex,
	RILRESULTCALLBACK pfnResult,
	RILNOTIFYCALLBACK pfnNotify,
	uint dwNotificationClasses,
	uint dwParam,
	out IntPtr lphRil);
[DllImport("ril.dll", EntryPoint = "RIL_GetCellTowerInfo")]
public static extern IntPtr RIL_GetCellTowerInfo(IntPtr hRil);
[DllImport("ril.dll")]
public static extern IntPtr RIL_Deinitialize(IntPtr hRil);

使用RIL_Initialize,你既可以通过回调函数pfnResult返回结果,也可以通过回调函数pfnNotify来异步返回应用程序通过dwNotificationClasses注册的所有状态的状态改变。这个白皮书的示例代码只使用了同步操作。每次当应用程序调用RIL_GetCellTowerInfo时,这个API的执行结果就马上返回。然而,实际的数据却是通过传递给RIL_Initialize 的回调函数pfnResult返回的。回调函数返回一个结构体,这个结构体必须先经过整理然后才能在托管代码中使用。下面的代码展示了在调用RIL_GetCellTowerInfo之后由RIL返回的结构体。

[StructLayout(LayoutKind.Explicit)]
internal class RILCELLTOWERINFO
{
	[FieldOffset(0)]
	uint dwSize;
	[FieldOffset(4)]
	uint dwParams;
	[FieldOffset(8)]
	public uint dwMobileCountryCode;
	[FieldOffset(12)]
	public uint dwMobileNetworkCode;
	[FieldOffset(16)]
	public uint dwLocationAreaCode;
	[FieldOffset(20)]
	public uint dwCellID;
}

在这段代码中,你将看到如何取得最重要的结构体成员以传递给一个可以返回蜂窝基站位置的Web服务。在RILCELLTOWERINFO结构体中还有一些更有趣的字段,譬如,你所连接的基站的信号强度。通过这个结构体的其他成员,你可以自己计算出一个更为精确的当前位置。然而为了简单起见,我们只关注你所连接的蜂窝基站和它的位置。现在在托管代码中,你可以取得你所连接的基站的信息并存储到一个类中了。

如下的代码示范了托管类如何存储蜂窝基站信息。

public class CellTower
{
	public int CellId { get; set; }
	public int LAC { get; set; }
	public int MCC { get; set; }
	public int MNC { get; set; }
}

你可以使用下面的示例代码来调用必须的RIL APIs。有趣的部分是蜂窝基站信息被返回给RIL_GetCellTowerInfo调用者的方式。信息不是至极返回的,而是通过一个回调函数返回的。因为位置感知的应用程序在Windows Mobile获知自己的位置之前无法做任何有用的工作,所以RIL_GetCellTowerInfo的异步行为通过基站信息可用时设置的一个托管事件转变成了同步行为。

如下的代码示范了在托管代码中如何获取基站信息。

public class CellTowerInfo
{
	private static AutoResetEvent dataReceived = new AutoResetEvent(false);
	private static RIL.RILCELLTOWERINFO towerInfo;

	public static CellTower GetCellTowerInfo()
	{
		IntPtr hRIL = IntPtr.Zero;
		IntPtr hResult = IntPtr.Zero;

		hResult = RIL.RIL_Initialize(1, 
			new RIL.RILRESULTCALLBACK(CellTowerData), 
			null, 0, 0, out hRIL);

		if (hResult != IntPtr.Zero)
			return null;

		hResult = RIL.RIL_GetCellTowerInfo(hRIL);
		dataReceived.WaitOne();

		RIL.RIL_Deinitialize(hRIL);

		CellTower ct = new CellTower();
		ct.LAC = (int)towerInfo.dwLocationAreaCode;
		ct.MCC = (int)towerInfo.dwMobileCountryCode;
		ct.MNC = (int)towerInfo.dwMobileNetworkCode;
		ct.CellId = (int)towerInfo.dwCellID;

		return ct;
	}

	private static void CellTowerData(uint dwCode,
		IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam)
	{
		towerInfo = new RIL.RILCELLTOWERINFO();
		Marshal.PtrToStructure(lpData, (object)towerInfo);
		dataReceived.Set();
	}
}

为了取得你所连接的基站位置,你还需要一些其他的附加功能,如数据库或Web服务以查询基站的坐标。有一些商业的和一些免费的Web服务可用于取得蜂窝基站的位置信息。这篇文章使用了两个托管与Yahoo的Web服务来获取基站的经纬度信息。Yahoo有一个极其易用的Web服务可以取得蜂窝基站的邮政编码。有了蜂窝基站的邮政编码,你可以传递这个邮编给另一个Yahoo的Web服务以转化一个邮编为经纬度。要获得基站位置,请参阅Yahoo网站。传递从RIL_GetCellTowerInfo 得到的国家代码(dwMobileCountryCode)、网络代码(dwMobileNetworkCode)、地区代码(dwLocationAreaCode)和基站ID(dwCellID),你就可以得到一个包含基站位置的邮政编码。你可以传递这个邮编给另一个Yahoo Web 服务,就可以取得你当前连接的蜂窝基站的经纬度。要使用这些Web服务,你必须注册并获取个Application ID。获得一个Application Id是很容易的。下面的屏幕展示了通过不同的Web服务取得的基站位置。

Dd938890_d6c322f3-5331-4c2b-b13b-3ebdf0acc6a0(en-us,MSDN_10)

这个白皮书中所用的Web服务是REST服务,也就意味着无论从浏览器还是应用程序中创建请求URL都是很容易的。譬如,你可以构造类似如下形式的URL获取基站位置。

http://zonetag.research.yahooapis.com/services/rest/V1/cellLookup.php?apptoken=3eeb504e7c4cdccf6641bef7cdfa06c8&cellid=19658&lac=1020&mnc=8&mcc=204

下面的代码展示了Yahoo基站查询Web服务返回的XML响应。

<?xml version="1.0" encoding="utf-8" ?> 
<rsp stat="ok">
    <Location>
        <Country cell="current" source="user">Netherlands</Country> 
    </Location>
    <Location>
        <Country cell="" source="GPS">The Netherlands</Country> 
        <State cell="" source="GPS">Array</State> 
        <City cell="" source="GPS">Alphen aan Den Rijn</City> 
        <Zipcode cell="" source="GPS">2408</Zipcode> 
    </Location>
</rsp>

当然还有其他一些可用的Web服务,包括一个由Google托管的可以为世界上的蜂窝基站提供合理精确度位置信息的服务。至于如何使用Google Maps内部使用的非文档化的Web 服务,这已经超出了本文的讨论范围。如果你想阅读更多关于如何访问这个传递基站位置的信息的特定Web服务的内容,你可能会在CodeProject上找到更多感兴趣的文章。

使Windows Mobile 设备的位置感知不依赖于位置检索方式

在你的应用程序中,程序应该是与取得当前位置的方式无关的。无论通过GPSID检索还是蜂窝基站检索,只要你有了一个好的当前位置经纬度读取方式,你都可以在在你的位置感知的应用程序中使用这些位置信息来完成各种任务,譬如以下这些任务:

  • 在Twitter中发布位置感知的"Tweets"
  • 在Face Book中发布照片并自动插入图片的拍摄位置
  • 创建位置感知的博客内容
  • 通过Live Search执行本地搜索
  • 通过Virtual Earth显示当前位置周围的地图

为了保持Windows Mobile应用程序的整洁,并使得取回位置信息的方式不依赖与底层的位置搜索技术,可以考虑创建一个类工厂来获取位置。如果你正在开发一个定位于Windwows Mobile设备的应用程序,你首先应该想到的是通过蜂窝基站获取位置信息。假如你已经通过移动运营商连接到了一个蜂窝基站的话,这种方式是不消耗设备电池的。如果你想得到你的精确位置,或者你不确定通过蜂窝基站得到的位置的精确性,你可以使用GPS功能获得一个更好的定位,甚至可以通过几个Web服务更新蜂窝基站的可用位置信息使其更精确。然而,所有这些功能对你的用户来说应该是透明的。如果你对蜂窝基站检索的位置不够信任的话,可以使用用蜂窝基站检索位置,再结合GPS获得更多细节信息,这是一种被称为Assisted GPS (A-GPS)的纯软件解决方案,然而这个是绝对免费的。它不需要在你设备上的其他硬件。

尽管大部分移动运营商都允许你的应用程序访问蜂窝基站信息,但还是有个别运营商不允许你的应用程序访问任何蜂窝基站信息。最终,所有的移动运营商可能都会使这些基站信息可用,因为开发者和用户可以从位置感知获得很大的益处,并且可以使用运营商的网络来获取位置感知的信息,如好友位置,搜索附近感兴趣的地方,等等。

使用类工厂取回当前位置

为了使位置获取功能对应用程序透明,你可以创建一个接口,在这个接口中定义几个取回位置的方法,和一个可被应用程序注册以获得位置更改通知的事件。

下面的代码示范了在不依赖于所使用的位置提供者是GPS检索还是蜂窝基站检索的情况下获取位置信息的方法。

public class LocationEventArgs : EventArgs
{
	public LocationEventArgs(LatLong l)
	{
		Location = l;
	}
	public LatLong Location { get; set; }
}

public delegate void LocationChangedEvent(ILocationProvider sender,
	LocationEventArgs e);

public interface ILocationProvider : IDisposable
{
	LatLong CurrentLocation { get; }
	void EnableLocationProvider(bool enable);
	void LiveUpdates(int interval);
	void StopUpdates();
	event EventHandler LocationChanged;
}

如果每个位置提供者都实现了这个接口的话,应用程序就可以通过ILocationProvider获取位置信息,而不需要关心在设备上取得位置信息的物理途径。在本文的可下载代码中,两个位置提供者都已经实现了,一个通过蜂窝基站检索获取位置信息,一个通过GPS检索获取。在应用程序中,可以有两种方法获取位置信息。在本文提供的示例应用程序中,用户既可以选择蜂窝基站检索也可以选择GPS检索。当然这也是可以自动化的,让应用程序在启动后先读取蜂窝基站信息,直到GPS可用。

下面的截屏展示了示例应用程序通过不同的方法获取位置信息。

Dd938890_7dc5159d-008d-493d-b50a-50ecd8b288d4(en-us,MSDN_10)

如以下代码所示,在在应用程序内部获取位置信息是非常简单的。

private LatLong location;
ILocationProvider locationProvider;

private void MainForm_Load(object sender, EventArgs e)
{
	if (locationProvider == null && SystemState.PhoneRadioPresent)
	{
		locationProvider = LocationProvider.GetLocationProvider(
			LocationProvider.LocationType.CellTower);
		location = locationProvider.CurrentLocation;
		ShowLocation(location.Latitude, location.Longitude);
	}
}

private void menuLocation_Click(object sender, EventArgs e)
{
	location = locationProvider.CurrentLocation;
	ShowLocation(location.Latitude, location.Longitude);
}

private void menuSettings_Click(object sender, EventArgs e)
{
	if (Settings.GetInstance().ShowDialog() == DialogResult.OK)
	{
		locationProvider = LocationProvider.GetLocationProvider(
			Settings.UseGPS ? LocationProvider.LocationType.GPS :
							  LocationProvider.LocationType.CellTower);
		location = locationProvider.CurrentLocation;
	}
}

展示如何通过调用一些Web服务 使用你的当前位置信息已经超出了本文的探讨范围。然而,只要当你的WIndows Mobiel设备上的位置信息可用之后,你就可以通过多种途径获取位置感知的数据,并且可以把你的位置数据发布到各种社交网络上。当然你也可以使用Microsoft SQL Server® Compact Edition数据库连续存储你的位置信息以实现不同的目的。还有一种有前途的技术(通过IP检索获取位置)在本文中没有介绍。

总结

在Windows Mobile设备上取得位置信息是非常简单的。这篇文章探讨了如何通过不同的方法获取你的位置信息:

  • 蜂窝基站检索,快速,不消耗过多电量,但是不完全精确
  • GPS检索,可能花费一些初始化时间(有时长达几分钟),消耗额外的电量,但是非常精确

为你的应用程序添加位置感知并呼叫你当前位置的Web服务,不仅为在线商务应用程序,也为其他多种消费者应用程序开启了很多可能。你可以使用本文介绍的技术开发一些位置感知的应用程序。通过可以IP检索来获取当前的位置的方法就留给读者来扩展了,这种方法可以返回很精确的结果,尤其在可用Wi-Fi网络密集的区域。

关于示例代码

这篇文章包含了完整的示例代码。当然,如果你在带电话功能的Windows Mobile 6 Professional设备上运行时,示例代码可以工作得很好。为了试验GPS位置获取,设备应该有一个内置或外置的GPS硬件,或者运行一个FakeGPS的实例。为了能够使用蜂窝基站检索Web服务,你必须获得一个Yahoo Application ID并存储在解决方案中作为资源文件一部分的字符串表中的YAHOO_AppID名字下。

作者经历

Maarten Struys是一个经验丰富的软件开发者。他已经伴随着微软的Windows操作系统工作了20多年,先是开发本地应用程序,然后从跨世纪之后,也开发托管应用程序。他是一个在Tech·Ed,MEDC和Mobile Connections等国际会议上都很有名的演讲者。Maarten为MSDN创建了大量关于设备开打的How-Do-I视频。过去,他频繁出席针对Windows Mobile设备开发的MSDN网络广播。这些网络广播都是可以点播的。最近,Maarten为Windows Mobile开发者建立了RampUp program 。Maarten主要关注如何为智能设备创建高性能的托管应用程序,同时使用有限的资源、消耗尽量少的电量。他经常在世界各地游历,讨论Windows Mobile和Windows Embedded CE开发。想获得关于如何在嵌入式环境使用.NET的信息,请访问Maarten的网站http://www.dotmetfordevices.com


参考资料

英文:Creating Location-Aware Applications for Windows Mobile Devices(作者:Maarten Struys, Alten-PTS  )