Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Track your position using a Windows Mobile 6 device

0.00/5 (No votes)
29 Dec 2008 1  
Track your geographical position using a Windows Mobile 6 device and some Google Map programming.

MobilePositionTracker/positiontrackermobile.JPG

Introduction

One of my hobbies besides programming for fun and my work is long-distance hiking. The favourite event of the year is the "Four Days Marches" in Nijmegen, the Netherlands. I have participated five times now, and it is really great fun to do.

One of the problems for the "supporting" people staying behind is to know where you are. You get called several times a day with the questions "where are you?" and "how long until the finish?". Well, having a mobile phone carrying a GPS and an Internet connection can solve that problem quite easily.

Binaries usage

All you need is:

  1. A WM6 SmartPhone with a GPS device on board and the possibility to connect to Internet.
  2. A PC connected to the Internet on the "home location".
  3. .NET CF 3.5 installed on the mobile phone.
  4. .NET 3.5 Framework installed on the PC.
  5. A Google Static Maps API key (distributed for free here).

The PC application

We will not dive into the details of the PC application, since that is not the subject of this article. It suffices to say that the program hosts a WCF web service, capable of consuming a set of coordinates. These coordinates are then used to call the Google Static Maps API to produce a map of the location denoted by the coordinates.

The web service's endpoint is at http://yourhost:xxx/services/positionservice.

When the program has ran once, it will have created a configuration file called AppConfig.xml. In this file, you can enter the details like hostname, port number, and the Google API key.

The mobile application

The mobile application is just an EXE which can be put on the mobile device using the usual mechanics of ActiveSync. There is no installer, so you will have to do it by hand. Once installed on the device, run the program once. In the folder where you put the EXE, you will now find AppConfig.xml, which houses the configuration.

Using the application

On the PC which will be used to track your position, startup the PositionTrackerPC program. Make sure that the configuration in the configuration file is correct. You may have to edit your firewall settings to open up the port you will use, and you may have to edit the NAT rules in your modem to get it working. I cannot help you configure that, each modem / firewall is different. So, now you have your position tracker ready running on the PC.

Now, fire up the position tracker program on the mobile device. Also here, make sure to enter the correct hostname and port number.

On the first tab, you can enter the hostname where the position tracker PC application runs, along with the port number used. Also, you enter your Google API key here (it is used on the second tab). If you are ready putting in configuration information, make sure to save it, or you will have to do it again! In the textbox, you can enter a remark, which will also show up at the PC application. Besides all this, some GPS information is shown concerning the number of satellites and the current location.

Pushing the "Send" button at the bottom will call the web service on your PC, and voila, your position will be shown!

MobilePositionTracker/positiontrackingPC.JPG

On the second tab of the application, as a bonus, you can also get the map of your current location. If the GPS is not functioning or present, the map of my location will be shown...

The internals of the mobile application

The mobile application is not very sophisticated, it is just a simple form with a tab control on it, housing two forms. There are three major technologies, interesting enough to be explained:

  1. Calling a WCF web service from a mobile device.
  2. Getting the GPS location from the GPS device.
  3. Showing a Google map using the found GPS coordinates.

Calling the WCF web service

Remember the web service endpoint from the PC application:

http://yourhost:xxx/services/positionservice

Let's, for the sake of this article, assume it is http://acme.com:8080/services/positionservice. Now, two problems arise: Visual Studio does not provide you with the tools to create a reference to the web service, and .NET 3.5 CF does not have the implementation of the ChannelFactory<TInterface> class.

So, how to do it then?

You will have to install the Power Toys for .NET Compact Framework 3.5. These tools include a command line tool called netcfSvcUtil.exe. This tool allows to generate the proxy for your web service and, in our case, is used as follows:

netcfSvcUtil.exe /language:cs http://acme.com:8080/services

This command will generate two files: PositionService.cs and CFClientBase.cs. Both of these files should be added to your project. In PositionService.cs, you must add a constructor for the PositionServiceClient to allow an endpoint URI to be passed in:

public PositionServiceClient(string endPointAddress) :
       this(CreateDefaultBinding(), 
       new System.ServiceModel.EndpointAddress(endPointAddress))
{
}

Now, you can create the PositionServiceClient using the dynamically constructed end point address from your configuration information.

//Calling it is now quite easy:
private void sendMenuItem_Click(object sender, EventArgs e)
{
    double latitude = 52.031694;
    double longitude = 5.165283;
    string uri = String.Format("http://{0}:{1}/services/PositionService", 
                               hostTextBox.Text, Convert.ToInt32(portTextBox.Text));
    PositionServiceClient client = new PositionServiceClient(uri);

    if (_position != null)
    {
        if (_position.LatitudeValid && _position.LongitudeValid)
        {
            latitude = _position.Latitude;
            longitude = _position.Longitude;
        }
    }
    client.SendPosition(latitude, longitude, remarksTextBox.Text);

    MessageBox.Show("Position sent!");
}

Getting the GPS location from the GPS device

Doing this is quite easy using the Microsoft supplied classes which wrap the native GPS API in WM6. I have included those classes in the application, and changed the namespace to match my application's one. No mistake here: all credits go to Microsoft for these very easy to use classes!

The initialization part is in the form's Load handler:

private void PositionSenderForm_Load(object sender, EventArgs e)
{
    _configuration = AppConfiguration.ApplicationConfiguration();
    
    hostTextBox.Text = _configuration.WebServiceHostName;
    portTextBox.Text = _configuration.PortNumber.ToString();
    googleAPIKey.Text = _configuration.GoogleMapAPIKey;
    
    if (!_gps.Opened)
    {
        _gps.Open();
        updateDataHandler = new EventHandler(UpdateData);
        _gps.LocationChanged += new LocationChangedEventHandler(_gps_LocationChanged);
    }
}

The call to Gps.Open turns on the GPS (if not already on) and starts looking for satellites. If the location changes, an event handler will be called to update the coordinates. It is as easy as that!

Showing a Google map using the found GPS coordinates

The last part concerns the display of a map using the GPS coordinates. Google exposes an API which makes it possible to get an image of the map centered around a set of latitude/longitude values, with a specified zoom value. A URL must be built for this using the following format:

String.Format(CultureInfo.InvariantCulture,
                    "http://maps.google.com/staticmap?center={0}," + 
                    "{1}&size={5}x{6}&markers={0},{1}," + 
                    "greenc&zoom={2}&maptype={3}&key={4}",
                    _coordinate.Latitude, _coordinate.Longitude, 
                    _zoomLevel, _mapType, _apiKey, _xSize, _ySize);

For this, the MapUrlBuilder class is used.

The code to retrieve the image is as follows:

MapUrlBuilder builder = new MapUrlBuilder();
builder.CenterCoordinate = coordinate;
builder.MapType = "mobile";
builder.ZoomLevel = 15;
builder.XSize = mapPictureBox.ClientRectangle.Width;
builder.YSize = mapPictureBox.ClientRectangle.Height;
builder.GoogleMapsAPIKey = _configuration.GoogleMapAPIKey;

LocationMap map = new LocationMap(builder.MapUrl);
mapPictureBox.Image = map.Map;

The LocationMap class retrieves the image as follows:

private Bitmap FromUrl(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    WebResponse response = request.GetResponse();
    Bitmap bmp = new Bitmap(response.GetResponseStream());
    return bmp;
}

For the complete code details, I will have to refer you to the supplied source.

Points of interest

Hopefully, I have given you some insight and some tooling to build your own great WM6 applications. I think it is a great platform which has lots of potential, especially when used with other .NET pillars like WCF.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here