mcpField
M
maui-geolocation

maui-geolocation

github.com/davidortinau开发17645 次安装16 周前更新
代码仓库

关于 maui-geolocation

面向 .NET MAUI 定位功能的实用指南,说明权限处理、精度与电量取舍、取消操作、平台差异和持续跟踪清理。

主要功能

  1. 01取消与超时处理指南
  2. 02精度与电量的取舍
  3. 03平台权限处理
  4. 04最后已知位置的回退方案
  5. 05持续跟踪的清理

适用场景

  1. 01为定位请求添加超时
  2. 02处理近似位置或定位不可用
  3. 03构建依赖位置的安全检查
  4. 04停止持续跟踪以避免 GPS 持续运行

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-geolocation

安装后在 Claude Code 中输入/maui-geolocation确认已加载。

附带文件references/geolocation-api.md

详细介绍

.NET MAUI 地理定位

重要:始终传入 CancellationToken

如果 GPS 已关闭、设备位于室内,或权限处于待处理状态,GetLocationAsync 可能会无限期挂起。始终设置超时。

// ❌ Hangs forever if no GPS fix is available
var location = await Geolocation.Default.GetLocationAsync(
    new GeolocationRequest(GeolocationAccuracy.High));

// ✅ Times out after 30 seconds
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var location = await Geolocation.Default.GetLocationAsync(
    new GeolocationRequest(GeolocationAccuracy.High), cts.Token);

精度与电量消耗的权衡

使用满足功能需求的最低精度。更高的精度会显著加快电量消耗,尤其是在 Android 上。

使用场景建议精度
城市级定位 / 天气Lowest 或 Low
附近搜索 / 门店查找Medium
逐向导航High 或 Best

平台注意事项

iOS 14 降低的精度

用户可以授予“近似”位置权限(精度 > 1 km)。应用会收到位置信息,但对需要高精度的功能可能毫无用处。

  • 检查 location.Accuracy——值 > 100 m 可能表示精度已降低。
  • 使用 GeolocationRequest.RequestFullAccuracy,并提供与 Info.plist 中 NSLocationTemporaryUsageDescriptionDictionary 匹配的键,以提示用户授予完整精度。
Android:安全敏感流程中的模拟位置
// ⚠️ Always check in security-sensitive flows (e.g., geofence, check-in)
if (location.IsFromMockProvider)
{
    // Reject — user is spoofing location
}
Android:Altitude 为 0.0 并不代表海平面

当 GPS 没有气压传感器时,一些 Android 设备会将 Altitude 返回为 0.0。应将 0.0 视为**“未知”**,而不是海平面。

Android 10+:后台位置需要单独申请权限

必须将 ACCESS_BACKGROUND_LOCATION 与前台权限分开申请,并且会触发单独的系统对话框。在申请前台权限时同时申请该权限,会导致某些设备拒绝这两种权限。

GetLastKnownLocationAsync 返回 null

首次启动或位置数据重置后出现这种情况是正常的。始终回退到 GetLocationAsync:

// ✅ Cache-first with fresh fallback
var location = await geolocation.GetLastKnownLocationAsync();
if (location is null || location.Timestamp < DateTimeOffset.UtcNow.AddMinutes(-5))
{
    location = await geolocation.GetLocationAsync(
        new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10)), ct);
}
调用任何地理定位方法前都必须先申请权限

先调用 Permissions.RequestAsync<Permissions.LocationWhenInUse>(),或者捕获 PermissionException。未获权限时调用 GetLocationAsync,在某些平台上会抛出异常,在另一些平台上则会返回 null——不同平台的行为并不一致。


持续监听:别忘了取消订阅

停止监听时未移除 LocationChanged 处理程序,会导致 GPS 持续运行并消耗电量。

// ❌ Forgetting to unsubscribe — GPS stays active
public void StopTracking()
{
    Geolocation.Default.StopListeningForeground();
    // LocationChanged handler still fires!
}

// ✅ Always remove the event handler
public void StopTracking()
{
    Geolocation.Default.StopListeningForeground();
    Geolocation.Default.LocationChanged -= OnLocationChanged;
}

检查清单

  • 每次调用 GetLocationAsync 时都传入 CancellationToken
  • 根据功能需求选择精度级别(不要盲目设为 Best)
  • 检查 GetLastKnownLocationAsync 是否为 null,并在必要时回退到 GetLocationAsync
  • 首次调用地理定位方法前申请运行时权限
  • 停止持续监听时移除 LocationChanged 处理程序
  • Android:单独申请 ACCESS_BACKGROUND_LOCATION(如有需要)
  • iOS:为完整精度提示添加 NSLocationTemporaryUsageDescriptionDictionary
  • Android:在安全敏感流程中检查 IsFromMockProvider

评论

支持 Markdown