ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:137.23KB ,
资源ID:7033526      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7033526.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(位置感知的应用程序.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

位置感知的应用程序.docx

1、位置感知的应用程序Windows Mobile技术文章翻译系列(1)为Windows Mobile设备创建位置感知的应用程序Author: MagicBoy | Posted: 16. 三月 2010 20:52 150 作者:Maarten Struys, Alten-PTS 日期:2009-12-28概要为你的应用程序添加位置感知并在当前位置呼叫Web服务,不仅为在线商务应用也为其他各种各样的消费者应用程序增加了许多潜在价值。你可以根据本文介绍的技术通过GPS检索或蜂窝站点检索获取当前位置从而开发具备位置感知的应用程序。本文主要讨论为Windows Mobile应用程序添加位置感知功能的技

2、术细节。涵盖了诸如定位对电池寿命的影响等问题,并提供了相关的代码和示例。适用于 Windows Mobile 5.0 Windows Mobile 5.0 SDK Windows Mobile 6 Professional Windows Mobile 6 SDK 索引 简介 通过GPS检索位置信息 使用GPSID托管包 通过蜂窝站点检索位置信息 在Windows Mobile 设备上访问蜂窝站点信息 使Windows Mobile 设备的位置感知不依赖于位置检索方式 使用类工厂取回当前位置 总结 关于代码 作者经历 简介位 置感知需要获得你的Windows Mobile设备的当前位置。所以你

3、必须使你的应用程序能够感知位置。应用程序应该被设计为不依赖于位置检索方式。这个白皮书向你展示了怎样通过GPS检 索和蜂窝站点检索取得你的位置信息。你也将学习到如何在Windows Mobile 设备中使用位置信息。通过GPS检索位置信息在Windows Mobile设备中有几种不同的方式检索位置信息,各自有着不同的优势。Windows Mobile 5.0和Windows Mobile 6.0设备中都包含了GPS中间驱动(GPSID)。尽管从名字来看它似乎是一个设备驱动,但实际上它并不是一个真正的设备驱动。GPSID是介于控制 GPS接收器的设备驱动与要使用GPS信息的应用程序之间的一个抽象层

4、。应用程序和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公

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

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

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

8、程序。在调用同步方法GetPosition后,位置信息被取回,并且通过注册LocationChanged 事件而持续更新。为了同步获取位置,如以下的示例代码展示的一样,你必须在调用Gps对象的Open方法之后调用另外一个一个方法。在这个代码示例中,一个Gps类的实例在MainForm的的构造方法中被创建,并立即调用了它的Open方法以启用GPS硬件。当用户选择了My Location菜单后menuLocation_Click事件处理程序中的代码就会执行。在这个事件处理程序中,你会看到程序通过GetPosition方法获取到了当前位置。直到GPSID返回从底层硬件获得的位置后,这个方法才会中断。

9、在位置信息可用后,纬度、经度和头信息的读取就会生效并在一个Label空间中显示出来。简而言之,在读取生效前任何操作都是不可用的。GetPosition方 法有两种可用的风格。以下第一个示例代码中用的方法是一直等待,直到GPS硬件返回新的读取信息;换句话说,就是在收到来自一个或多个卫星的位置信息之 前,程序会一直等待。同时还有一个以时间戳对象为参数的重载方法可用。用这个方法,可以返回一个缓存的只要不比指定时间戳老的位置信息,从而更高效得获取 位置。当你知道设备的位置从上次读取之后没有变化时,这个版本的GetPosition方法对初始化位置读取是很有用的。 如下的代码展示了如何通过GPSID同步获

10、取位置。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.GetPosi

11、tion(); 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();

12、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对象的初始化被省略了,因为它和

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

14、理程序中看到的一样,控件必须通过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.LocationChange

15、d += 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 = positio

16、n.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.A

17、ppendLine(location.Longitude.ToString(); sb.Append(Heading = ); sb.AppendLine(location.Heading.ToString(); label2.Invoke(UpdateLocationInfo)delegate() label2.Text = sb.ToString(); ); GPSID与电池在上面的第二段代码示例中,位置信息仅仅是更新并提供给用户。在某些情况下,合理的做法是添加代码使应用程序工作于前台时更新位置信息(例如在地图 中显示位置信息的更新),而在应用程序转到后台时停止位置信息的持续更新。限制工作

18、于后台的应用程序的运行以节省电池电量。在这样的情况下你甚至可以通过 在应用程序转到后台时关闭GPSID连接,而在程序转到前台时重新打开的方式来节省更多的电量。下面的代码演示了如何优化应用程序以维持电池的寿命。应用 程序通过对MainForm对象引发的Activated事件作出反应,从而在每次应用程序转到前台时注册LocationChanged事件。通过对MainForm对象引发的Deactivate事件作出反应,在每次应用转到后台时解除LocationChanged事件的绑定。下面的代码示范了如何在应用程序转到后台时节省电池电量。private void MainForm_Activated(

19、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轻易得取得你的当前位置,

20、并且卫星返回的位置非常精确,然而使用GPSID却未必是获取位置信息最高效的方法。从开始到第 一个位置信息被返回给设备可能花费很长时间。依赖于物理硬件设备,你的当前位置,卫星的可见性,以及最后一次通过GPSID的位置读取,取得位置信息可能 会花费几分钟的时间。如果你不需要达到GPS传输的精确度,但同事又需要更快的定位速度,可以考虑以下的选择。 通过蜂窝基站检索位置信息大部分的Windows Mobile设备当然都是手机。依赖于你所使用的移动运营商,你的手机可以以编程方式取得蜂窝基站的信息。信息中包含一个蜂窝基站代码、一个地区代码和一 个国家代码。根据这些信息,你可以取得你的手机当前连接的蜂窝基站

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

22、 RIL的推荐设置禁止不受信任的应用程序访问RIL功能。因此,你必须用一个有效的证书为你的应用程序签名,或者在你的应用程序内部限制对TIL功能的访 问。为了取得为蜂窝基站信息,你主要要调用一个独立的RIL函数。但是,你必须调用其他的函数作为RIL的处理程序,并且必须在结束使用RIL功能时清楚 这些处理程序。你可能对通过访问Windows Mobile的底层功能取回蜂窝基站信息还不是很熟悉。但是这不是什么大问题,因为无线接口层被实现为划分成两个独立层次的驱动程序和一个从应用程序内部 访问信息的代理。MDD(模型设备驱动)层是独立于无线通讯堆栈的。它包含了与RIL代理通信的代码,和RIL驱动中所有

23、无线通讯功能的实现。发布在 MDD层中的代码是使用安全、文档良好的,并且为你提供了对所有种类无线通讯功能的高层访问。另一方面,RIL的底层,PDD(平台依赖驱动)层是依赖于 无线通信层的。每个OEM对它的实现都是不同的。RIL公开了几个以“RIL_”为前缀的API.这些API都是用本地代码编写的,因此想要在托管程序中访问必须使用P/Invoke。你必须使用以下的API来获取蜂窝基站信息: RIL_Initialize.初始化无线接口层以提供应用程序使用。 RIL_Deinitialize.在应用程序结束使用RIL时正确地关闭并清除资源。 RIL_GetCellTowerInfo.获取Widow

24、s 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(

25、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);D

26、llImport(ril.dll)public static extern IntPtr RIL_Deinitialize(IntPtr hRil);使用RIL_Initialize,你既可以通过回调函数pfnResult返回结果,也可以通过回调函数pfnNotify来异步返回应用程序通过dwNotificationClasses注册的所有状态的状态改变。这个白皮书的示例代码只使用了同步操作。每次当应用程序调用RIL_GetCellTowerInfo时,这个API的执行结果就马上返回。然而,实际的数据却是通过传递给RIL_Initialize 的回调函数pfnResult返回的。回调函数返回一

27、个结构体,这个结构体必须先经过整理然后才能在托管代码中使用。下面的代码展示了在调用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; Field

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

29、c 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的异步行为通过基站信息可用时设置的

30、一个托管事件转变成了同步行为。如下的代码示范了在托管代码中如何获取基站信息。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.RI

31、L_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.dwMobileNetworkC

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1