HarmonyOS LocationKit:geoLocationManager 完全使用指南
文章目录前言一、单次定位getCurrentLocation1.1 基础用法1.2 location 对象的完整字段1.3 带配置的精确定位二、项目中的定位流程2.1 MapUtil.getMyLocation 源码2.2 坐标转换的必要性三、持续定位on/off 实时追踪3.1 开启持续定位3.2 实时追踪完整示例四、地理围栏进出区域自动触发4.1 设置地理围栏五、定位常见问题排查总结前言本项目的核心功能之一是显示附近加油站这依赖于获取用户当前位置。HarmonyOS 提供了kit.LocationKit中的geoLocationManager模块来实现位置服务。本篇深入讲解geoLocationManager的各种用法从单次定位到持续追踪带你掌握 HarmonyOS 位置服务的完整体系。一、单次定位getCurrentLocation1.1 基础用法import{geoLocationManager}fromkit.LocationKit;// 最简单直接调用使用默认配置asyncfunctiongetLocation():Promisevoid{try{constlocationawaitgeoLocationManager.getCurrentLocation();console.log(纬度${location.latitude});console.log(经度${location.longitude});console.log(精度${location.accuracy}m);console.log(时间${newDate(location.timeStamp).toLocaleString()});}catch(error){console.error(定位失败${error.message});}}1.2 location 对象的完整字段// geoLocationManager.Location 的字段interfaceLocation{latitude:number;// 纬度度longitude:number;// 经度度altitude:number;// 海拔米accuracy:number;// 水平精度米speed:number;// 速度m/stimeStamp:number;// UTC 时间戳毫秒direction:number;// 方向角0~360度正北为0timeSinceBoot:number;// 启动后时间纳秒additions?:string[];// 附加信息additionSize?:number;// 附加信息数量isFromMock?:boolean;// 是否来自模拟定位}1.3 带配置的精确定位import{geoLocationManager}fromkit.LocationKit;asyncfunctiongetAccurateLocation():PromisegeoLocationManager.Location{// CurrentLocationRequest 配置constrequest:geoLocationManager.CurrentLocationRequest{// 优先级精度 vs 速度 vs 节电priority:geoLocationManager.LocationRequestPriority.ACCURACY,// 高精度优先// 定位场景影响底层定位策略scenario:geoLocationManager.LocationRequestScenario.NAVIGATION,// 导航场景// 最大等待时间毫秒超时抛出异常timeoutMs:10000,// 10秒超时// 可接受的最大缓存时间毫秒0 不接受缓存结果maxAccuracy:100,// 只接受精度在100米以内的结果};returnawaitgeoLocationManager.getCurrentLocation(request);}优先级配置说明LocationRequestPriority含义功耗精度ACCURACY高精度GPS 网络高最高FAST_FIRST_FIX快速首次定位中中LOW_POWER低功耗网络定位低低FIRST_FIX第一次定位结果中中二、项目中的定位流程2.1 MapUtil.getMyLocation 源码// MapUtil.etsasyncgetMyLocation():PromisegeoLocationManager.Location{letlocation:geoLocationManager.LocationawaitgeoLocationManager.getCurrentLocation();returnlocation;}// 调用链// GasStationPage.init() 的 callback 中this.currentLatitude(awaitmapUtil.getMyLocation()).latitude;this.currentLongitude(awaitmapUtil.getMyLocation()).longitude;提示项目中调用了两次getMyLocation()可以优化为只调用一次保存结果后复用。这是一个可以改进的点。2.2 坐标转换的必要性GPS 返回的是WGS84 坐标系但中国大陆地图显示使用GCJ02火星坐标系。如果直接用 WGS84 坐标显示在地图上会有几十到几百米的偏差// MapUtil.etsasyncmoveToMyLocation(mapController:map.MapComponentController):Promisevoid{// 步骤1获取 WGS84 坐标GPS原始坐标letlocation:geoLocationManager.Locationawaitthis.getMyLocation();// 步骤2将位置同步给地图的我的位置层显示蓝点mapController?.setMyLocation(location);// 步骤3将 WGS84 转换为 GCJ02中国地图坐标letgcj02Positionawaitthis.convertToGCJ02(location.latitude,location.longitude);// 步骤4移动地图相机到 GCJ02 坐标避免偏移this.moveToCurrentPosition(gcj02Position.latitude,gcj02Position.longitude,mapController);}三、持续定位on/off 实时追踪3.1 开启持续定位import{geoLocationManager}fromkit.LocationKit;// 持续定位配置constlocationRequest:geoLocationManager.LocationRequest{priority:geoLocationManager.LocationRequestPriority.ACCURACY,scenario:geoLocationManager.LocationRequestScenario.NAVIGATION,timeInterval:1,// 定位时间间隔秒distanceInterval:10,// 定位距离间隔米移动超过10米才更新maxAccuracy:50,// 最大可接受精度米};// 定位回调constlocationCallback(location:geoLocationManager.Location){console.log(位置更新${location.latitude},${location.longitude});console.log(精度${location.accuracy}m, 速度${location.speed}m/s);};// 开始监听geoLocationManager.on(locationChange,locationRequest,locationCallback);// 停止监听页面销毁时必须调用geoLocationManager.off(locationChange,locationCallback);3.2 实时追踪完整示例import{geoLocationManager}fromkit.LocationKit;EntryComponentstruct TrackingPage{StatecurrentLat:number0;StatecurrentLng:number0;Stateaccuracy:number0;Statespeed:number0;StateisTracking:booleanfalse;StatelocationHistory:string[][];privatelocationCallback:(loc:geoLocationManager.Location)void(loc){this.currentLatloc.latitude;this.currentLngloc.longitude;this.accuracyloc.accuracy;this.speedloc.speed;// 记录轨迹最多保留10条constrecord${loc.latitude.toFixed(5)},${loc.longitude.toFixed(5)};this.locationHistory[record,...this.locationHistory].slice(0,10);};startTracking():void{constrequest:geoLocationManager.LocationRequest{priority:geoLocationManager.LocationRequestPriority.ACCURACY,scenario:geoLocationManager.LocationRequestScenario.NAVIGATION,timeInterval:2,distanceInterval:5,};try{geoLocationManager.on(locationChange,request,this.locationCallback);this.isTrackingtrue;}catch(error){console.error(开启定位失败${error.message});}}stopTracking():void{try{geoLocationManager.off(locationChange,this.locationCallback);this.isTrackingfalse;}catch(error){console.error(停止定位失败${error.message});}}aboutToDisappear():void{// 页面销毁时必须停止追踪if(this.isTracking){this.stopTracking();}}build(){Column({space:16}){Text(实时位置追踪).fontSize(20).fontWeight(FontWeight.Bold)// 当前位置信息Column({space:8}){Row({space:8}){Text(状态).fontSize(14).fontColor(#666666)Text(this.isTracking?追踪中 :已停止).fontSize(14).fontColor(this.isTracking?#FF4D4F:#999999).fontWeight(FontWeight.Bold)}Text(纬度${this.currentLat.toFixed(6)||--}).fontSize(14).fontColor(#333333)Text(经度${this.currentLng.toFixed(6)||--}).fontSize(14).fontColor(#333333)Text(精度${this.accuracy?this.accuracy.toFixed(1)m:--}).fontSize(14).fontColor(#666666)Text(速度${this.speed?(this.speed*3.6).toFixed(1)km/h:--}).fontSize(14).fontColor(#666666)}.padding(16).width(90%).backgroundColor(#F8F9FA).borderRadius(12).alignItems(HorizontalAlign.Start)// 控制按钮Row({space:16}){Button(开始追踪).onClick((){if(!this.isTracking)this.startTracking();}).backgroundColor(this.isTracking?#CCCCCC:#52C41A).fontColor(#FFFFFF).borderRadius(20).enabled(!this.isTracking)Button(停止追踪).onClick((){if(this.isTracking)this.stopTracking();}).backgroundColor(this.isTracking?#FF4D4F:#CCCCCC).fontColor(#FFFFFF).borderRadius(20).enabled(this.isTracking)}// 轨迹历史if(this.locationHistory.length0){Column({space:4}){Text(轨迹记录最新).fontSize(14).fontWeight(FontWeight.Bold).alignSelf(ItemAlign.Start)ForEach(this.locationHistory,(record:string,index:number){Text(${index1}.${record}).fontSize(12).fontColor(#666666).alignSelf(ItemAlign.Start)})}.padding(12).width(90%).backgroundColor(#F0F4FF).borderRadius(8)}}.padding(24).width(100%).height(100%).justifyContent(FlexAlign.Center)}}四、地理围栏进出区域自动触发4.1 设置地理围栏// 地理围栏当用户进入/离开指定区域时自动通知constgeofenceRequest:geoLocationManager.GeofenceRequest{priority:geoLocationManager.LocationRequestPriority.ACCURACY,scenario:geoLocationManager.LocationRequestScenario.NO_POWER,geofence:{latitude:40.0046,// 围栏中心纬度加油站位置longitude:116.4823,// 围栏中心经度radius:500,// 围栏半径米expiration:-1// 过期时间-1 永不过期}};// 进入围栏触发geoLocationManager.on(fenceStatusChange,geofenceRequest,(transition){if(transition.eventgeoLocationManager.GeofenceTransition.GEOFENCE_TRANSITION_ENTER){console.log(进入加油站附近500m范围内);// 推送通知附近有加油站}elseif(transition.eventgeoLocationManager.GeofenceTransition.GEOFENCE_TRANSITION_EXIT){console.log(离开加油站附近);}});五、定位常见问题排查问题原因解决方案定位超时GPS 信号弱、室内环境增加超时时间降低精度要求坐标偏移未做 WGS84→GCJ02 转换调用map.convertCoordinate转换权限被拒用户未授权引导用户在设置中开启定位速度为0设备静止或 GPS 未激活正常设备静止时速度为0code: 3301000位置功能未开启引导用户打开系统设置 → 位置信息总结geoLocationManager是 HarmonyOS 位置服务的核心 API单次定位用getCurrentLocation()持续追踪用on(locationChange, ...)地理围栏用on(fenceStatusChange, ...)。始终记住①申请权限再调用②GPS 返回 WGS84中国地图需要转换为 GCJ02③页面销毁时必须off()停止监听避免内存泄漏和无效定位。