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

GPS Tracking with Windows Mobile 5.0+

0.00/5 (No votes)
15 Aug 2007 2  
Use a Windows Mobile Professional phone with a GPS receiver to create a simple SMS based location tracking program.

Screenshot - Title.png

Introduction

This program is a proof of concept for a larger system that I plan to build. Ultimately, I would like to have a system that allows users to opt in and out of letting their locations be known. The location information would be acquired through an application running on a Windows Mobile 5.0 (or later) device. Such a system has commercial applications (knowing where a delivery or service person is located) and personal applications (e.g.: you are heading to a friend's house and the friend would like to know how far away you are). In this prototype, my goal is to touch on some of the foundational technologies for the system.

For this proof of concept, I wanted to be able to acquire the GPS information from the GPS Intermediate Driver, and wanted a way to have a phone send this information either by request of the phone's owner or one of the owner's contacts. Thus, the fundamental technologies used here are:

  • GPS Intermediate Driver - gets GPS information in a way that won't interfere with other GPS applications.
  • MessageInterceptor - waits for location request and starts the application when one is received.

Required Tools

To run this code, you will need to have Visual Studio 2005 installed, and both the Windows Mobile 5.0 SDK and the Windows Mobile 6 Professional SDK. The 5.0 SDK is needed because I've set this project to target 5.0 devices. The code used for accessing the GPS device is part of the 6.0 SDK (though it runs just fine on 5.0 devices). I've included the compiled assembly for the GPS wrapper with my project, but not the source code. To see the source code for this wrapper, you must have the Windows Mobile Professional 6.0 SDK.

I would also suggest that you have a Windows Mobile 5.0 device to test the application with. You can use the emulators for testing the program. This program makes use of SMS messaging. Depending on your service plan with your phone company, you may have to pay fees for every message sent and received. I fall into this category, as at this point in time, available carriers here in the United States do not allow many phones to have unlimited text message subscriptions on the same phone line as a one that has an unlimited data subscription. Because of this, the emulators may be preferable for initial testing of the program. You can redirect the COM port of the emulated Windows Mobile device to an external GPS receiver connected to your PC, or you can use the "FakeGPS" program available in the Windows Mobile 6.0 SDK to also emulate a GPS receiver.

The Missing GPS Settings Icon

On phones with Windows Mobile 5 Professional and later (the phones with touch sensitive screens), there is an icon in the Settings menu that allows one to set the hardware port over which their GPS receiver communicates. On some rather popular Windows Mobile phones, this icon is missing. It is not erased. Rather, some OEMs saw fit to hide the icon. The icon can be restored by deleting the Registry keys [HKEY_LOCAL_MAHINE\ControlPanel\Settings\GPS Settings\Hide] and [HKEY_LOCAL_MAHINE\ControlPanel\Settings\GPS Settings\Redirect]. If you don't have a registry editor, you can delete these keys by running the GPS Icon Restoration Program attached to this article. Simply copy it to your phone and run it. It will display a message box letting you know that it was successful or that those keys do not exist. You may need to reset your phone after running this program, for the changes to take affect.

How Does this Program Work

When initially run, the owner of the phone is able to enter a pin that will be used to identify location request messages. When an SMS message is received, if it contains the PIN that the user selected, this program will be started up (if it is not already running) and the message will be passed to the program. All other messages will be handled as usual on the phone. When the message is received, the program reads the current GPS coordinates from the phone, and responds back to the sender with a link to a map on local.live.com showing the phone owner's current location.

Catching SMS Messages with the MessageInterceptor Class

As its name suggests, the MessageInterceptor class is used to capture incoming SMS messages and allow your code to act upon receiving the message. Rather than needing to manually check all of the messages yourself, you set up a message rule for the types of messages that you are interested in. Within this program, there is only one property on the class that we have interest in: MessageCondition.

The MessageCondition member is of a class by the same name, MessageCondition. The MessageCondition allows you to specify a string that will be searched for in the message. You can specify that the string must be at the beginning, end, or anywhere within the message, and you can specify whether or not the search is case sensitive. For this program, I've set the MessageCondition class to only search within the body of the message for the presence of your pin anywhere in the message.

_messageInterceptor.MessageCondition = new MessageCondition();
_messageInterceptor.MessageCondition.CaseSensitive = false;
_messageInterceptor.MessageCondition.ComparisonType = 
        MessagePropertyComparisonType.Contains;
_messageInterceptor.MessageCondition.ComparisonValue = this.txtPin.Text;
_messageInterceptor.MessageCondition.Property = MessageProperty.Body;

Once the condition is set, the MessageInterceptor only needs to be enabled, and an event handler must be given to it:

_messageInterceptor.EnableApplicationLauncher(ruleName);
_messageInterceptor.MessageReceived += _messageInterceptorEventHandler;

The user may have exited the program since the MessageInterceptor was created. If a message is received after exiting the program and if the user left the program in an enabled state, then the program will be automatically started. To catch messages that caused the program to start, we must create the MessageInterceptor class in the program's Load event. During load, the program checks to see if the application had registered to be automatically loaded up receiving a message. If that is the case, then the program creates a new MessageInterceptor and gives it an event handler. The application will then receive notification of that message through the event handler.

if (MessageInterceptor.IsApplicationLauncherEnabled(ruleName))
{
    _messageInterceptor = new MessageInterceptor(ruleName);
    _messageInterceptor.MessageReceived += 
      new MessageInterceptorEventHandler(_messageInterceptor_MessageReceived);
    txtPin.Text = _messageInterceptor.MessageCondition.ComparisonValue;
    this.chkFindMeEnabled.Checked = true;
}
else
{
    this.chkFindMeEnabled.Checked = false;
}

Obtaining the Current Location

The Intermediate GPS Driver handles the details of interfacing to the GPS hardware for us. I'm using a wrapper included in the Windows Mobile 6 SDK that simplifies the use of the driver. The code works well, and is easy to use, so I would encourage you to consider using it instead of creating your own GPS reading code. Initializing the GPS object can be done in a few lines of code:

gps = new Gps();            
gps.LocationChanged += 
  new LocationChangedEventHandler(gps_LocationChanged);
gps.Open();

The EventArgs received from the LocationChanged event contains more details than you'll probably ever need from the GPS receiver. I simply save the Position member from the EventArgs and update the _currentLocation object.

void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
    if (args.Position.LatitudeValid && args.Position.LongitudeValid)
    {
        currentPosition = args.Position;
        UpdatePosition();
    }
}

When the program no longer needs to use the GPS Receiver, a call to Gps.Close() is made to end the object's worker thread. Not doing this could cause the program to never terminate.

Sending a Message

Sending messages is straightforward. In the case of SMS messages, a new SMSMessage object is created with the receiver's number and the message text as its constructor arguments. Then, the object's Send() method is called to deliver the message. Since an SMS message cannot be more than 160 characters, the link sent in the SMS message only contains a user's coordinates and a pushpin.

It would not be practical to receive the SMS message containing the map link on a phone, so you may wonder why the program has this ability. You must remember that computers can also send SMS messages either through another application such as Live Messenger or through built-in hardware such as a GMS modem or CDMA modem.

public void SmsSendCoordinates(string to,GpsPosition pos)
{
    string message = String.Format(responseTemplate, 
                     pos.Latitude, pos.Longitude);
    SmsMessage sms = new SmsMessage(to, message);
    sms.Send();
    this.eventLog.Add(DateTime.Now, to, pos);
}

Sending e-mail messages is just as simple. Create a new email object, populate a subject and body, add an address to the "To" collection, and then call its Send() method. The Send() method for e-mail requires an argument that was not needed for SMS. That argument is the name of the mail account to use. On my phone, the available accounts are named "ActiveSync" and "MMS". Naturally, I would rather not use MMS since my phone service provider charges what I feel to be high tariffs for sending a message via MMS.

Since the 160 character limit is not applied against e-mails I am at liberty to place more information in the link. So when sending an e-mail the program may (Depending on the user's selected options) include custom text and an image for representing the user.

public void EmailSendCoordinates(string emailAddress, GpsPosition pos)
{
    string avatarUrl = string.Empty;
    string displayName = string.Empty;
    string customMessage=string.Empty;

    if(((_Settings.OptionFlags&OptionChangedFlags.Avatar)==
         OptionChangedFlags.Avatar)&& (_Settings.Avatar.Length>0)
     )
        avatarUrl=_Settings.Avatar;
    displayName = optionsUI.DisplayName;
    customMessage = optionsUI.CustomMessage;

    string message = String.Format(detailedResponseTemplate, 
                     pos.Latitude, pos.Longitude, 
                     Utility.UrlEncode(avatarUrl), Utility.UrlEncode
                     (displayName), Utility.UrlEncode(customMessage));
    EmailAccount account = 
      (new OutlookSession()).EmailAccounts[_Settings.EmailAccount];
    EmailMessage msg = new EmailMessage();
    msg.To.Add(new Recipient(emailAddress));
    msg.Subject = "My location";
    msg.BodyText = message;
    msg.Send(account);
    this.eventLog.Add(DateTime.Now, emailAddress, pos);
}

What's Next

There are quite a number of features I would like to add to this program. In the next revision, I plan to add a mapping control so that users can see each other's location from their phones. I may also add support for Windows Mobile 5 Standard Edition (the devices with no touch screens). To accomplish this, there needs to exist a web server. Once those two pieces are working, I plan to use the Windows Live Search and MapPoint APIs to provide functionality for finding points of interest and getting directions to them so that users can meet each other.

History

  • 15 August 2007 - Article published.

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