当前位置: 首页 > news >正文

【HarmonyOS实战】 LocationKit定位服务:获取用户位置完整指南

文章目录

    • 前言
    • 一、getMyLocation 方法
    • 二、项目中的两次定位
    • 三、getCurrentLocation 的参数
      • 3.1 LocationRequestPriority(优先策略)
      • 3.2 LocationRequestScenario(使用场景)
    • 四、持续定位:on/off locationChange
    • 五、定位失败处理
    • 六、setMyLocation:设置地图的"我的位置"
    • 七、定位在项目中的完整使用链路
    • 八、定位最佳实践
      • 8.1 只在需要时定位
      • 8.2 缓存位置结果
      • 8.3 权限问题导致定位失败
    • 总结

前言

知道用户在哪,是"附近加油站"最核心的能力。这个能力来自LocationKit,通过geoLocationManager模块实现。

项目里获取位置的代码看起来很简单——就一行await geoLocationManager.getCurrentLocation(),但背后有不少值得深入的地方:定位方式选择、精度控制、异步处理、持续定位。这篇文章全部讲清楚。

项目预览

一、getMyLocation 方法

// MapUtil.etsasyncgetMyLocation():Promise<geoLocationManager.Location>{letlocation:geoLocationManager.Location=awaitgeoLocationManager.getCurrentLocation();returnlocation;}

geoLocationManager.getCurrentLocation()一次性定位:获取当前时刻的位置,返回后结束。

调用返回的Location对象结构:

interfaceLocation{latitude:number;// 纬度(WGS84)longitude:number;// 经度(WGS84)altitude:number;// 海拔(米)accuracy:number;// 水平精度(米,越小越精准)speed:number;// 移动速度(m/s)timeStamp:number;// 时间戳direction:number;// 方向角(0-360,正北为0)altitudeAccuracy:number;// 海拔精度additionSize:number;// 附加信息大小}

二、项目中的两次定位

// GasStationPage.ets callback 里mapUtil.moveToMyLocation(mapController);// 第一次:移动地图到当前位置this.currentLatitude=(awaitmapUtil.getMyLocation()).latitude;// 第二次this.currentLongitude=(awaitmapUtil.getMyLocation()).longitude;// 获取坐标存起来

定位被调用了两次,实际上效率不高(发了两次定位请求)。更优的写法是:

// 优化:只定位一次letlocation=awaitmapUtil.getMyLocation();this.currentLatitude=location.latitude;this.currentLongitude=location.longitude;this.latitude=this.currentLatitude;this.longitude=this.currentLongitude;awaitmapUtil.moveToMyLocation(mapController);// 内部也调用了一次 getMyLocation

实际上moveToMyLocation内部也调用了一次getMyLocation,总共三次定位请求。对于演示项目来说这没问题,实际项目里可以缓存位置结果避免重复请求。

三、getCurrentLocation 的参数

不传参时,系统使用默认定位配置。如果需要自定义精度和超时:

// 指定定位请求参数letrequestParam:geoLocationManager.CurrentLocationRequest={priority:geoLocationManager.LocationRequestPriority.FIRST_FIX,// 优先策略scenario:geoLocationManager.LocationRequestScenario.UNSET,// 使用场景maxAccuracy:100,// 最大可接受精度(米),0表示不限制timeoutMs:10000,// 超时时间(毫秒)};letlocation=awaitgeoLocationManager.getCurrentLocation(requestParam);

3.1 LocationRequestPriority(优先策略)

策略说明耗电
FIRST_FIX尽快返回位置(精度可能低)
ACCURACY高精度优先(等待更准确的位置)
LOW_POWER省电模式(精度最低)最低
UNSET未设置,系统决定中等

3.2 LocationRequestScenario(使用场景)

enumLocationRequestScenario{UNSET,// 未设置NAVIGATION,// 导航场景(高频率、高精度)TRAJECTORY_TRACKING,// 轨迹记录CAR_HAILING,// 打车场景DAILY_LIFE_SERVICE,// 日常生活(本项目适合这个)NO_POWER,// 不主动定位,只接收其他应用的定位结果}

四、持续定位:on/off locationChange

getCurrentLocation是一次性的,如果需要实时跟踪用户位置,用持续定位:

// 开始持续定位geoLocationManager.on('locationChange',locationRequest,(location)=>{console.log(`位置更新:${location.latitude},${location.longitude}`);// 更新地图上的用户位置this.mapController?.setMyLocation(location);});// 停止持续定位(页面销毁时调用)geoLocationManager.off('locationChange',callback);

持续定位的请求参数:

letlocationRequest:geoLocationManager.LocationRequest={priority:geoLocationManager.LocationRequestPriority.ACCURACY,scenario:geoLocationManager.LocationRequestScenario.NAVIGATION,timeInterval:3,// 定位间隔(秒)distanceInterval:5,// 位置变化超过 5 米才触发回调maxAccuracy:50,// 精度要求 50 米内};

五、定位失败处理

getCurrentLocation返回 Promise,失败时 reject:

// 完整的错误处理asyncgetMyLocation():Promise<geoLocationManager.Location|null>{try{letlocation=awaitgeoLocationManager.getCurrentLocation();returnlocation;}catch(err){leterror=errasBusinessError;Logger.error('MapUtil',`定位失败: code=${error.code}, msg=${error.message}`);// 根据错误码做不同处理switch(error.code){case201:// 权限不足Logger.error('MapUtil','没有定位权限,请用户授权');break;case3301000:// 定位功能未开启Logger.error('MapUtil','请开启设备定位功能');break;case3301100:// 定位超时Logger.error('MapUtil','定位超时,请稍后重试');break;default:Logger.error('MapUtil','定位服务异常');}returnnull;}}

常见错误码:

错误码含义
201权限检查失败
401参数错误
3301000位置服务不可用(未开启)
3301100定位超时
3301200反向地理编码失败

六、setMyLocation:设置地图的"我的位置"

// MapUtil.ets - moveToMyLocationmapController?.setMyLocation(location);

setMyLocation是 MapKit 的方法(不是 LocationKit),它接收一个位置信息,在地图上显示蓝色定位圆点:

mapController.setMyLocation(location:geoLocationManager.Location):void;

注意:setMyLocation接受的是WGS84 坐标(geoLocationManager 返回的原始位置),MapKit 内部会自动处理坐标转换,在地图(GCJ02)上正确显示位置。

七、定位在项目中的完整使用链路

申请权限(MainPage.aboutToAppear) └─> PermissionsUtil.checkPermissions(['LOCATION', 'APPROXIMATELY_LOCATION']) └─> 用户授权后 → geoLocationManager.getCurrentLocation() 激活定位 地图初始化(GasStationPage callback) ├─> mapUtil.moveToMyLocation(controller) │ ├─> geoLocationManager.getCurrentLocation() → location (WGS84) │ ├─> mapController.setMyLocation(location) → 地图显示蓝点 │ ├─> convertToGCJ02(location.lat, location.lon) → gcj02 │ └─> animateCamera(gcj02, zoom=15.9) → 镜头移动 │ └─> mapUtil.getMyLocation() × 2 └─> geoLocationManager.getCurrentLocation() → currentLatitude/Longitude └─> 存储,用于后续计算到各加油站的距离

八、定位最佳实践

8.1 只在需要时定位

不要一进入应用就持续定位,只在需要位置信息时调用,用完就停。这个项目只在地图页使用位置,完全没问题。

8.2 缓存位置结果

同一次用户操作里多次需要位置,缓存第一次的结果:

// MapUtil 里添加缓存privatecachedLocation:geoLocationManager.Location|null=null;privatelastLocationTime:number=0;privateCACHE_DURATION=10000;// 10秒内的位置可以复用asyncgetMyLocation():Promise<geoLocationManager.Location>{letnow=Date.now();if(this.cachedLocation&&(now-this.lastLocationTime)<this.CACHE_DURATION){returnthis.cachedLocation;// 返回缓存}letlocation=awaitgeoLocationManager.getCurrentLocation();this.cachedLocation=location;this.lastLocationTime=now;returnlocation;}

8.3 权限问题导致定位失败

getCurrentLocation在没有定位权限时会报 201 错误。所以一定要先申请权限,再调用定位——这也是项目在主页就申请权限的原因。

总结

LocationKit 的核心 API 就两个:

  1. 一次性定位geoLocationManager.getCurrentLocation()→ 返回当前位置(WGS84)
  2. 持续定位on('locationChange', request, callback)→ 实时位置更新

使用注意事项:

  • 先申请LOCATION+APPROXIMATELY_LOCATION权限
  • 返回的坐标是WGS84,显示在地图上要转 GCJ02
  • 做好错误处理(超时、权限不足、服务不可用)
  • 避免重复定位,缓存位置结果

下一篇讲暗色模式与多语言适配——color.json双套配置和string.json多语言是怎么工作的。

http://www.rkmt.cn/news/1477485.html

相关文章:

  • 告别网盘限速:八大主流平台直链下载助手全攻略
  • 无需鼠标!借助键盘实现快速鼠标控制
  • 别再只盯着GPS了!精度因子(DOP)在Wi-Fi/蓝牙定位里同样关键
  • 从F1赛车到无人机避障:聊聊脉冲雷达‘测不准’的那些事儿与工程解法
  • KMS智能激活工具:高效解决Windows和Office激活难题
  • 高效Windows内存优化指南:3步掌握Mem Reduct智能内存管理技巧
  • CPU上的LLM推理加速:AMX指令集与稀疏化技术
  • 2026年5月国内电动两轮高端改装灯具品牌排行:行业电动两轮高端灯具/顶级灯具设计研发/高端两轮灯具/高端灯具研发首家/选择指南 - 优质品牌商家
  • e2 studio调试总失败?别慌,先检查这3个配置项(含Connection Settings详解)
  • CANoe自动化配置进阶:如何用CommunicationSetup接口批量管理你的应用模型和数据源
  • 手把手教你将GCNv2特征提取器‘抠’出来做双目匹配测试(附完整C++代码)
  • K8s介绍(1)
  • GprMax正演模拟避坑指南:除了介电常数,这3个参数设置不当也会导致图像‘消失’
  • 从STM32转战NXP LPC54114?手把手教你用Keil5点亮第一个LED(附完整工程)
  • 从Eclipse老手到STS新手:这10个SpringBoot开发必备设置,你配好了吗?
  • SAP FICO后台配置避坑指南:从汇率到固定资产,新手必知的10个关键配置点
  • 告别S3控制台!用MinIO Client(mc)命令行5分钟搞定文件同步与备份
  • 别再乱用SCOPE了!ABAP锁机制深度解析:V1锁、V2锁与BAPI调用的那些事儿
  • 从文件系统到网络库:聊聊Linux内核与开源项目中那些‘树’的实战应用
  • 2026工业粉尘治理技术实测:收尘器、脉冲式除尘器、超低排放洗车机、车间降尘、雾森降尘、龙门洗车台、龙门洗车机定制选择指南 - 优质品牌商家
  • K8s介绍(2)POD架构
  • 告别开机弹窗!Vivado 18.3安装后必做的几项优化设置(附License配置避坑)
  • 告别单调点图条图:用clusterProfiler+ggplot2打造高颜值可发表的富集分析图
  • 从玻尔兹曼机到AlexNet:跟着Hinton的论文,一步步看懂深度学习的诞生史
  • VMware macOS解锁工具:打破硬件限制的虚拟化魔法
  • 从激光雷达回波到论文复现:深入解读Rclonte-M算法中的波形参数奥秘
  • 2026年口碑好的螺旋地桩/地桩优质厂家推荐榜 - 行业平台推荐
  • 2026年美国留学中介推荐,机构排名对比与选机构建议全流程指南 - 环球新视野
  • PCIe 6.0的FLIT模式详解:如何把传输延迟从毫秒级降到纳秒级?
  • Simple Runtime Window Editor:释放窗口控制的无限可能,打造个性化数字工作空间