The article discusses how to capture location information on a mobile device and how to use this information for location-based services such as getting driving directions, create custom maps etc. The article also presents Resco.Location library that provides respective high-level .Net classes for Windows Mobile and Windows Phone 7 platforms.
Introduction
GPS applications in mobile devices are becoming popular nowadays and have a wide range of applicability. Examples of popular utilization of mobile GPS services include for instance:
- Logistics - tracking of drivers, trucks and shipments
- Touristics - customer navigation to hotels, tourists can track most popular attractions
- Fleet location - tracking of ships, calculating the estimated time of arrival etc.
- Person tracking - tracking of location of salespeople in the field etc.
Modern mobile devices are often location-aware. For example all Windows Phone 7 phones contain a GPS receiver. On the other hand there exist location-based services – web services that can convert raw GPS information into useful content such as maps, addresses, driving directions etc. All these services together are usually denoted as map services.
There exist various implementations of map services. Perhaps the best known examples represent Google Maps and Bing Maps. Map services are rather complex and their use is highly non-trivial.
The article starts from explaining location basics - GPS coordinates and their relation to geographical maps. In the next part we’ll discuss Google Maps vs. Bing Maps – both the possibilities and limitations. In the final part we’ll present Resco.Location library that provides high-level interface for using GPS data and location-based services.
The library is part of Resco MobileForms Toolkit and is currently supported on two platforms – Windows Mobile and Windows Phone 7.
Prerequisites
The target audience is a C# .NET programmer. Knowledge of Silverlight is not required.
Low Level GPS Data
Geographic coordinate System
Geographic coordinates describe every location on the earth by two numbers:
- Latitude measures the angle from the equator towards the North or the South Pole. (Equator latitude is zero.)
- Longitude represents the angle in the east-west direction from the reference meridian (Prime meridian) passing near Greenwich.
In the following we'll use the term GPS coordinates instead of longer latitude/longitude coordinate system. Following picture (taken from Wikipedia) shows GPS coordinates.
Getting GPS Coordinates
The Global Positioning System (GPS) is a global navigation satellite system that provides reliable location and time information. It is maintained by the United States government and is freely accessible by anyone with a GPS receiver.
GPS receiver calculates its position from the signals sent by GPS satellites. (Four or more satellites are used to compute the location.) GPS receiver reports also altitude, i.e. elevation above the see level.
Except positional data, low-level GPS software in mobile phones can deliver additional information such as
- Course (WP7 uses internal compass for this purpose)
- Speed (Computed from the received GPS data)
- Time stamp of the generated information
Availability of the GPS information on the phone
WP7 has built-in GPS receiver. The system API (GeoCoordinateWatcher class) lets you optionally select low-precision data, in which case the signals coming from the cellular network are used instead of GPS receiver.
This method provides less accurate results, but is more energy-efficient.
GPS and Resco.Location Library
GpsDevice class provides the main interface for receiving GPS information. You can start/stop data receiving and react on the PositionChanged event. WP7 users will find this interface remarkably similar to the built-in GeoCoordinateWatcher class. Indeed, it is. The purpose of this class is the unification of the code base across different platforms.
GpsTracking class can be used to obtain smoothed polyline that describes your movement during the period when the tracking was activated.
Receiving GPS signals is not enough. You have to present it to the user somehow, i.e. show it on the map or describe it in understandable form. This can be done by using Geo services supported by Resco.Location library as discussed in the rest of this article.
Location-based services
GPS coordinates and maps
The surface of the earth is approximately an ellipsoid. Maps, as we all know them, represent planar projection of the earth surface. Maps commonly use UTM (Universal Transverse Mercator) coordinate system. UTM is not a single map projection but a series of projections, each one valid for a local zone. There are sixty such zones and these zones partially overlap.
Conversions between GPS and UTM coordinates are only approximate and the error increases towards the zone boundaries. Different UTM zones use different GPS/UTM conversion formulas.
The lesson to be taken:
You cannot precisely show GPS point on the map without knowing how the map was constructed. (I.e. to which UTM zone it belongs to.)
The author made a personal experience in trying to construct GPS tracking system - displaying GPS coordinates of a moving car on a city map. With wrong UTM formulas the cars were moving parallel to the roads, whereby the errors were much larger than the GPS receiver accuracy.
Google and Bing map services discussed later offer a partial solution: They not only offer the map, but also draw the points of interest on this map. In other words, they solve the complex UTM/GPS conversions for you.
This is enough for applications such as route planning or even GPS tracking with low refresh rate. However, if you need real-time GPS tracking or you need to minimize net traffic (maps are images), you have no other choice but to delve into complex UTM topics.
Web map services
These services deliver maps and related data (such as GIS data, f.e. hydrological data, land evaluation...) over the web.
You should be aware of the disadvantages/problems related to web maps:
- Reliability of the internet and web servers.
- Web maps need relatively high bandwidth.
- Limited screen space
- Many web maps are of poor quality (region-dependent)
- Copyright and privacy issues
There are many web map services often providing rather different services; a nice comparison can be found here: http://en.wikipedia.org/wiki/Comparison_of_web_map_services.
Web map services supported by Resco.Location Library
At present Resco.Location library supports Bing maps and Google maps services. Alternative providers such as Yahoo or OpenStreetMap may be added later.
You have to select the provider (Google or Bing) and then start to use high-level .Net classes. Apart from minor differences both providers offer identical services.
As far as the maps are concerned Resco.Location provides only static maps. These maps are delivered as raster images (png/jpg/gif) and they can be combined with additional information - markers (the figure below shows a marker positioned at four locations) or highlighted route.
Besides their core functionality (maps), Google and Bing provide additional services. Two of these services are supported by Resco.Location library:
- Routing determines a route between given locations. Routing is done for driving/walking/bicycling and can be optimized to minimize cost/traffic/distance. You can optionally provide locations to be visited during the route - so called way points. Routing can be provided in textual form (as a series of instructions such as "turn left") or in visual form (showing the route on the map).
- Geocoding is the process of converting between civic addresses such as "221B Baker Street, London" (yes, Sherlock Holmes) and geographic coordinates, such as in this case
Latitude: 51.523700; Longitude: -0.158600
While civic addresses are better suited for reports, GPS points can be easily shown on the map by placing a marker, for example.
Do not try manipulate the maps yourself (for example by drawing a marker) - you would encounter all kinds of problems:
- Reliability of the map information
- GPS/UTM conversion errors
- Legal problems
The maps API is quite powerful and can do many things for you. (Even if things such as fast interactive GPS tracking are not among them.)
Conditions for using Maps API
Even if the services are free at the first sight, it is not quite true. Both Google and Microsoft impose limitations, conditions and paid services.
Using Google Maps Web Services
Resco.Location covers 3 services:
- Google Static Maps API (downloading map images)
- Google Geocoding API (translation between GPS addresses and civic addresses)
- Google Directions API (requesting routing directions)
Elevation and places APIs are not covered. Deprecated services are unsupported as well - Google Geocoding V2 API, f.e.
Following restrictions apply (for ordinary users):
- 1000 unique (different) image requests per viewer per day.
- Geocoding API: 2500 requests per day
- Directions API: 2500 requests per day, with up to 8 intermediate waypoints
Additionally:
- The maps may only be displayed within browser content (Use of static maps outside of the browser is not allowed.)
- Directions/Geocoding results may only be used to display the results in relation to a Google map; unrelated uses are prohibited.
- Directions API generates copyrights which must be displayed to the user in some fashion.
There is another formal criterion:
Requests (maps/geocode/georoute) are encoded into an URL that is sent to respective web service. These URLs are restricted to 2048 characters in size (before URL encoding). You may easily violate this limit when requesting too many markers, for example.
Google Maps API Premier
You can purchase Google Maps API Premier with several advantages:
- Service Level Agreement provides 99.9% uptime guarantee
- Price is based on the number of map views and starts at $10/year.
- Https support (unsupported by Resco.Location)
Premier API limitations (Higher limits can be purchased.):
- Geocoding API: 100,000 requests per day
- Directions API: 100,000 requests per day and a maximum of 23 waypoints per request
- Maps: Image display outside viewer allowed.
After you purchase Google Maps API Premier, you’ll receive Google API key that need to be used with all requests. (See ServiceSettings class.)
Using Bing Maps Web Services
Bing Maps API represents numerous interfaces. One of them - Bing Maps REST Services - is used in Resco.Location library. (Another interesting example is Bing Maps Silverlight Control available f.e. on Windows Phone 7.)
You must have a Bing Maps Developer Account to get a Bing Maps Key for your application. This key is included in every location/route/mapping request and is used by Microsoft to count the transactions. (See ServiceSettings class.)
Microsoft imposes rather liberal limits on the free transactions, i.e.
- 50,000 transactions per day
- 500,000 transactions per year
Additionally:
- You have to display Bing logo and copyrights.
- “Real-time” navigation is forbidden
- You may not integrate Bing maps with other map platforms (i.e. use either Bing or Google, but not both)
(Full Terms of use for Bing Maps (http://www.microsoft.com/maps/product/terms.html) are too complex to be reproduced here.)
Higher limits and more liberal conditions can be negotiated.
Resco.Location Library
In the following we’ll present main classes implemented in Resco.Location library. Class descriptions provided are rather schematic — written so that you can easily get an idea what is offered. All unneeded information is stripped off. (For example the keyword public is omitted, properties are listed by name only etc.)
Service implementation scheme
All service classes (GeoCode, GeoRoute, GeoMap) follow the same scheme:
- They let the user setup the request
- The request is translated into an URL
- The URL is sent to the respective web service
- The service response is parsed and translated into user-understandable form
All service classes implement event-based asynchronous pattern with multiple concurrent calls allowed. Synchronous pattern is implemented for WM platform only.
Here is the pattern used for all service classes:
class SomeService
{
...
void GetXXXAsync( ...parameters..., object userState)
event EventHandler<GetXXXCompletedEventArgs> GetXXXCompleted;
#if !SILVERLIGHT
GeoPoint GetXXX(...parameters...)
#endif
}
class GetXXXCompletedEventArgs : AsyncCompletedEventArgs
{
....
bool Cancelled Exception Error Object UserState }
Namespace Resco.Location
The namespace contains basic classes used by other more specialized namespaces.
struct GeoDistance
{
GeoDistance(double meters)
double Meters, Kilometers, Feet, Yards, Miles, NauticalMiles operators <, <=, >, >=, ==, !=, +, -, *, /
string ToString() }
class GeoPoint
{
GeoPoint(GeoPoint p)
GeoPoint(double lat, lon)
double Latitude, Longitude
GeoPoint Move(lat, lon) GeoDistance GetDistanceTo(GeoPoint other)
GeoPoint(string str)
GeoPoint(string lat, string lon)
string ToString( eGPSFormat fmt, string delimiter) }
class GeoArea
{
GeoArea( GeoPoint southWest, northEast)
GeoPoint SouthWest, NorthEast
GeoDistance Width/Height GeoPoint CenterPoint
bool IsEnclosing( point | area) void EnlargeArea( point | area) void InflateArea( ... ) }
class GeoPolyline
{
GeoPolyline( string polyline )
GeoPolyline( IEnumerable points )
string Polyline List<GeoPoint> Points GeoDistance Length }
Namespace Resco.Location.GPS
The namespace provides classes working with GPS receiver. The API is modeled by GPS classes built-in in Windows Phone 7.
class GeoPosition : GeoPoint
{
DateTime TimeStamp double Altitude, Course, Speed, HorizontalAccuracy, VerticalAccuracy
}
class GpsDevice : IDisposable
{
GeoPosition Position GeoPositionStatus Status
PositionChanged StatusChanged
static GpsDevice Create()
static GpsDevice Create(GeoCoordinateWatcher watcher, bool dispose)
bool Start();
void Stop();
bool WaitForLocation(int timeout) }
class GpsTracking : IDisposable
{
GpsTracking()
GpsTracking(GpsDevice device, bool dispose)
TimeSpan MinimalTimeDifference GeoDistance MinimalDistance double RouteAccuracy
bool Start()
void Stop()
List<GeoPosition> TrackList GeoPolyline Polyline
TrackListChanged StatusChanged }
Namespace Resco.Services
Namespace contains service-oriented classes used by individual services.
enum eServiceProvider
class Address
{
Address(string country, string city, string street, string streetNum)
string StreetNumber, Street, City, Region, Country, CountryCode, PostalCode
string ToString() }
class ServiceRequestException : Exception
class ServiceSettings
{
static ServiceSettings Instance
string BingApiKeyl string GoogleApiKeyl
eServiceProvider DefaultProvider eUnitSystems DefaultUnitSystem string Language
}
Namespace Resco.Services.GeoCode
Class GeoCode provides the translation between GPS locations and civic addresses. Each translation direction represents a separate request.
class GeoCode
{
eServiceProvider ServiceProvider
void GetAddressAsync(GeoPoint location, object userState)
event EventHandler<GetAddressCompletedEventArgs> GetAddressCompleted;
GeoPoint Location GeoArea ViewPoint eGeoPrecision LocationPrecision
void GetLocationAsync(Address address, object userState)
event EventHandler<GetLocationCompletedEventArgs> GetLocationCompleted;
Address Address eGeoPrecision LocationPrecision GeoArea ViewPoint string FormattedAddress string EntityType
Address GetAddress(GeoPoint location)
GeoPoint GetLocation(Address address)
}
Namespace Resco.Services.GeoRoute
Class GeoRoute provides high-level API for routing service. The remaining classes are used to describe routing result.
enum eTravelModes
class GeoRouteResult
{
List<GeoRouteLeg> RouteLegs
string Copyrights }
class GeoRouteLeg
{
string StartAddress, EndAddress
GeoRouteSummary Summary
GeoPoint EndLocation
GeoPolyline Polyline
List<ItineraryItem> ItineraryItems
}
class ItineraryItem
{
eCompassDirection Direction eTravelModes TravelMode
eIconType IconType GeoRouteSummary Summary
GeoPolyline Polyline
string Instructions
}
class GeoRouteSummary
{
GeoPoint StartLocation
GeoDistance Distance
TimeSpan Duration
GeoArea Bounds
}
class GeoRoute
{
RouteOptions
{
eWayType AvoidWayType eTravelModes TravelMode eUnitSystems Units eRouteOptimization Optimization
bool RequirePathPoints }
eServiceProvider ServiceProvider;
void GetRouteAsync( Address src, Address dst, object userState, params Address[] waypoints)
void GetRouteAsync( GeoPoint src, GeoPoint dst, object userState, params GeoPoint[] waypoints)
event EventHandler<GetRouteCompletedEventArgs> GetRouteCompleted
GeoRouteResult Route
GeoRouteResult GetRoute(Address src, Address dst, params Address[] waypoints)
GeoRouteResult GetRoute(GeoPoint src, GeoPoint dst, params GeoPoint[] waypoints)
}
Namespace Resco.Services.Map
Class GeoMap provides high-level API for downloading static map images. The remaining classes are used to describe supplementary map content.
Note that there are substantial differences between the setup of Google and Bing maps.
class GeoMapPath
{
GeoMapPath(GeoRouteResult route)
Color RouteColor Color MapFill int RouteWeight
GeoMapPath(GeoPolyline polyline)
}
class GeoMapMarkers
{
GeoMapMarkers( Color col, size, label, params locations[] )
string IconUrl
GeoMapMarkers( int markerType, label, params locations[] )
}
class GeoMap
{
eServiceProvider ServiceProvider
List<GeoMapMarkers> Markers GeoMapPath Path
Options {
Size ImageSize eImgFormat Format eMapType MapType object Center int Zoom GeoArea ViewPoint }
void DownloadMapAsync(object userState)
event EventHandler<DownloadMapCompletedEventArgs> DownloadMapCompleted;
Stream ImageStream
ImageSource Image Bitmap Image
string URL void ShowInBrowser()
Stream DownloadMap()
}
How to implement GPS tracking – Sample Code
Below we’ll demonstrate how to build a WP7 application that track your movement and shows the tracked route on the map. The code is simplistic, i.e. all checks etc. were stripped off.
Minimalistic MainPage.xaml contains
- TextBlocks GPS status and last received position
- Button for showing the tracked route on the map
<phone:PhoneApplicationPage>
<StackPanel Margin="12,0,12,0">
<TextBlock x:Name="statusText" />
<TextBlock x:Name="positionText" />
<Button Content="Show Map" Click="btnShowMap"/>
</StackPanel>
</phone:PhoneApplicationPage>
What is included in the MainPage.cs code:
- Setup of the GPS provider. We select Google because we want to show tracking result (i.e. a general polyline) on the map. Bing can’t do that.
- Setup of the GpsTracking object
- GPS tracking starts when the page is loaded and stops when the page unloads
- Status and position changes are shown in the UI
- The map showing tracked route is shown when the [Show Map] button is pressed.
public partial class MainPage : PhoneApplicationPage
{
GpsTracking gpsTracking = new GpsTracking()
{
MinimalDistance = new GeoDistance(10),
MinimalTimeDifference = new TimeSpan(0, 0, 1)
};
public MainPage()
{
ServiceSettings.Instance.DefaultProvider = eServiceProvider.Google;
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
this.Unloaded += new RoutedEventHandler(MainPage_Unloaded);
gpsTracking.StatusChanged += new EventHandler<StatusChangedEventArgs>(gpsTracking_StatusChanged);
gpsTracking.TrackListChanged += new EventHandler(gpsTracking_TrackListChanged);
}
void MainPage_Unloaded(object sender, RoutedEventArgs e)
{
gpsTracking.Start();
}
void MainPage_Unloaded(object sender, RoutedEventArgs e)
{
gpsTracking.Stop();
gpsTracking.Dispose();
}
void gpsTracking_TrackListChanged(object sender, EventArgs e)
{
var list = gpsTracking.TrackList;
string txt = list.Count > 0 ? list[list.Count - 1].ToString() : "NoData";
positionText.Text = txt; }
void gpsTracking_StatusChanged(object sender, StatusChangedEventArgs e)
{
statusText.Text = e.Status.ToString();
}
private void btnShowMap(object sender, RoutedEventArgs e)
{
gpsTracking.Stop();
var map = new GeoMap() { Path = new GeoMapPath(gpsTracking.Polyline) };
map.ShowInBrowser();
}
}
About Resco.Location Library
The library is part of Resco MobileForms Toolkit that can be downloaded from http://www.resco.net/developer/mobileformstoolkit. Sample code can be downloaded from the same location.
The Toolkit is provided for four platforms - Windows Phone 7, Windows Mobile, Android and iOS. At the time of this writing the Location library was available for Windows Phone 7 and Windows Mobile platforms.
About the Author
Jan Slodicka. Programming for over 30 years. Covered several desktop platforms and programming languages. Since 2003 working for Resco on mobile technologies – Palm OS, Windows Mobile, now Windows Phone 7.
You can contact me at jano at resco.net or through Resco forums.
Resco MobileForms Toolkit - Windows Phone 7 Edition can be downloaded from http://www.resco.net/developer/mobilelighttoolkit. The Toolkit contains a set of useful controls that simplify Windows Phone 7 programming. Besides WP7, there is also Windows Mobile, Android and iOS edition.
Resco is a company with a long tradition of mobile programming covering many platforms and both end-user applications and developer tools.