关于 maui-geolocation
面向 .NET MAUI 定位功能的实用指南,说明权限处理、精度与电量取舍、取消操作、平台差异和持续跟踪清理。
主要功能
- 01取消与超时处理指南
- 02精度与电量的取舍
- 03平台权限处理
- 04最后已知位置的回退方案
- 05持续跟踪的清理
适用场景
- 01为定位请求添加超时
- 02处理近似位置或定位不可用
- 03构建依赖位置的安全检查
- 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