Location information in your Windows Phone applications is managed by the Windows Phone Location Service, which allows you to use your device's Wi-Fi, GPS, or cellular network to determine location. As we discussed earlier, Microsoft lays strong emphasis on location, so much that it is a basic hardware requirement for all Windows Phones.
The main class that handles the Location Service is the GeoCoordinateWatcher
class. Perform the following steps and make sure you import the DLL in your solution:
PhoneApp1
as shown in the following screenshot: System.Device
reference as shown in the following screenshot: MainPage.xaml.cs
file import the following location namespace by using the using
keyword:using System.Device.Location;
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
Now that we know how to import the Location Service, let us now learn how to start using it.
To start the Location Service, the Start
method of the GeoCoordinateWatcher
class needs to be called. Continuing from our previous example, open the MainPage.xaml.cs
file and create a variable of type GeoCoordinateWatcher
in your MainPage()
constructor as:
var locationManager = new GeoCoordinateWatcher();
And declare the locationManager
variable in the global scope, by declaring it as a field right after the class initialization.
public partial class MainPage : PhoneApplicationPage { GeoCoordinateWatcher locationManager;
Now we call the Start
method as:
locationManager.Start();
To quickly get the latitude/longitude data (assuming the application can access location information), add two TextBlock
elements to your main XAML file (MainPage.xaml
) and name them latitudeText
and longitudeText
respectively. This is shown in the following screenshot:
Add the following code to MainPage.xaml.cs
in the MainPage()
constructor, after the locationManager.Start()
line:
latitudeText.Text= locationManager.Position.Location.Latitude.ToString("0.000"); longitudeText.Text = locationManager.Position.Location.Longitude.ToString("0.000");
Running the example in the emulator will produce the following result:
In the previous example, we assumed that the GPS or other location-determining hardware was ready to return the location information as soon as we requested it. However, this is not true in a real-world scenario, GPS devices may take a few seconds to get a good signal in a remote place. The GeoCoordinateWatcher
class implements the StatusChanged
event to handle this, returning the status (of type GeoPositionStatus)
, which could be any of the following based on the device's status:
Status |
Description |
---|---|
|
The Windows Phone Location Service is trying to acquire data |
|
The Location Service is ready with data |
|
Service disabled or not supported |
|
The device can fetch location information, but no data available (due to poor reception or otherwise) |
We define the StatusChanged
event handler function immediately after creating the locationManager
variable in the MainPage()
constructor as:
locationManager.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs> (locationManager_getStatus);
locationManager_getStatus
is our custom-defined function where we handle the statuses for the GeoCoordinateWatcher
class, which is defined as:
void locationManager_getStatus(object sender, GeoPositionStatusChangedEventArgs e) { switch (e.Status) { case GeoPositionStatus.Initializing: statusText.Text = "Loading ..."; break; case GeoPositionStatus.Ready: latitudeText.Text = locationManager.Position.Location.Latitude.ToString(); longitudeText.Text = locationManager.Position.Location.Longitude.ToString(); statusText.Text = "Location Available"; break; case GeoPositionStatus.Disabled: statusText.Text = "Disabled"; break; case GeoPositionStatus.NoData: statusText.Text = "No Data at this time"; break; }// end of switch } // end of locationManager_getStatus
In most cases, you should be able to get the location; however, there could be two reasons for location being disabled:
We cannot help in the first case; however, in the second case we can use the Permission
property of the GeoCoordinateWatcher
class. Modify the GeoPositionStatus.disabled
case from the previous example to the following one:
case GeoPositionStatus.Disabled: if (locationManager.Permission == GeoPositionPermission.Denied) { statusText.Text = "User has disabled location settings"; } else statusText.Text = "Disabled"; break;
To display the status of the Location Service, we added one more TextBlock
to the UI (via the MainPage.xaml
file) and named it statusText
, and placed it near the footer of the app as shown in the following screenshot:
There is no way to disable the location settings on the emulator yet, so we tested this example on the phone itself. The following screenshot shows how the application will behave with location settings turned off (see Chapter 1, The Location-based World on how to turn location settings on/off):
You can also specify accuracy for the GeoCoordinateWatcher
object by passing an argument of type GeoPositionAccuracy
. There are two accuracy levels:
We will modify our GeoCoordinateWatcher
object to use the high accuracy level by using the following arguments at the object creation time:
locationManager = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
It is also a good practice to use the Stop()
method wherever possible to turn off the Location Service when not needed, to maximize the battery life of the device.
You can find this example project in the code files for the book under Chapter 2
, titled PhoneApp1
.
In our previous example we saw how to fetch the location data when the service is ready. We saw a simple way to access the location data from the GeoCoordinateWatcher
object; however, there is another event exposed by the GeoCoordinateWatcher
class – the PositionChanged
event that is fired when the location service detects a change in the position of the Windows Phone device.
Let us now build our Hello Location example that uses both the StatusChanged
and PositionChanged
events:
Hello Location
as shown in the following screenshot: System.Device
reference library to your project and import it in your MainPage.xaml.cs
file by adding the following line:using System.Device.Location;
GeoCoordinateWatcher locationManager;
TextBlocks
, two for the latitude/longitude labels and two more for their respective values. The following screenshot shows how our UI should now look: Margin
property. Name the elements properly so that you can access them in your code.<Grid x:Name="ContentPanel" Grid.Row="1"Margin="12,0,12,0"> <TextBlock Height="30" HorizontalAlignment="Left" Margin="10,575,0,0" Name="statusText" Text="Status: " VerticalAlignment="Top" Width="444" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,118,0,0" Name="latitudeLabel" Text="Latitude: " VerticalAlignment="Top" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,175,0,0" Name="longitudeLabel" Text="Longitude: " VerticalAlignment="Top" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="155,118,0,0" Name="latitudeText" Text="Value" VerticalAlignment="Top" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="155,175,0,0" Name="longitudeText" Text="Value" VerticalAlignment="Top" /> <Button Content="Start" Height="72" HorizontalAlignment="Left" Margin="0,35,0,0" Name="startButton" VerticalAlignment="Top" Width="160" Click="startButton_Click" /> <Button Content="Stop" Height="72" HorizontalAlignment="Left" Margin="0,256,0,0" Name="stopButton" VerticalAlignment="Top" Width="160" Click="stopButton_Click" /> </Grid>
Click="startButton_Click"
and Click="stopButton_Click"
code in XAML shown in the previous step. These are click event functions that are called when the user hits the start and stop buttons. From your UI, double-clicking on the buttons will open up the code editor for modifying these function calls.private void startButton_Click(object sender, RoutedEventArgs e) { locationManager.Start(); } private void stopButton_Click(object sender, RoutedEventArgs e) { locationManager.Stop(); }
StatusChanged
event of the GeoCoordinateWatcher
class earlier, now we will implement the PositionChanged
event. In your MainPage()
constructor, after creating an object locationManager
of type GeoCoordinaeWatcher
, we declare the PositionChanged
event as:locationManager = new GeoCoordinateWatcher(GeoPositionAccuracy.High); locationManager.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs> (locationManager_getStatus); locationManager.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>> (locationManager_getPosition);
locationManager_getPosition
function as:void locationManager_getPosition(object sender, GeoPositionChangedEventArgs<GeoCoordinate>newLoc) { latitudeText.Text = newLoc.Position.Location.Latitude.ToString(); longitudeText.Text = newLoc.Position.Location.Longitude.ToString(); }
locationManager_getPosition
function exposes the device's current location via the<GeoCoordinate>
parameter in the function declaration. We use this in our implementation via the newLoc
variable, and pass the current latitude and longitude values to the respective TextBlock
for display.You can find this example project in the code files for the book under Chapter 2
, titled Hello Location.
We used the Nokia Lumia 800 skin on our emulator; get yours from http://www.developer.nokia.com/Community/Wiki/How_to_use_skins_of_Nokia_Lumia_on_Windows_Phone_emulator. For multiple skin choices head to http://wp7emuskinswitcher.codeplex.com/, which allows you to switch skins for a couple of phones, and yes there is a white Nokia Lumia 800 skin too!
Having played with our Hello Location example app, let us now dig more into the Windows Phone location simulator to understand how we can simulate location data in our application.
Open the Hello Location example and run it in Windows Phone Emulator. The Emulator comes with an Additional Tools sidebar, which is activated from the Emulator home screen via the Additional Tools button (>>) as shown in the following screenshot:
Within the Additional Tools sidebar open, select the Location tab, as shown in the following screenshot:
When you run the Hello Location example, the values you get for the latitude/longitude pair by default would be 47.64483 and -122.141197, which is Microsoft's Redmond office. Playing around with the location simulator and the Hello Location application side by side, you will find the location updates happen immediately on the Hello Location app.
You can also search for places using the search input box. A cool feature of the simulator is the ability to save the maps points you have added on the maps. This can be loaded back from the saved file or by manually adding points to simulate your app behavior, by loading the saved locations file (Locations.xml
in our case) and hitting the Play all points button as shown in the following screenshot:
The Location.xml
file is shown as follows; we added two different cities' latitude/longitude data to it and checked the Hello Location app against it.
<?xml version="1.0" encoding="utf-8"?> <WindowsPhoneEmulator xmlns= "http://schemas.microsoft.com/WindowsPhoneEmulator/2009/08/ SensorData"> <SensorData> <Header version="1" /> <GpsData latitude="48.8596434322625" longitude="1.49173867702484" /> <GpsData latitude="48.645964012732" longitude="1.49723184108734" /> <GpsData latitude="19.0227245363093" longitude="72.8413543701172" /> </SensorData> </WindowsPhoneEmulator>
3.137.166.124