Simulating location in the emulator

Microsoft provides a GPS emulator that allows you to simulate location in the emulator.

TipTip:

The Mango release of the Windows Phone Developer Tools contains location functionality in the emulator.

Using location in the emulator

By using the GPS emulator, you can use location in your emulator. To accomplish this, perform the following steps:

  1. Download the Windows Phone GPS Emulator recipe from Microsoft.
  2. Unzip the files.
  3. Browse to and open the solution file at GpsEmulator_AppHubReady\GpsEmulator\GPSEmulator.sln.
  4. You may need to use a different port for the GPS Emulator if 8192 is already in use on your machine. To do so, search for 8192 in the entire solution and replace it with a different port number, such as 8198.
  5. The are some enhancements that make the GPS Emulator more useful for testing certain applications. The GPS Emulator doesn't currently use CultureInfo.Invariant on to and from string parsing; as a result, it will fail in many regions. The GPS Emulator as it is downloaded doesn't transmit speed, accuracy, or heading. In addition, the GPS Emulator constantly updates the location instead of providing updates once per second (as the device codes). If these are required for your testing, make the following updates in the solution:
    1. Open the GpsEmulator_AppHubReady\GpsEmulator\GpsEmulator\MainWindow.xaml.cs file, go to line 389, find the following code:
      directionalMarkerCurrentLocation.X += dLat * simulationSpeed;
      directionalMarkerCurrentLocation.Y += dLng * simulationSpeed;
      this.Dispatcher.Invoke((Action)(() =>
      {
          transmittedLocation = String.Format("{0}, {1}", currentPosition.X, currentPosition.Y);
          tbCurrentPosition.Text = String.Format("{0} : {1}", currentTime, transmittedLocation);
      
      and replace it with the following:
      directionalMarkerCurrentLocation.X += dLat * simulationSpeed;
      directionalMarkerCurrentLocation.Y += dLng * simulationSpeed;
      this.Dispatcher.Invoke((Action)(() =>
      {
          double heading = 90 - Math.Atan2(dLat, dLng) * 180 / Math.PI;
          if (heading < 0) heading += 360;
          transmittedLocation = String.Format(System.Globalization.CultureInfo.InvariantCulture,
              "{0}, {1}, {2}, {3}", currentPosition.X, currentPosition.Y, simulationSpeed, heading); 
          tbCurrentPosition.Text = String.Format("{0} : {1}", currentTime, transmittedLocation);
      
      NoteNote:

      This will not provide the actual speed, rather it provides a value for the speed.

    2. Open the GpsEmulator_AppHubReady\GpsEmulator\GpsEmulatorClient\GeoCoordinateWatcher.cs file. Go to line 23, find the definition for currentLocation, and add the following lines after that (starting on line 24):
      System.Windows.Threading.DispatcherTimer timer;
      static Random r = new Random();
      
    3. Find the GeoCoordinateWatcher constructor that starts with public GeoCoordinateWatcher(GeoPositionAccuracy desiredAccuracy). Update that method to match the following code:
      public GeoCoordinateWatcher(GeoPositionAccuracy desiredAccuracy)
      {
          this.desiredAccuracy = desiredAccuracy;
          timer = new System.Windows.Threading.DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
          timer.Tick += new EventHandler(timer_Tick);
      }
      
    4. Add the following timer_Tick method after the constructor that was just updated:
      void timer_Tick(object sender, EventArgs e)
      {
          if (client != null)
              client.GetCurrentPositionAsync();
      }
      
    5. Find the GeoCoordindateWatcher's Start method. At the end of the try block, find client.GetCurrentPositionAsync(); and comment out that line.
    6. At the end of the GeoCoordinateWatcher's Start method, outside of the if statement, add the following:
      if (!timer.IsEnabled)
          timer.Start();
      
    7. Find the GeoCoordinateWatcher's Stop method, and before the Dispose call, stop the timer as follows:
      timer.Stop();
      
    8. Find the GeoCoordinateWatcher's client_GetCurrentPositionCompleted event, then find the following code:
      string[] coordinates = e.Result.Split(latLngSeparator);
      if (coordinates.Length == 2)
      {
          double lat, lng;
          if (Double.TryParse(coordinates[0], out lat) && double.TryParse(coordinates[1], out lng))
      
      and replace it with the following:
      string[] coordinates = e.Result.Split(latLngSeparator);
      if (coordinates.Length >= 2)
      {
          double lat, lng;
          double heading = 0;
          double speed = 0;
          if (coordinates.Length > 2)
              double.TryParse(coordinates[2], out speed);
          if (coordinates.Length > 3)
              double.TryParse(coordinates[3], out heading);
          if (Double.TryParse(coordinates[0], out lat) && double.TryParse(coordinates[1], out lng))
      
    9. In the same event, find the following code:
      currentLocation = new GeoPosition<GeoCoordinate>(DateTimeOffset.Now, gc);
      GeoPositionChangedEventArgs<GeoCoordinate> gpcea = new GeoPositionChangedEventArgs<GeoCoordinate>(currentLocation);
      Status = GeoPositionStatus.Ready;
      
      and replace it with the following:
      currentLocation = new GeoPosition<GeoCoordinate>(DateTimeOffset.Now, gc);
      currentLocation.Location.Course = heading;
      currentLocation.Location.Speed = speed;
      currentLocation.Location.HorizontalAccuracy = r.NextDouble() * 100;
      GeoPositionChangedEventArgs<GeoCoordinate> gpcea =
          new GeoPositionChangedEventArgs<GeoCoordinate>(currentLocation);
      Status = GeoPositionStatus.Ready;
      
    10. At the end of the same event, find the line client.GetCurrentPositionAsync(); and comment it out.
  6. Compile the solution.
  7. Run the created Windows Phone GPS Emulator as admin.
  8. Close the GPSEmulator solution.
  9. In the solution for your Windows Phone application that makes use of location, which you want to test using the location simulation in the emulator, add references to System.Device and the GpsEmulatorClient assembly that was created by the GpsEmulatorClient project in the GPSEmulator solution.
  10. Go to the XAML file where your application makes use of the GpsLayer and add the following namespace definition:
    xmlns:location2 = "clr-namespace:GpsEmulatorClient;assembly=GpsEmulatorClient"
    
  11. Go to the GpsLayer used in the Map element in your XAML, and override the GeoPositionWatcher property of the layer as follows:
    <esriDS:GpsLayer ID="gpsLayer" >
        <esriDS:GpsLayer.GeoPositionWatcher>
            <location2:GeoCoordinateWatcher/>
        </esriDS:GpsLayer.GeoPositionWatcher>
    </esriDS:GpsLayer>
    
  12. Run the application.
  13. In the GPSEmulator, click the map to move the location to new points, and notice how it updates the location in your application. Read GPS Emulator_Final.docx that is included with the downloaded GPS Emulator in the GpsEmulator_AppHubReady folder for additional details on working with the emulator.

    In addition to setting point locations, you can create and playback tracks, as well as change the simulation speed.
    Screen shot of GPS simulation.
1/23/2012