There are a couple of very smart and very useful projects I’ve come across for working with location data in the WP7 emulator. One is Peter Torr’s “Mock Location APIs from my Mix10 Talk” and the other is “No Device? No GPS? No Matter!” from @keyboardP (sorry, I don’t know your real name).

What Peter did for his Mix10 talk was to mock out much of the System.Device.Location namespace. This allows you to simply add a reference to his library and, by switching namespaces from System.Device.Location to MixDemoHelpers.Location, control the location data being received by your app running on the emulator. The only downside – you need to define the Lat/Lon data up front.

What @keyboardP did was write a client app that uses a Bing Maps control to generate Lat/Lon data and expose this via a WCF service. His demo also includes a WP7 app that consumes this data but it consumes the WCF service directly, rather than using the WP7 location API.

So we have a mock for the location API and a method to generate Lat/Lon data that we can control by simply moving your mouse over a map. Wouldn’t it be nice to combine the two?

 

The above video shows a simple WP7 location demo I used at a recent event – it simply uses the location API to display the current Lat/Lon. By default in the emulator this does very little but I had already incorporated Peter Torr’s mock classes so I could “pretend” to be in Las Vegas (his demo was at Mix after all). I modified Peter’s mock classes to access @keyboardP’s WCF service providing real-time Lat/Lon data. This gives me mock classes to use with the emulator and gives me control of the location data they’re providing at runtime.

The video shows my WP7 app in front of @keyboardP’s client app (incorporates the Bing Map control and WCF service). Watch the video and you’ll see an initial Lat/Lon displayed (this is a Vegas Lat/Lon, for ease I only changed the PositionChanged event to access the WCF service). You’ll then see the Lat / Lon on the emulator update regularly and pick up the Lat/Lon from the Bing Map.

In other words I now have a WP7 app running in the emulator using the standard location API (with just a namespace switch to mock out the real classes) which I can drive with Lat/Lon data from a map.

If you want to get this working, go and download the code from both projects I mention above.

  • Into your WP7 app solution, add the MixDemoHelpers project from Peter Torr and add a reference to it from your WP7 app project
  • You can switch between real and mock API by switching out your System.Device.Location using statement for a MixDemoHelpers.Location one
  • Make a call to LasVegasLocationData.Setup() when you’re using the mock API to initialise things
  • (Actually I seem to recall a couple of very minor things have changed in the location API since Peter published his code – it should be very easy to update it, I managed it okay :) )
  • In the GeoCoordinateWatcher mock class, there’s a FakeLocationLoop() method. I realise it’s a complete hack but here’s what I changed in that method (look for the while (isRunning) loop as a point of reference):
      GPSSimClient proxy = new GPSSimClient();
      proxy.GetGPSDataCompleted += 
          new EventHandler<GetGPSDataCompletedEventArgs>(GetGPSDataCompleted);

      while (isRunning)
      {
          proxy.GetGPSDataAsync();

        //if (InMotionPositions != null && InMotionPositions.Count > index)
        //{
        //  currentLocation = InMotionPositions[index++];
        //}
        //ChangePositionWithEvent(currentLocation);
        Thread.Sleep(TimeToChangePosition);
      }

      ChangeStatusWithEvent(GeoPositionStatus.Initializing);
    }

    void GetGPSDataCompleted(object sender, GetGPSDataCompletedEventArgs e)
    {
        GeoCoordinate currentLocation = 
            new GeoCoordinate(e.Result[0], e.Result[1]);
        ChangePositionWithEvent(currentLocation);
    }
  • Do feel free to do something a little more robust :)
  • Open @keyboardP’s VEMap/Simulators solution (you’ll need to run VS elevated for this to work)
  • Modify Form1.cs. Find Form1_Load() and change the webBrowser1.Navigate URI to the correct URI for wherever you’ve downloaded the project (for me it’s file:///C:\Users\mormond\Desktop\GPS Sim - keyboardP\GPS Sim - keyboardP\VEMap\VEMap\map.html)
  • Start the project running to make the WCF service available
  • Use SlSvcUtil.exe (in C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Tools) to create a proxy class for the service
  • Add the generated proxy class  (GPSSim.cs) and the ServiceReferences.ClientConfig file to the MixDemoHelpers project
  • Add the ServiceReferences.ClientConfig file to your WP7 project (otherwise expect a runtime exception that the file isn’t included in the XAP)
  • You should be good to go

There’s no check in the mock class as things stand to ensure that the new location is more than the threshold distance from the old – that should be a relatively simple enhancement. And as I mentioned previously, I’ve only updated the PositionChanged event. You may want to update the mock classes to use the WCF service for the initial position as well.

Thanks to both Peter and @keyboardP.