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

【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():PromisegeoLocationManager.Location{letlocation:geoLocationManager.LocationawaitgeoLocationManager.getCurrentLocation();returnlocation;}geoLocationManager.getCurrentLocation()是一次性定位获取当前时刻的位置返回后结束。调用返回的Location对象结构interfaceLocation{latitude:number;// 纬度WGS84longitude:number;// 经度WGS84altitude:number;// 海拔米accuracy:number;// 水平精度米越小越精准speed:number;// 移动速度m/stimeStamp:number;// 时间戳direction:number;// 方向角0-360正北为0altitudeAccuracy:number;// 海拔精度additionSize:number;// 附加信息大小}二、项目中的两次定位// GasStationPage.ets callback 里mapUtil.moveToMyLocation(mapController);// 第一次移动地图到当前位置this.currentLatitude(awaitmapUtil.getMyLocation()).latitude;// 第二次this.currentLongitude(awaitmapUtil.getMyLocation()).longitude;// 获取坐标存起来定位被调用了两次实际上效率不高发了两次定位请求。更优的写法是// 优化只定位一次letlocationawaitmapUtil.getMyLocation();this.currentLatitudelocation.latitude;this.currentLongitudelocation.longitude;this.latitudethis.currentLatitude;this.longitudethis.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,// 超时时间毫秒};letlocationawaitgeoLocationManager.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 locationChangegetCurrentLocation是一次性的如果需要实时跟踪用户位置用持续定位// 开始持续定位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():PromisegeoLocationManager.Location|null{try{letlocationawaitgeoLocationManager.getCurrentLocation();returnlocation;}catch(err){leterrorerrasBusinessError;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, zoom15.9) → 镜头移动 │ └─ mapUtil.getMyLocation() × 2 └─ geoLocationManager.getCurrentLocation() → currentLatitude/Longitude └─ 存储用于后续计算到各加油站的距离八、定位最佳实践8.1 只在需要时定位不要一进入应用就持续定位只在需要位置信息时调用用完就停。这个项目只在地图页使用位置完全没问题。8.2 缓存位置结果同一次用户操作里多次需要位置缓存第一次的结果// MapUtil 里添加缓存privatecachedLocation:geoLocationManager.Location|nullnull;privatelastLocationTime:number0;privateCACHE_DURATION10000;// 10秒内的位置可以复用asyncgetMyLocation():PromisegeoLocationManager.Location{letnowDate.now();if(this.cachedLocation(now-this.lastLocationTime)this.CACHE_DURATION){returnthis.cachedLocation;// 返回缓存}letlocationawaitgeoLocationManager.getCurrentLocation();this.cachedLocationlocation;this.lastLocationTimenow;returnlocation;}8.3 权限问题导致定位失败getCurrentLocation在没有定位权限时会报 201 错误。所以一定要先申请权限再调用定位——这也是项目在主页就申请权限的原因。总结LocationKit 的核心 API 就两个一次性定位geoLocationManager.getCurrentLocation()→ 返回当前位置WGS84持续定位on(locationChange, request, callback)→ 实时位置更新使用注意事项先申请LOCATIONAPPROXIMATELY_LOCATION权限返回的坐标是WGS84显示在地图上要转 GCJ02做好错误处理超时、权限不足、服务不可用避免重复定位缓存位置结果下一篇讲暗色模式与多语言适配——color.json双套配置和string.json多语言是怎么工作的。