You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI获取精准位置问题:轨迹不准确及未移动时异常漂移

位置轨迹绘制问题求助

我用以下代码获取用户当前位置:

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)
        {
            // 无法获取位置
            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);
        }
    }
}

使用该类时,我会对比新旧位置,只有不同时才通过API上传到服务器:

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保存新位置信息
}
else
{
    // 无操作
}

每10秒共享一次位置,并用以下代码绘制轨迹:

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);

XAML地图布局:

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

现在遇到两个问题:

  1. 部分设备轨迹绘制不准确,另一部分设备运行正常;
  2. 部分设备中用户未移动,但轨迹仍显示变化,想了解用户静止时是否会出现位置坐标变更。

用户未移动时的错误轨迹截图:
错误轨迹1
错误轨迹2
错误轨迹3


问题原因及解决方案

用户未移动却出现位置变更的原因

这是定位技术的正常误差导致:

  • GPS、基站定位本身存在精度范围(GPS一般3-10米,基站定位误差更大),哪怕用户静止,每次获取的坐标也会在真实位置周围小幅波动;
  • 代码直接对比字符串形式的经纬度,小数点后几位的微小差异都会被判定为“位置变化”,进而上传并绘制无效轨迹。

轨迹不准确的优化方案

  1. 设置位置变化距离阈值
    不要直接对比经纬度字符串,计算两次位置的实际直线距离,只有超过设定阈值(比如5米)时,才判定为有效移动:

    // 将存储的字符串转为数值类型
    if (double.TryParse(latitude, out double newLat) && double.TryParse(longitude, out double newLng)
        && double.TryParse(oldLatitude, out double oldLat) && double.TryParse(oldLongitude, out double oldLng))
    {
        // 计算两点距离(单位:米)
        var distance = Location.CalculateDistance(new Location(newLat, newLng), new Location(oldLat, oldLng), DistanceUnits.Meters);
        // 设定5米为有效移动阈值
        if (distance > 5)
        {
            Preferences.Default.Set("oldLatitude", latitude);
            Preferences.Default.Set("oldLongitude", longitude);
            // 调用上传API
        }
    }
    
  2. 优化定位请求逻辑

    • 若场景允许,可将GeolocationAccuracy.High调整为Medium,平衡精度与设备性能;
    • 增加位置精度过滤,只保留精度符合要求的坐标:
      if (location != null && location.Accuracy <= 10) // 只保留精度在10米以内的位置数据
      {
          Preferences.Default.Set("latitude", location.Latitude);
          Preferences.Default.Set("longitude", location.Longitude);
          Utility.DebugAndLog("Values:>>", $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
      }
      
  3. 修复代码逻辑漏洞
    获取位置的代码中,if (location != null)未加大括号,导致设置经度的代码永远执行,哪怕location为null,会引发空引用异常,修正如下:

    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}");
    }
    
  4. 轨迹绘制优化

    • 当前步长计算可能跳过过多有效点,导致轨迹失真,若坐标量不大可直接去掉步长,添加所有点;
    • 对轨迹点使用道格拉斯-普克算法做抽稀处理,过滤冗余的波动点,让轨迹更贴合真实路径。

内容的提问来源于stack exchange,提问作者Matthew Pans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:27:04