MAUI: How to fetch accurate current location?

Sreejith Sreenivasan 941 Reputation points
2025-01-22T15:21:36.2+00:00

I am using below codes to fetch the current location of a user:

public class GetCurrentLocations
{
    private CancellationTokenSource _cancelTokenSource;
    private bool _isCheckingLocation;
    public async Task GetCurrentLocation()
    {
        try
        {
            _isCheckingLocation = true;

            GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.High, TimeSpan.FromSeconds(10));

            _cancelTokenSource = new CancellationTokenSource();

            Location location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);

            if (location != null)
                Preferences.Default.Set("latitude", location.Latitude);
                Preferences.Default.Set("longitude", location.Longitude);
            Utility.DebugAndLog("Values:>>", $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
        }
        catch (Exception ex)
        {
            // Unable to get location
            Utility.SendCrashReport(ex);
        }
        finally
        {
            _isCheckingLocation = false;
        }
    }

    public void CancelRequest()
    {
        try
        {
            if (_isCheckingLocation && _cancelTokenSource != null && _cancelTokenSource.IsCancellationRequested == false)
                _cancelTokenSource.Cancel();
        }
        catch (Exception exception)
        {
            Utility.SendCrashReport(exception);
        }
    }
}

And I use it like below and send the location details to our server using an API. First I check the old location detail and new location details are same. If same no action and if not same I will send that location details to our server.

GetCurrentLocations getcurrentLocations = new GetCurrentLocations();
await getcurrentLocations.GetCurrentLocation();
string latitude = Preferences.Default.Get("latitude", "");
string longitude = Preferences.Default.Get("longitude", "");
string oldLatitude = Preferences.Default.Get("oldLatitude", "");
string oldLongitude = Preferences.Default.Get("oldLongitude", "");
if (latitude != oldLatitude && longitude != oldLongitude)
{
    Preferences.Default.Set("oldLatitude", latitude);
    Preferences.Default.Set("oldLongitude", longitude);
    //API to save the new location details
}
else
{
    //No action
}

On each 10 seconds I share the location details to our server and using these location details I draw a line on map using below code:

Polyline polyline = new Polyline
{
    StrokeColor = Color.FromArgb("#ea4333"),
    StrokeWidth = 5,
};
int step = Math.Max(1, validCoordinates.Count / 50);
for (int i = 0; i < validCoordinates.Count; i += step)
{
    polyline.Geopath.Add(validCoordinates[i]);
}
map.MapElements.Add(polyline);

<maps:Map 
    x:Name="map" 
    VerticalOptions="FillAndExpand" 
    HorizontalOptions="FillAndExpand"
    MapClicked="MapClicked"
    IsScrollEnabled="True"
    IsTrafficEnabled="False"
    MapType="Street"
    IsZoomEnabled="True">
</maps:Map>

My problem are:

This is working fine on some devices and in some devices the lines are not accurate.

In some devices the user is not moved but lines are showing. If the user is not moved, is there any location change happen?

Following are some of the inaccurate line screenshots and on all these cases the user is not moved.

12User's image

UPDATE

  1. Set a Threshold for Significant Change

I compare the new location values with the previously fetched ones and determine if the change exceeds a certain threshold (e.g., 10 meters). If the change is below the threshold, ignore the new location.

public class GetCurrentLocations
{
    private CancellationTokenSource _cancelTokenSource;
    private bool _isCheckingLocation;
    private Location _lastKnownLocation;
    public async Task GetCurrentLocation()
    {
        try
        {
            _isCheckingLocation = true;

            GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(10));
            _cancelTokenSource = new CancellationTokenSource();

            Location location = await Geolocation.Default.GetLocationAsync(request, _cancelTokenSource.Token);

            if (location != null)
            {
                if (_lastKnownLocation == null || IsSignificantChange(_lastKnownLocation, location))
                {
                    _lastKnownLocation = location;
                    Preferences.Default.Set("latitude", location.Latitude);
                    Preferences.Default.Set("longitude", location.Longitude);
                    Utility.DebugAndLog("Values:>>", $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
                }
            }
        }
        catch (Exception ex)
        {
            // Unable to get location
            Utility.SendCrashReport(ex);
        }
        finally
        {
            _isCheckingLocation = false;
        }
    }

    private bool IsSignificantChange(Location oldLocation, Location newLocation)
    {
        const double thresholdInMeters = 10; // Adjust threshold as needed
        double distanceInKm = Location.CalculateDistance(oldLocation, newLocation, DistanceUnits.Kilometers);
        double distanceInMeters = distanceInKm * 1000;
        return distanceInMeters > thresholdInMeters;
    }

    public void CancelRequest()
    {
        try
        {
            if (_isCheckingLocation && _cancelTokenSource != null && !_cancelTokenSource.IsCancellationRequested)
            {
                _cancelTokenSource.Cancel();
            }
        }
        catch (Exception exception)
        {
            Utility.SendCrashReport(exception);
        }
    }
}

But I am facing the same issue after implement this too. The location is changing when the user is not moving and lines are visible on the ap. Any other solutions?

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,900 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.