- Xamarin.Mobile (the easy but suboptimal approach to geolocation),
- Google Play Services (for better results on Android) and
- SimpleLocation (for better results with less code).
Furthermore, we will solve two related tasks:
- converting an address into coordinates – also known as geocoding – and
- displaying an interactive map.
Xamarin.Mobile is a library for accessing common device functionalities like location, camera and contacts from shared code. It comes with an easy-to-use, platform-independent geolocation module. We don’t recommend using it in production code, since it doesn’t make use of the powerful location APIs of the Google Play services on Android. But in this chapter it will serve as a first reference solution, since getting the current GPS location is basically done in two to three lines of code.
We start by defining a public Geolocator object within the platform-independent App class.
public static Geolocator Geolocator;
Since the initialization method is slightly different for Android and iOS, we call it within the platform-specific code. In iOS’ FinishedLaunching we call
App.Geolocator = new Geolocator { DesiredAccuracy = 50 };
and in Android’s OnCreate we additionally need to pass the activity as context:
App.Geolocator = new Geolocator(this) { DesiredAccuracy = 50 };
Since iOS 8 we also need to add two items to the “Info.plist” file. We do so by either double-clicking the file from within Xamarin Studio and adding two strings within the “Source” view6, or editing the file with a text editor of our choice and adding the following two entries right before the closing dict tag:
...
<key>NSLocationAlwaysUsageDescription</key>
<string>Can we use your location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We are using your location</string>
</dict>
</plist>Within the App constructor we create a MainPage with one Label. The placeholder text indicates that the app is busy determining the location.
MainPage = new ContentPage {
Content = new Label {
Text = "Determining your location...",
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
},
};
Furthermore, we call a method GetPosition. This method is asynchronous and will continue running in a background thread after returning from the constructor.
GetPosition();
The GetPosition method itself asks the static Geolocator for the current position. We pass a timeout of 10 seconds or 10000 milliseconds. For asynchronous method calls we can specify an action or function to continue with: Here we refer to the Task object t. We check its state and display either an error message or the obtained coordinates. The DisplayAlert method will open a pop-up window with the title “Location”, the respective message text and an “Ok” button.
async void GetPosition()
{
await Geolocator.GetPositionAsync(10000).ContinueWith(t => {
if (t.IsFaulted || t.IsCanceled)
MainPage.DisplayAlert("Location", "Couldn't determine location", "Ok");
else
MainPage.DisplayAlert("Location", string.Format("Latitude: {0}\nLongitude: {1}",
t.Result.Latitude, t.Result.Longitude), "Ok");
}, TaskScheduler.FromCurrentSynchronizationContext());
}
- Xamarin.Mobile does not fuse different sources like GPS, Cell-ID and WiFi. Therefore, it lacks accuracy, speed and reliability.
- When asking for the current location, Xamarin.Mobile needs to startup the GPS sensor and determine a new initial location. In contrast, Google Play services access the system-wide location, which might already be known from a previous request and – if there wasn’t any major movement detected by the motion sensors – might still be sufficiently accurate. Thus, Google Play services are usually much faster.
- Since Google Play services can combine different sensors, they can yield location requests with low required accuracy with less power consumption. Thus, Google Play services increase battery life.