Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article describes how you can use the .NET Multi-platform App UI (.NET MAUI) IGeolocation interface. This interface provides APIs to retrieve the device's current geolocation coordinates.
The default implementation of the IGeolocation
interface is available through the Geolocation.Default property. Both the IGeolocation
interface and Geolocation
class are contained in the Microsoft.Maui.Devices.Sensors
namespace.
Get started
To access the Geolocation functionality, the following platform-specific setup is required:
Coarse or fine ___location permissions, or both, must be specified and should be configured in the Android project.
Additionally, if your app targets Android 5.0 (API level 21) or higher, you must declare that your app uses the hardware features in the manifest file. This can be added in the following ways:
Add the assembly-based permission:
Open the Platforms/Android/MainApplication.cs file and add the following assembly attributes after
using
directives:[assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)] [assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)] [assembly: UsesFeature("android.hardware.___location", Required = false)] [assembly: UsesFeature("android.hardware.___location.gps", Required = false)] [assembly: UsesFeature("android.hardware.___location.network", Required = false)]
If your application is targeting Android 10 - Q (API Level 29 or higher) and is requesting
LocationAlways
, you must also add this permission request:[assembly: UsesPermission(Android.Manifest.Permission.AccessBackgroundLocation)]
- or -
Update the Android Manifest:
Open the Platforms/Android/AndroidManifest.xml file and add the following in the
manifest
node:<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_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" />
If your application is targeting Android 10 - Q (API Level 29 or higher) and is requesting
LocationAlways
, you must also add this permission request:<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
- or -
Update the Android Manifest in the manifest editor:
In Visual Studio double-click on the Platforms/Android/AndroidManifest.xml file to open the Android manifest editor. Then, under Required permissions check the permissions listed above. This will automatically update the AndroidManifest.xml file.
Tip
Be sure to read the Android documentation on background ___location updates, as there are many restrictions that need to be considered.
Get the last known ___location
The device may have cached the most recent ___location of the device. Use the GetLastKnownLocationAsync() method to access the cached ___location, if available. This is often faster than doing a full ___location query, but can be less accurate. If no cached ___location exists, this method returns null
.
Note
When necessary, the Geolocation API prompts the user for permissions.
The following code example demonstrates checking for a cached ___location:
public async Task<string> GetCachedLocation()
{
try
{
Location ___location = await Geolocation.Default.GetLastKnownLocationAsync();
if (___location != null)
return $"Latitude: {___location.Latitude}, Longitude: {___location.Longitude}, Altitude: {___location.Altitude}";
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (FeatureNotEnabledException fneEx)
{
// Handle not enabled on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to get ___location
}
return "None";
}
Depending on the device, not all ___location values may be available. For example, the Altitude property might be null
, have a value of 0, or have a positive value indicating the meters above sea level. Other values that may not be present include the Speed and Course properties.
Get the current ___location
While checking for the last known ___location of the device may be quicker, it can be inaccurate. Use the GetLocationAsync method to query the device for the current ___location. You can configure the accuracy and timeout of the query. It's best to the method overload that uses the GeolocationRequest and CancellationToken parameters, since it may take some time to get the device's ___location.
Note
When necessary, the Geolocation API prompts the user for permissions.
The following code example demonstrates how to request the device's ___location, while supporting cancellation:
private CancellationTokenSource _cancelTokenSource;
private bool _isCheckingLocation;
public async Task GetCurrentLocation()
{
try
{
_isCheckingLocation = true;
GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
_cancelTokenSource = new CancellationTokenSource();
Location ___location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);
if (___location != null)
Console.WriteLine($"Latitude: {___location.Latitude}, Longitude: {___location.Longitude}, Altitude: {___location.Altitude}");
}
// Catch one of the following exceptions:
// FeatureNotSupportedException
// FeatureNotEnabledException
// PermissionException
catch (Exception ex)
{
// Unable to get ___location
}
finally
{
_isCheckingLocation = false;
}
}
public void CancelRequest()
{
if (_isCheckingLocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false)
_cancelTokenSource.Cancel();
}
Not all ___location values may be available, depending on the device. For example, the Altitude property might be null
, have a value of 0, or have a positive value indicating the meters above sea level. Other values that may not be present include Speed and Course.
Warning
GetLocationAsync can return null
in some scenarios. This indicates that the underlying platform is unable to obtain the current ___location.
Listen for ___location changes
In addition to querying the device for the current ___location, you can listen for ___location changes while an app is in the foreground.
To check to see if the app is currently listening for ___location changes, there's a IsListeningForeground property you can query. Once you're ready to start listening for ___location changes you should call the StartListeningForegroundAsync method. This method starts listening for ___location updates and raises the LocationChanged event when the ___location changes, provided that the app is in the foreground. The GeolocationLocationChangedEventArgs object that accompanies this event has a Location property, of type Location, that represents the new ___location that's been detected.
Note
When necessary, the Geolocation API prompts the user for permissions.
The following code example demonstrates how to listen for a ___location change, and how to process the changed ___location:
async void OnStartListening()
{
try
{
Geolocation.LocationChanged += Geolocation_LocationChanged;
var request = new GeolocationListeningRequest((GeolocationAccuracy)Accuracy);
var success = await Geolocation.StartListeningForegroundAsync(request);
string status = success
? "Started listening for foreground ___location updates"
: "Couldn't start listening";
}
catch (Exception ex)
{
// Unable to start listening for ___location changes
}
}
void Geolocation_LocationChanged(object sender, GeolocationLocationChangedEventArgs e)
{
// Process e.Location to get the new ___location
}
Error handling can be implemented by registering an event handler for the ListeningFailed event. The GeolocationListeningFailedEventArgs object that accompanies this event has an Error property, of type GeolocationError, that indicates why listening failed. When the ListeningFailed event is raised, listening for further ___location changes stops and no further LocationChanged events are raised.
To stop listening for ___location changes, call the StopListeningForeground method:
void OnStopListening()
{
try
{
Geolocation.LocationChanged -= Geolocation_LocationChanged;
Geolocation.StopListeningForeground();
string status = "Stopped listening for foreground ___location updates";
}
catch (Exception ex)
{
// Unable to stop listening for ___location changes
}
}
Note
The StopListeningForeground method has no effect when the app isn't listening for ___location changes.
Check if ___location services are enabled
The Geolocation class has a read-only IsEnabled
property that can be used to determine if ___location services have been enabled on the device.
Accuracy
The following sections outline the ___location accuracy distance, per platform:
Important
iOS has some limitations regarding accuracy. For more information, see the Platform differences section.
Lowest
Platform | Distance (in meters) |
---|---|
Android | 500 |
iOS | 3000 |
Windows | 1000 - 5000 |
Low
Platform | Distance (in meters) |
---|---|
Android | 500 |
iOS | 1000 |
Windows | 300 - 3000 |
Medium (Default)
Platform | Distance (in meters) |
---|---|
Android | 100 - 500 |
iOS | 100 |
Windows | 30-500 |
High
Platform | Distance (in meters) |
---|---|
Android | 0 - 100 |
iOS | 10 |
Windows | <= 10 |
Best
Platform | Distance (in meters) |
---|---|
Android | 0 - 100 |
iOS | ~0 |
Windows | <= 10 |
Detecting mock locations
Some devices may return a mock ___location from the provider or by an application that provides mock locations. You can detect this by using the IsFromMockProvider on any Location:
public async Task CheckMock()
{
GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium);
Location ___location = await Geolocation.Default.GetLocationAsync(request);
if (___location != null && ___location.IsFromMockProvider)
{
// ___location is from a mock provider
}
}
Distance between two locations
The CalculateDistance method calculates the distance between two geographic locations. This calculated distance doesn't take roads or other pathways into account, and is merely the shortest distance between the two points along the surface of the Earth. This calculation is known as the great-circle distance calculation.
The following code calculates the distance between the United States of America cities of Boston and San Francisco:
Location boston = new Location(42.358056, -71.063611);
Location sanFrancisco = new Location(37.783333, -122.416667);
double miles = Location.CalculateDistance(boston, sanFrancisco, DistanceUnits.Miles);
The Location(Double, Double, Double) constructor accepts the latitude and longitude arguments, respectively. Positive latitude values are north of the equator, and positive longitude values are east of the Prime Meridian. Use the final argument to CalculateDistance
to specify miles or kilometers. The UnitConverters class also defines KilometersToMiles and MilesToKilometers methods for converting between the two units.
Platform differences
This section describes the platform-specific differences with the geolocation API.
Altitude is calculated differently on each platform.
On Android, altitude, if available, is returned in meters above the WGS 84 reference ellipsoid. If this ___location doesn't have an altitude, 0.0
is returned.
The Location.ReducedAccuracy property is only used by iOS and returns false
on all other platforms.