HarmonyOS7 定位与地图:getLocation + Map 组件实现附近的人

发布时间:2026/7/21 7:08:14
HarmonyOS7 定位与地图:getLocation + Map 组件实现附近的人 文章目录前言定位权限与配置获取位置Map 组件接入添加 Marker 标注计算两点距离写在最后前言做过社交类 App 的同学都知道附近的人是个经典功能。但真要自己实现定位权限怎么配、经纬度怎么拿、地图怎么渲染、Marker 怎么加——一堆问题等着你。我之前做这个功能的时候踩了不少坑尤其是定位权限那块差点把手机搞崩溃。今天就把完整流程捋一遍照着做基本能跑通。这篇文章的目标很明确用 HarmonyOS7 的定位 API 拿到当前经纬度再结合 Map 组件把位置标在地图上最后算算距离搞一个简易版附近的人。涉及的模块主要是kit.LocationKit和kit.MapKit都是官方 Kit不用引第三方。定位权限与配置划重点定位权限不配好代码写得再漂亮也白搭。HarmonyOS 的定位权限分两种模糊定位和精确定位权限说明ohos.permission.APPROXIMATELY_LOCATION模糊定位精确度约 5kmohos.permission.LOCATION精确定位GPS 级别你需要两个都申请因为精确定位依赖模糊定位。在module.json5里这样写{requestPermissions:[{name:ohos.permission.APPROXIMATELY_LOCATION,reason:$string:location_reason,usedScene:{abilities:[EntryAbility],when:inuse}},{name:ohos.permission.LOCATION,reason:$string:location_reason,usedScene:{abilities:[EntryAbility],when:inuse}}]}when: inuse表示仅前台使用时授权。如果需要后台定位改成always并额外申请ohos.permission.LOCATION_IN_BACKGROUND。另外光在配置里声明还不够运行时还要动态申请权限。不然用户没授权你就调定位 API直接崩给你看。获取位置权限搞定后就该拿经纬度了。核心 API 是geoLocationManager.getCurrentLocation()。import{geoLocationManager}fromkit.LocationKit;import{abilityAccessCtrl,bundleManager}fromkit.AbilityKit;asyncrequestLocationPermission():Promiseboolean{letatManagerabilityAccessCtrl.createAtManager();try{letgrantStatusawaitatManager.checkAccessToken(bundleManager.getBundleInfoForSelfSync().appInfo.accessTokenId,ohos.permission.LOCATION);if(grantStatusabilityAccessCtrl.GrantStatus.PERMISSION_GRANTED){returntrue;}// 动态申请权限letresultawaitatManager.requestPermissionsFromUser(this.getUIContext().getHostContext()ascommon.UIAbilityContext,[ohos.permission.APPROXIMATELY_LOCATION,ohos.permission.LOCATION]);returnresult.authResults[0]0;}catch(e){console.error(权限申请失败: JSON.stringify(e));returnfalse;}}关键讲解checkAccessToken先检查权限状态已经有了就不用重复申请requestPermissionsFromUser弹出系统授权弹窗用户点允许才返回 0两个权限要一起申请别只申请精确不申请模糊拿到权限后获取位置就简单了StatemyLatitude:number0;StatemyLongitude:number0;asyncgetCurrentLocation():Promisevoid{letrequestInfo:geoLocationManager.CurrentLocationRequest{priority:geoLocationManager.LocationRequestPriority.FIRST_FIX,scenario:geoLocationManager.LocationRequestScenario.UNSET,maxAccuracy:100};try{letlocationawaitgeoLocationManager.getCurrentLocation(requestInfo);this.myLatitudelocation.latitude;this.myLongitudelocation.longitude;console.info(定位成功:${this.myLatitude},${this.myLongitude});}catch(e){console.error(定位失败请检查位置开关: JSON.stringify(e));}}逐行讲解priority: FIRST_FIX— 优先快速拿到结果不管精度高低先返回一个scenario: UNSET— 不指定场景时 priority 才生效maxAccuracy: 100— 要求精度不超过 100 米getCurrentLocation返回的location对象里包含latitude纬度和longitude经度血泪教训如果用户没开手机的位置开关getCurrentLocation会抛异常。必须 try-catch 包住不然 App 直接闪退。Map 组件接入有了经纬度接下来上地图。HarmonyOS7 用的是MapComponent来自kit.MapKit。import{MapComponent,mapCommon,map}fromkit.MapKit;import{AsyncCallback}fromkit.BasicServicesKit;StatemapController?:map.MapComponentController;privatemapOptions?:mapCommon.MapOptions;privatecallback?:AsyncCallbackmap.MapComponentController;aboutToAppear():void{this.mapOptions{position:{target:{latitude:39.9042,longitude:116.4074},zoom:14}};this.callbackasync(err,mapController){if(!err){this.mapControllermapController;}else{console.error(地图初始化失败:${err.code},${err.message});}};}build(){Column(){MapComponent({mapOptions:this.mapOptions,mapCallback:this.callback}).width(100%).height(500)}}关键讲解mapOptions.position.target— 地图初始中心点坐标这里先写个默认值北京拿到定位后更新mapOptions.position.zoom— 缩放级别14 大概能看到街区级别callback是地图初始化完成的回调拿到mapController才能操作地图mapController是一切地图操作的入口加标记、移动镜头都靠它添加 Marker 标注附近的人当然得在地图上标点。Marker 就是干这个的。asyncaddMarkers():Promisevoid{if(!this.mapController)return;// 自己的位置letmyMarkerOptions:mapCommon.MarkerOptions{position:{latitude:this.myLatitude,longitude:this.myLongitude},title:我,clickable:true};awaitthis.mapController.addMarker(myMarkerOptions);// 模拟附近的人letnearbyUsers[{name:小明,lat:this.myLatitude0.002,lng:this.myLongitude0.001},{name:小红,lat:this.myLatitude-0.001,lng:this.myLongitude0.003},{name:阿杰,lat:this.myLatitude0.001,lng:this.myLongitude-0.002}];for(letuserofnearbyUsers){letmarkerOptions:mapCommon.MarkerOptions{position:{latitude:user.lat,longitude:user.lng},title:user.name,clickable:true};awaitthis.mapController.addMarker(markerOptions);}// 移动镜头到我的位置this.mapController.moveCamera(map.newLatLng(this.myLatitude,this.myLongitude),14);}讲解MarkerOptions里的position是必须的指定标记的经纬度title会显示在 Marker 上方的信息窗里addMarker是异步操作得awaitmoveCamera把地图视角移到指定位置和缩放级别计算两点距离地图上标了点还不够用户肯定想知道这个人离我多远。用 Haversine 公式算就行getDistance(lat1:number,lng1:number,lat2:number,lng2:number):number{constR6371000;// 地球半径单位米letdLat(lat2-lat1)*Math.PI/180;letdLng(lng2-lng1)*Math.PI/180;letaMath.sin(dLat/2)*Math.sin(dLat/2)Math.cos(lat1*Math.PI/180)*Math.cos(lat2*Math.PI/180)*Math.sin(dLng/2)*Math.sin(dLng/2);letc2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a));returnR*c;// 返回距离单位米}怎么用letdistthis.getDistance(this.myLatitude,this.myLongitude,user.lat,user.lng);console.info(小明距我${Math.round(dist)}米);R * c的单位是米。如果想要公里除以 1000 就行。这套公式在短距离几十公里内精度完全够用。写在最后定位 地图这组合在社交、出行、外卖类 App 里太常见了。HarmonyOS7 把这两个能力都封装成了 Kit用起来比我想象中顺手。最折腾人的还是权限那块——动态申请、位置开关、try-catch 缺一不可。