在.NET MAUI应用中获取设备GPS地理位置,核心是使用Microsoft.Maui.Devices.Sensors命名空间下的Geolocation类。它屏蔽了Android和iOS底层定位API的差异,让开发者用统一代码拿到经纬度、海拔和速度等信息。实际开发时,重点不在于调用那一行异步方法,而在于权限申请、精度配置以及异常处理。

一、项目权限配置
MAUI跨平台项目必须在各自原生配置中声明定位权限,否则运行时会直接抛异常或返回空数据。Android需要在Platforms/Android/AndroidManifest.xml里添加粗调和细调权限,iOS则要在Platforms/iOS/Info.plist中写明确用途描述。
对于Android,如果目标版本较高,还需要在运行时动态申请。MAUI提供了Permissions API来统一处理。下面给出Android清单文件的必要片段,注意字符都要转义以符合XML规范。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application android:allowBackup="true"></application>
</manifest>
iOS的Info.plist需要包含NSLocationWhenInUseUsageDescription,否则上架会被拒。文本要说明应用为何需要位置,例如用于展示附近门店。配置不完整是很多初学者拿不到数据的首要原因。
除了静态声明,运行时权限申请建议放在页面出现后触发。可以用Permissions.RequestAsync方法,它会自动调起系统弹窗。用户拒绝后要有降级方案,比如手动输入地址。
// 请求位置权限示例
var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
// 用户拒绝,提示并退出定位逻辑
return;
}
二、使用Geolocation读取当前位置
Geolocation类最常用的函数是GetLocationAsync,它接受一个GeolocationRequest对象,用来设置精度与超时。如果不传请求,默认是中等精度且超时较长,可能在室内迟迟不返回。
下面代码展示如何在ViewModel或页面后台获取一次当前GPS坐标。我们显式指定高精度,并限制十秒内必须返回,避免界面卡死。注意所有HTML特殊字符在代码块内均已转义。
using Microsoft.Maui.Devices.Sensors;
using System.Diagnostics;
public async Task<Location> GetCurrentGpsAsync()
{
try
{
var request = new GeolocationRequest(GeolocationAccuracy.High, TimeSpan.FromSeconds(10));
Location location = await Geolocation.GetLocationAsync(request);
if (location != null)
{
Debug.WriteLine($"纬度: {location.Latitude}, 经度: {location.Longitude}");
return location;
}
}
catch (FeatureNotSupportedException)
{
// 设备不支持定位
}
catch (PermissionException)
{
// 权限不足
}
catch (Exception ex)
{
// 其他异常如超时
Debug.WriteLine(ex.Message);
}
return null;
}
Location对象除了Latitude和Longitude,还包含Altitude、Speed、Course以及Timestamp。在导航类应用中,Speed和Course能帮助判断行进方向与速率,但部分平台在室内或低速时不会填充这些字段。
如果想持续监听位置变化,可以使用GetLocationAsync配合循环,或者订阅ListeningChanged事件。不过持续定位非常耗电,建议在页面不可见时停止。下面示例展示如何监听:
public void StartListening()
{
Geolocation.LocationChanged += OnLocationChanged;
}
private void OnLocationChanged(object sender, GeolocationLocationChangedEventArgs e)
{
var loc = e.Location;
Debug.WriteLine($"更新坐标: {loc.Latitude},{loc.Longitude}");
}
三、精度、耗时与异常处理要点
GeolocationAccuracy枚举包含Low、Medium、High、Best等档位。精度越高,系统越倾向使用GPS卫星而非基站或WiFi,耗电和冷启动时间显著增加。在共享单车类应用可设High,在天气插件里Medium就够了。
超时设置过短,在高层建筑或天气恶劣时容易抛TimeoutException。建议首次定位给十五秒,后续用缓存位置做过渡。下表列出常见精度档位的参考特性:
| 精度档位 | 数据源 | 耗电 | 典型场景 |
|---|---|---|---|
| Low | 基站/WiFi | 低 | 城市区县级展示 |
| Medium | 混合 | 中 | 附近商户列表 |
| High | GPS为主 | 高 | 实时导航轨迹 |
异常方面,FeatureNotSupportedException代表设备无定位模块,PermissionException代表未授权,一般异常可能来自系统服务被禁用。生产环境应分类提示,而不是笼统报错。
另外,模拟器调试时Windows和Mac的本地传感器可能不准。可用官方模拟器发送虚拟坐标来验证UI逻辑。发布前应在真机测试弱网与隧道环境,确保超时后有友好反馈。
四、在页面中整合显示
拿到位置后,通常会绑定到界面元素。MAUI的MVVM模式里,可以把Location存为属性,用Label展示。下面给出一个极简页面后台调用示例,展示点击按钮获取并显示坐标。
private async void OnLocateClicked(object sender, EventArgs e)
{
var loc = await GetCurrentGpsAsync();
if (loc != null)
{
ResultLabel.Text = $"当前位置:{loc.Latitude:F4}, {loc.Longitude:F4}";
}
else
{
ResultLabel.Text = "获取失败,请检查权限或信号";
}
}
若要在地图上标点,可把经纬度传给Microsoft.Maui.Controls.Maps的Pin对象。注意Maps组件需要额外初始化和权限,且iOS需在Info.plist配置NSLocationWhenInUseUsageDescription以外还要打开地图能力。
整体来看,MAUI的Geolocation把复杂原生交互收敛成简单异步调用,但权限和精度策略仍是稳定获取GPS的关键。按上述步骤配置并捕获异常,就能在跨平台项目中可靠地拿到用户位置。
MAUIGeolocationGPS定位修改时间:2026-08-08 20:24:16