Using Xamarin.Essentials we can retrieve device’s current Latitude and Longitude. It provides Geolocation
and Geocoding
using which we can get Location information along with the possible addresses for the provided Latitude and Longitude of the device. In this post we will create a simple Xamarin Forms application which we will retrieve:
- Latitude and Longitude – By using Geolocation class
- Addresses – By using Geocoding class.
First things first, install Xamarin.Essentials package in your project:
Android Project setup:
Android Manifest – Add following permissions and features:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.xamforms" android:installLocation="auto"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" /> <application android:label="XamForms.Android" android:theme="@style/MainTheme"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-feature android:name="android.hardware.location" android:required="false" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <uses-feature android:name="android.hardware.location.network" android:required="false" /> </manifest>
When you install the nuget package, permissions for getting the location services will be added in MainActivity.cs file as below, if they are not added please add it. Also Xamarin.Essentials
must be initialized in the OnCreate
method.
MainActivity.cs:
protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App()); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); }
iOS Project setup:
Info.plist must contain the NSLocationWhenInUseUsageDescription
key in order to access the device’s location. Open Info.plist editor and add:
Info.plist:
<key>NSLocationWhenInUseUsageDescription</key> <string>This app wants to know your current Location info.</string>
Now we will begin our actual Xamarin forms application coding. The app will contain two buttons. One will be for getting last known location and other will be for getting current location. Using the LatLong info received from both the processes we will try to obtain possible address matches by passing it to GeoCoding
class.
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XamForms.MainPage" Title="Xamarin Forms - My Location" Visual="Material"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="9*"/> <RowDefinition Height="1*"/> </Grid.RowDefinitions> <StackLayout Grid.Row="0" Padding="5"> <Label x:Name="lblLocationInfo" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" FontSize="16"/> </StackLayout> <StackLayout Orientation="Horizontal" Grid.Row="1" HorizontalOptions="Center" Spacing="5"> <Button x:Name="btnGetLastKnownLocation" Text="Get Last Location" BackgroundColor="#dbdbdb" HorizontalOptions="Center" Clicked="btnGetLastLocation_Clicked" VerticalOptions="Start" Padding="2"/> <Button x:Name="btnGetCurrentLocation" Text="Get Current Location" BackgroundColor="#dbdbdb" HorizontalOptions="Center" Clicked="btnGetCurrentLocation_Clicked" VerticalOptions="Start"/> </StackLayout> </Grid> </ContentPage>
The design is pretty simple. Just a Xamarin forms label control to display all the location and Latitude & Longitude related information. And two buttons at the bottom of the screen for both the processes respectively.
MainPage.xaml.cs:
using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xamarin.Essentials; using Xamarin.Forms; namespace XamForms { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } private async void btnGetLastLocation_Clicked(object sender, EventArgs e) { btnEnabler(false); try { var location = await Geolocation.GetLastKnownLocationAsync(); if (location != null) await GetLocation(location); else await DisplayAlert("Unknown", "Your Location is unknown", "Ok"); } catch (Exception ex) { await DisplayAlert("Error occurred", ex.Message.ToString(), "Ok"); } btnEnabler(true); } private async void btnGetCurrentLocation_Clicked(object sender, EventArgs e) { btnEnabler(false); try { var request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(20)); CancellationTokenSource cts = new CancellationTokenSource(); var location = await Geolocation.GetLocationAsync(request, cts.Token); if (location != null) await GetLocation(location); else await DisplayAlert("Unknown", "Your Location is unknown", "Ok"); } catch (Exception ex) { await DisplayAlert("Error occurred", ex.Message.ToString(), "Ok"); } btnEnabler(true); } public async Task GetLocation(Location location) { try { var locationInfo = $"Latitude: {location.Latitude}\n" + $"Longitude: {location.Longitude}\n"; lblLocationInfo.Text = locationInfo; var placemarks = await Geocoding.GetPlacemarksAsync(location.Latitude, location.Longitude); var placemark = placemarks?.FirstOrDefault(); if (placemark != null) { var geocodeAddress = "\n" + $"{ placemark.Thoroughfare}\n" + //Address $"{ placemark.SubLocality}\n" + //Address area name $"{placemark.Locality} {placemark.SubAdminArea}\n" + //CityName $"{placemark.PostalCode}\n" + //PostalCode $"{placemark.AdminArea}\n" + //StateName $"{placemark.CountryName}\n" + //CountryName $"CountryCode: {placemark.CountryCode}\n"; lblLocationInfo.Text += geocodeAddress; } else await DisplayAlert("Error occurred", "Unable to retreive address information", "Ok"); } catch (Exception ex) { await DisplayAlert("Error occurred", ex.Message.ToString(), "Ok"); } } public void btnEnabler(bool val) { btnGetCurrentLocation.IsEnabled = val; btnGetLastKnownLocation.IsEnabled = val; } } }
The GetLocation(Location location)
methods accepts a Location parameter using which we are getting LatLong
info. The location permissions is asked once you click any one of the buttons. The last location function (btnGetLastLocation_Clicked
) is used for getting the last known location, it is much faster as compared to getting live location of the device. This is done using Geolocation.GetLastKnownLocationAsync()
function. Also this fails if you have not used maps or location services on your device for a long time because there is no last known location. So it is important to check if the location is null or not.
The GeolocationRequest
class accepts two optional parameters: GeolocationAccuracy
and a Timespan
value, after which the request to timeout. Geolocation.GetLocationAsync()
accepts GeolocationRequest
and a CancellationToken parameters. CancellationToken is used for cancelling the operation to avoid it the device getting stuck if it is taking longer to query current location of the device. For both the operations the location value is being the GetLocation function which will get multiple possible addresses.
Also see:
Xamarin Forms – Performing Firebase database CRUD operation
Xamarin forms Creating Action Sheets
Xamarin forms MVVM Binding CommandParameter to Command
Xamarin forms SQLite database – Performing CRUD operations
Xamarin forms creating and using SQLite database
Xamarin forms using Google Maps
Xamarin forms using Camera – saving Images to Gallery
Xamarin Forms Creating a Simple ListView
Xamarin Forms MVVM ListView ItemSource Binding
Xamarin forms Create HTML formatted Label