Share via

January 2009

Volume 24 Number 01

Windows Mobile - Use GPS And Web Maps For Location-Aware Apps

By Christopher Mitchell | January 2009

Code download available

This article discusses:

  • MapPoint Web services
  • Caching tasks and maps
  • Getting nearby points of interest
  • Creating new tasks
This article uses the following technologies:
Windows Mobile 6, MapPoint


Using MapPoint for Location
Tasks and Pocket Outlook
Application Architecture
Getting Nearby Points
Adding Tasks
Moving on down the Road

I recently movedto a new house, and some kind friends spent a full day helping me pack and unpack boxes, arrange for utility hookups, and all of the other important but tedious tasks of moving. On my way back from retrieving the last box at the old house, I nearly forgot to pick up dinner for my friends. I had set a reminder on my Windows Mobile phone, but it couldn't tell me when I was driving right past the most convenient take-out restaurant.

The solution I needed was a phone that informed me when I was near a place where I could complete said task. A time and location-appropriate reminder would have had us enjoying take-out rather than driving around an unfamiliar neighborhood after a long day of shifting boxes.

Windows Mobile provides many interfaces and capabilities that can help keep the device informed about its environment—where it is, whether it has a signal, how much of a signal, and so on. But how can these features be used in your applications? The most prominent and arguably useful of these capabilities is location awareness. This should enable you to create location-aware applications, ranging from the rather obvious satellite navigation program to the much more sophisticated task list that will be discussed here.

This article will look at the issues involved with using this capability and the additional code you need to write to develop useful applications. In this article, I will discuss the mobile application development environment and utilities, and show you how to build a location-aware task list application that can remind you of a task when and where it's appropriate.

Using MapPoint for Location

My location-aware task list application, named wheretodo, needs to perform several core tasks. It needs to get information about where the phone is located geographically. It also needs to store and monitor tasks. Furthermore, the application needs to know what shops and services are available near the phone's current location that could be used to solve a current task. Finally, it needs to provide alerts to the phone. The interface of the application is shown in Figure 1.


Figure 1 Wheretodo App

The first thing the app requires is geographical data. For the purpose of this article, I chose to use the Microsoft MapPoint Web service. This Web service is the underlying technology for Live Search Mapsand Virtual Earth and provides a search nearby service for Europe and the United States. The example code provided uses European map data settings; you will need to change this to make it work elsewhere.

MapPoint takes a GPS latitude and longitude and search codes for specific types of stores as its arguments. The position information can be provided by the FakeGPS utility when installed on an emulator or smartphone. (See the "FakeGPS" sidebar for more information about this utility.)

MapPoint provides an XML Web service with a SOAP API. The Web service is broken down into four main services: a common service, a find service, a render service, and a route service. The main service of interest to this application is the find service, but if you wanted to give directions to the user or a map, the other services could be used to extend the functionality.

The common service (CommonServiceSoap) contains classes, methods, and properties that are common to the find, route, and render services, or are basic utility functions.

You can use the find service (FindServiceSoap) to locate addresses, geographic entities, latitude and longitude coordinates, and points of interest (POI) from MapPoint Web service data. You can also parse addresses and return location information for a specified latitude and longitude.

You can use the render service (RenderServiceSoap) to draw maps of routes and locations, place pushpins, draw polygon regions, set the map size and map view, select points on a map, get location information about points and polygons on a map, and pan and zoom a rendered map.

The route service (RouteServiceSoap) generates routes, driving directions, and calculated route representations (used to render a highlighted route on the map) based on locations or waypoints, sets segment and route preferences, and generates map views of segments and directions.

A full set of object model class diagramsis on MSDN. MapPoint holds the data used for the find, route, and render services in a number of different data sources depending on geographic region or type of information required. You will be able to find a full range of MapPoint technical articleson using the service on MSDN.

Tasks and Pocket Outlook

The Pocket Outlook Object Model (POOM) allows you to add menus and functionality to the Tasks and Contacts applications in Windows Mobile and to manipulate their associated items and data. There are three main interfaces of interest to a location-aware application: IAppointment, ITask, and IContact.

IAppointment represents an appointment in the Calendar folder. An appointment object can represent a meeting, a one-time appointment, or a recurring appointment or meeting.

ITask represents an assigned, delegated, or self-assigned task to be performed within a specified time frame. Task items are contained within the Tasks folder.

IContact represents a contact in the Contacts folder. Its methods can be used to save, delete, duplicate, or display a contact. The IPOutlookItem­Collection interface can be used to add new contacts or to retrieve existing ones.

The sample application will be using ITask. (Functionally, it could use IAppointment, but that interface is not as well suited to the immediate needs of the application.) The POOM is similar to the desktop Outlook object model, and you can learn more about it on MSDN in the " Differences Between the Pocket Outlook Object Model and the Outlook Object Model" article.

Application Architecture

The location-aware application is made up of two chains of functions. The first is the system that monitors the current tasks and issues, as shown in Figure 2. Tasks are stored in a SQL Server­ Compact database table. In addition, a set of auxiliary data is stored within another table called geocache. Using the separate table is a means of limiting the amount of connectivity required, as I will explain later in this article.


Figure 2 Monitoring and Alerting of Location-Aware Tasks

The information for the points nearby is provided by the Micro­soft MapPoint Web service. There are different data sources in the MapPoint Web service for different parts of the world, and some have more capabilities than others. The data source used by the sample application is NavTech.EU. Once this information is gathered, some distance calculations can be performed and alerts issued, where applicable.

The second chain of events (see Figure 3) adds tasks to the Tasks list on your Windows Mobile device via the POOM. This framework also allows access to the calendar and SMS functions.


Figure 3 System Flow for Adding Tasks to the Wheretodo Application

Tasks and Cache represents the first part of the monitoring and alerting chain of events. The task manager simply gets a list of tasks from the POOM. It also manages the geocache, which addresses the issues with using Web services on potentially limited connectivity devices. The level of connectivity of the device can range from permanent connectivity to sparsely connected or no connection at all.

To cope with the large range of connectivity strength, you need a decent cache policy for the Web service data and a straightforward system that knows how to make the most of the connectivity. Although very complex scenarios could easily be imagined, a simple radius cache policy was established for the purpose of this article. For example, a query is placed to the MapPoint Web service looking for all Chinese take-out restaurants within a given radius from the current location, say 80 kilometers (km). Once you have gone 40 km in any one direction, a new search is issued. This is based on the principal that every query to the Web service is costly.

It also makes the assumption that the distance you travel away from the point where you entered the task is not likely to be greater than 40 km. As the distance used to control the actions of the cache is likely to vary from person to person and country to country, it is designed to be input by the user.

Logs of where queries have been run are stored in the geocache­log database and checked before any additional queries are made so that duplicate information is not requested from the Web service. It also provides the opportunity for the system to be pre-populated with a considerable volume of information.



FakeGPS Application

The Windows Mobile 6 SDKcontains a utility application called FakeGPS that lets you test your application with simulated GPS data. For information about installing and testing using FakeGPS, see the MSDN Library article " Using the Fake­GPS Utility."

FakeGPS reads a pre-recorded set of GPS instructions. The GPS data can be obtained from a real GPS device using a raw GPS data recorder. The resulting file is read by a FakeGPS device and can be re-run, simulating changing location data, for testing purposes. For example, I recorded a trip around London to gather data for my application and then re-enacted the trip through FakeGPS.

Getting Nearby Points

The next component defines how the geocache is populated. When the application needs to find a location, a GetNearByPOI function is called (see Figure 4). The code queries the MapPoint Web service. Note that the code shown here has been simplified for clarity and is different from that in the code download.

Figure 4 Getting Nearby Points of Interest

private void GetNearByPOI( string KeyWord, LatLong CurrentPosition) { FindServiceSoap findService = new FindServiceSoap(); FindNearbySpecification findNearBySpec = new FindNearbySpecification(); findService.Credentials = new System.Net.NetworkCredential(myUserName, myPassword); findService.PreAuthenticate = true; findNearBySpec.Distance = Convert.ToDouble(inputdistance.Text); findNearBySpec.LatLong = new LatLong(); findNearBySpec.LatLong.Latitude = CurrentPosition.Latitude; findNearBySpec.LatLong.Longitude = CurrentPosition.Longitude; findNearBySpec.Filter = new FindFilter(); //findNearBySpec.Filter.EntityTypeName = KeyWord; findNearBySpec.Filter.EntityTypeName = "FoodType3"; // SIC CODE findNearBySpec.DataSourceName = "NavTech.EU"; FindResults foundResults; foundResults = findService.FindNearby(findNearBySpec); string connectionString; string fileName = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\wheretodo.sdf"; string password = "sa"; connectionString = string.Format("DataSource=\"{0}\"; Password='{1}'", fileName, password); SqlCeConnection cn = new SqlCeConnection(connectionString); cn.Open(); SqlCeCommand cmd; //Loop Round and add it to the geocache foreach (FindResult fr in foundResults.Results) { //This needs to include LongLat in geocache string sql = "insert into geocache2 (POI_Name, POI_Address, POI_Tel, POI_Web, " + "POI_POST_ZIP, POI_Lat, POI_Long, POI_KeyWord) " + "values (@Name, @Address, @Tel, @Web, @POST_ZIP, '" + fr.FoundLocation.LatLong.Latitude.ToString() + "', '" + fr.FoundLocation.LatLong.Longitude.ToString() + "', '" + KeyWord.ToString() + "')"; cmd = new SqlCeCommand(sql, cn); cmd.Parameters.Add("@Name", SqlDbType.NVarChar, 255, "Name").Value = fr.FoundLocation.Entity.Properties[0].Value.ToString(); cmd.Parameters.Add("@Address", SqlDbType.NVarChar, 255, "Address").Value = fr.FoundLocation.Entity.Properties[1].Value.ToString() + fr.FoundLocation.Entity.Properties[2].Value.ToString(); cmd.Parameters.Add("@Tel", SqlDbType.NVarChar, 255, "Tel").Value = fr.FoundLocation.Entity.Properties[9].Value.ToString(); cmd.Parameters.Add("@Web", SqlDbType.NVarChar, 255, "Web").Value = ""; cmd.Parameters.Add("@POST_ZIP", SqlDbType.NVarChar, 255, "POST_ZIP").Value = fr.FoundLocation.Entity.Properties[7].Value.ToString(); cmd.ExecuteNonQuery(); //Update geocachelog sql = "insert into GeoCodeLog (Keyword, Lat, Long ) values ('" + KeyWord + "', '" + fr.FoundLocation.LatLong.Latitude.ToString() + "', '" + fr.FoundLocation.LatLong.Longitude.ToString() + "' )"; cmd = new SqlCeCommand(sql, cn); cmd.ExecuteNonQuery(); } }

Take a look at the section in which CurrentPos­ition.Lat­itude and CurrentPosition.Longitude are called. This is ultimately derived from the GPS Intermediate Driver, a software layer that sits between applications and the device driver for GPS hardware. This layer of abstraction allows applications to be written once and work with multiple GPS devices. The GPS Intermediate Driver API is exposed through a native code library. You can gain access to this library from managed code by using the sample that is included with the Windows Mobile 6 Professional SDK (see " Using the GPS Intermediate Driver from Managed Code)".

Once you have the current location and nearby POI that are relevant to the task, identified here by standard industrial classification (SIC) codes used in the Navtech.EU data source, you need to determine exactly how far these points are from your current location. I used the longitude and latitude values returned from the Web service and the GPS (in this case, FakeGPS); Figure 5shows how I converted these values to distance.

Figure 5 Computing the Distance

private double GetLatLongTuppleDistance( double Lat1, double Long1, double Lat2, double Long2) { //Convert Degress to Radians for Calculations double Lat1r = ConvertDegreesToRadians(Lat1); double Lat2r = ConvertDegreesToRadians(Lat2); double Long1r = ConvertDegreesToRadians(Long1); double Long2r = ConvertDegreesToRadians(Long2); // Spherical law of cosines formula—ignores the effect of hills double R = 6371; // Earth's radius (km) double d = Math.Acos(Math.Sin(Lat1r) * Math.Sin(Lat2r) + Math.Cos(Lat1r) * Math.Cos(Lat2r) * Math.Cos(Long2r—Long1r)) * R; //Returns distances in km return d; }

A spherical trigonometry function based on the spherical law of cosines (which generalizes the Pythagorean theorem) provides the function that translates latitude and longitude pairs into km distances. This obviously makes some massive assumptions about the things blocking where you are from the location you're trying to find. As the earth is not a perfect sphere, there will be errors in using these formulas. For miles, divide km by 1.609344 and, in case you're nipping out in your boat to get some bread, for nautical miles divide km by 1.852.

The final part of this chain of events is to issue the alert to the user if a solution to the task is found within a certain distance from your current location. As this distance is determined by the mode of transport—driving, walking, cycling, and so on—this has been left as an input for the user.

Adding Tasks

Of course, before the application can find a location, the user needs to add tasks to the mobile device. The POOM mirrors the Outlook object model, but its scope of functionality is reduced to accommodate the practical constraints of mobile devices.

Using the POOM, it is straightforward to modify and display appointment, task, and contact items, as well as manipulate the folders that contain them. Here's the code to create a task item:

OutlookSession outlooksession = new OutlookSession(); Task NewTask = new Task(); NewTask.Body = textBox2.Text.ToString(); string MyString = dateTimePicker2.Value.ToShortDateString() + " " + dateTimePicker1.Text.ToString(); DateTime MyDateTime = new DateTime(); MyDateTime = DateTime.ParseExact(MyString, "M/d/yy h:mm:ss tt", null); NewTask.DueDate = MyDateTime.ToUniversalTime(); NewTask.Subject = textBox1.Text.ToString(); outlooksession.Tasks.Items.Add(NewTask);

Various parameters can be altered to set the end date and the task body text and then add it to the POOM.

This component makes up the last of the two chains of components used to provide the functionality of the wheretodo application. The system UI itself is very simple and provides a means of setting all the relevant information and determining the SIC codes the application will be searching out. The overall application is simply wrapped in an infinite loop just to illustrate the use of location-aware applications. You could very easily add this as a background service to your mobile device to make it a more efficient and cleaner integration into the Windows Mobile 6 or Windows Mobile 5 environment.

Mobile Data Resources


Write Code Once for Both Mobile and Desktop Apps


Going Places: Adaptable Apps for Windows Mobile


Data Points: Accessing Data from a Mobile Application

Moving on down the Road

You've seen one type of location-aware device and a tool that eases the development of these applications. This basic concept of a location-aware task list could be easily extended for RFID.

There are improvements that can be made to this code that apply to any location-aware application. The biggest collection of these can be summarized by how the location awareness ties in with the other context-aware services that run on the majority of mobile phones. The tasks do not have an idea what else you are trying to do, only where you are. You might target tasks to both a time and a location so that they are triggered by you getting near something at a particular time (say, driving home from work). Even better, the task reminder would know that you have a meeting in 10 minutes, and it would also know that is not enough time to get stamps, even though you are passing the post office on the way to the meeting.

If you are interested in building a custom installer for this or your own newly updated location-aware application, see my article from the October 2007 issue of MSDN Magazine( Adjust Your Ring Volume For Ambient Noise).

I would like to dedicate this article to Tom Passey, a dear friend who, along with his wife, has looked after me on many occasions, providing great memories. Wish you all the best.

Christopher Mitchellfinished his PhD in machine learning and music/sound signal processing, was a Kauffman/NCGE fellow, and is currently undertaking a start-up in Cambridge UK. He is a part-time lecturer at Anglia Ruskin University, Cambridge, UK. You can contact Chris at