【鸿蒙 HarmonyOS Next 最佳实践】位置定位场景开发指导

守听  金牌会员 | 2025-3-16 21:50:45 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 970|帖子 970|积分 2910

简介

位置定位提供了GNSS定位、网络定位等多种功能。在实际开发场景中,经常会利用位置定位的功能,如都会定位功能、外卖与快递服务及时跟踪配送员位置、汽车及时导航等等。
常见开发场景如下所示:


  • 利用精准定位确认具体位置
  • 获取历史定位
  • 及时获取当前位置
  • 背景定位
申请定位权限

场景描述

应用在利用位置本领前,首先须要确认体系的位置开关为开启状态。如果体系位置本领没有开启,应用不能利用定位服务。


其次,装备的位置信息须要想用户申请对应的访问权限,用户授权后,应用才气利用定位服务。须要用户授权的用户如下所示。


  • ohos.permission.LOCATION:用于获取精准位置,精准度在米级别。
  • ohos.permission.APPROXIMATELY_LOCATION:用于获取含糊位置,精确度为5公里。
  • ohos.permission.LOCATION_IN_BACKGROUND:用于应用切换到背景仍然须要获取定位信息的场景。

开发步骤

1.在module.json5中配置须要的权限。
  1. {
  2. // ...
  3. "requestPermissions": [
  4.          {
  5.            "name": "ohos.permission.LOCATION",
  6.            "reason": "$string:location_permission",
  7.            "usedScene": {
  8.              "abilities": [
  9.                "EntryAbility"
  10.              ],
  11.              "when": "inuse"
  12.            }
  13.          },
  14.          {
  15.            "name": "ohos.permission.INTERNET",
  16.            "reason": "$string:internet_permission",
  17.            "usedScene": {
  18.              "abilities": [
  19.                "EntryAbility"
  20.              ],
  21.              "when": "inuse"
  22.            }
  23.          },
  24.          {
  25.            "name": "ohos.permission.APPROXIMATELY_LOCATION",
  26.            "reason": "$string:fuzzy_location_permission",
  27.            "usedScene": {
  28.              "abilities": [
  29.                "EntryAbility"
  30.              ],
  31.              "when": "inuse"
  32.            }
  33.          },
  34.          {
  35.            "name": "ohos.permission.LOCATION_IN_BACKGROUND",
  36.            "reason": "$string:location_permission",
  37.            "usedScene": {
  38.              "abilities": [
  39.                "EntryAbility"
  40.              ],
  41.              "when": "inuse"
  42.            }
  43.          }
  44.        ]
  45. // ...
  46. }
复制代码
2.详细申请定位权限的代码如下所示。关于权限的申请,详情可以参考向用户申请授权。
  1. // 引入abilityAccessCtrl
  2. import { UIAbility, AbilityConstant, Want, abilityAccessCtrl } from '@kit.AbilityKit';
  3. // ...
  4. export default class EntryAbility extends UIAbility {
  5.   async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
  6.     Logger.info(TAG, `[Demo] EntryAbility onCreate`);
  7.     let atManager = abilityAccessCtrl.createAtManager();
  8.     try {
  9.       // 申请权限
  10.       atManager.requestPermissionsFromUser(this.context,
  11.         ['ohos.permission.INTERNET', 'ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'])
  12.         .then((data) => {
  13.           Logger.info(TAG, `data: ${JSON.stringify(data)}`);
  14.         })
  15.         .catch((err: BusinessError) => {
  16.           Logger.error(TAG, `err: ${JSON.stringify(err)}`);
  17.         })
  18.     } catch (err) {
  19.       Logger.error(TAG, `catch err->${JSON.stringify(err)}`);
  20.     }
  21.   }
  22. // ...
  23. }
复制代码
利用精准定位确认具体位置

场景描述

关于位置定位,重要有两种方式GNSS定位和网络定位,如下表所示。
定位方式阐明优点
GNSS定位基于环球导航卫星体系,包含GPS、GLONASS、北斗、Galileo等,通过导航卫星、装备芯片提供的定位算法,来确定装备正确位置。定位精准
网络定位通过网络举行定位,包罗WLAN、蓝牙定位、基站定位。定位速率快
位置定位的战略是重要是基于GNSS定位和网络定位实现的,定位精准的战略利用的是GNSS定位,定位快速的战略利用的网络定位。
获取定位信息的接口getCurrentLocation须要设置定位战略和单次定位超时时间,单次定位超时时间建议设置为10秒,定位战略支持两种参数配置,分别是CurrentLocationRequest和SingleLocationRequest。SingleLocationRequest从API version 12开始支持,在实现上更为简单,也是保举的实现方式。CurrentLocationRequest和SingleLocationRequest的定位战略对比如下所示:
参数范例战略阐明
CurrentLocationRequestPRIORITY_ACCURACY0x501表现精度优先。(GNSS定位)
PRIORITY_LOCATING_SPEED0x502表现快速获取位置优先。(网络定位)
SingleLocationRequestUNSET0x200表现未设置优先级,表现LocationRequestPriority无效。
ACCURACY0x201表现精度优先。(GNSS定位)
LOW_POWER0x202表现低功耗优先。(网络定位)
PRIORITY_LOCATING_SPEED0x203表现快速获取位置优先,如果应用希望快速拿到一个位置,可以将优先级设置为该字段。 快速定位优先战略会同时利用GNSS定位和网络定位技术。
开发步骤

如下流程图所示,利用精准定位确认具体位置分为以下多个步骤。
1.开启体系定位本领,向用户申请位置权限。
2.设置定位战略,确认当前定位的方式。
3.获取当前定位信息。
4.将定位坐标转化为地理描述。

如下代码所示,设置定位的战略为PRIORITY_LOCATING_SPEED,即速率优先,并根据PRIORITY_LOCATING_SPEED的战略调用getCurrentLocation获取当前位置。
  1. getLocationPosition(): void {
  2.   // 设置LocatingPriority定位策略
  3.   let request: geoLocationManager.SingleLocationRequest = {
  4.     locatingPriority: geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,
  5.     locatingTimeoutMs: CommonConstants.TEN_THOUSAND
  6.   };
  7.   // 根据策略获取当前定位信息
  8.   geoLocationManager.getCurrentLocation(request).then((location: geoLocationManager.Location) => {
  9.     // 位置转化
  10.     this.getAddress({
  11.       latitude: location.latitude,
  12.       longitude: location.longitude
  13.     });
  14.   }).catch((err: BusinessError) => {
  15.     promptAction.showToast({
  16.       message: JSON.stringify(err),
  17.       duration: CommonConstants.TWO_THOUSAND
  18.     });
  19.   });
  20. }
复制代码
通过getAddressesFromLocation将定位坐标转化为地理描述,代码如下所示:
  1. async getAddress(location: LocationInter) {
  2.     try {
  3.       // ...
  4.       let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest = {
  5.         locale: getContext(this).resourceManager.getStringSync($r('app.string.language')),
  6.         latitude: location.latitude,
  7.         longitude: location.longitude,
  8.         maxItems: 1
  9.       };
  10.       // 通过getAddressesFromLocation将定位坐标转化为地理描述
  11.       geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
  12.         if (data) {
  13.           this.address = data[0]?.placeName || '';
  14.           this.marker?.setInfoWindowVisible(true)
  15.           this.marker?.setSnippet(this.address)
  16.         } else {
  17.           promptAction.showToast({
  18.             message: JSON.stringify(err),
  19.             duration: CommonConstants.TWO_THOUSAND
  20.           });
  21.         }
  22.       });
  23.     } catch (error) {
  24.       promptAction.showToast({
  25.         message: JSON.stringify(error),
  26.         duration: CommonConstants.TWO_THOUSAND
  27.       });
  28.     }
  29.   }
复制代码
获取历史定位

场景描述

如下图所示,历史定位的缓存是所有应用公用的,应用1和应用2调用getLastLocation获取的缓存是同一个。

开发步骤

通过getLastLocation获取上一次的缓存定位,代码如下所示。
  1. getPreLocationPosition(): void {
  2.   try {
  3.     let location = geoLocationManager.getLastLocation();
  4.     this.getAddress({
  5.       latitude: location.latitude,
  6.       longitude: location.longitude
  7.     });
  8.   } catch (err) {
  9.     promptAction.showToast({
  10.       message: JSON.stringify(err),
  11.       duration: CommonConstants.TWO_THOUSAND
  12.     });
  13.   }
  14. }
复制代码
持续获取当前位置

场景描述

持续获取当前位置常用于导航、运动轨迹、出行等场景。持续获取须要设置位置请求参数,当前locationChange事件支持LocationRequest和ContinuousLocationRequest两种参数。ContinuousLocationRequest从API version 12开始支持,简单易用,保举利用ContinuousLocationRequest举行配置。
开发步骤

持续获取当前位置重要分为以下步骤:


  • 设置位置请求参数ContinuousLocationRequest
  • 开启位置变化订阅locationChange
  • 设置回调接口
核心代码如下所示:
  1. onLocationChange(): void {
  2.   // 设置位置请求参数
  3.   let request: geoLocationManager.ContinuousLocationRequest = {
  4.     interval: 1,
  5.     locationScenario: CommonConstants.NAVIGATION
  6.   };
  7.   try {
  8.     // 开启位置变化订阅
  9.     geoLocationManager.on('locationChange', request, this.locationChange);
  10.   } catch (err) {
  11.     promptAction.showToast({
  12.       message: JSON.stringify(err),
  13.       duration: CommonConstants.TWO_THOUSAND
  14.     });
  15.   }
  16. }
  17.   
  18. // 回调接口
  19. locationChange = (location: geoLocationManager.Location): void => {
  20.   this.getAddress({
  21.     latitude: location.latitude,
  22.     longitude: location.longitude
  23.   });
  24. }
复制代码
背景定位

场景描述

背景定位常用于应用切换到背景后,应用须要继承定位的场景。背景定位的功能须要获取ohos.permission.LOCATION_IN_BACKGROUND权限,同时须要申请长时任务。
核心代码

  1. let context = getContext(this) as common.UIAbilityContext;
  2.     let wantAgentInfo: wantAgent.WantAgentInfo = {
  3.       // 点击通知后,将要执行的动作列表
  4.       wants: [
  5.         {
  6.           bundleName: context.abilityInfo.bundleName,
  7.           abilityName: context.abilityInfo.name
  8.         }
  9.       ],
  10.       operationType: wantAgent.OperationType.START_ABILITY,
  11.       requestCode: 0,
  12.       wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
  13.     }
  14.     wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
  15.       backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj)
  16.         .then(() => {
  17.           console.log('cwq start background task success');
  18.           this.startLocation()
  19.         })
  20.         .catch((err: BusinessError) => {
  21.           console.error(`cwq Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
  22.         });
  23.     }).catch((err: BusinessError) => {
  24.       console.error(`cwq Failed to operation getWantAgent. Code is ${err.code}, message is ${err.message}`);
  25.     });
  26.   }
  27. startLocation() {
  28.     console.log('cwq start location');
  29.     let locationChange = (location: geoLocationManager.Location): void => {
  30.       console.log('cwq locationChanger: data: ' + JSON.stringify(location));
  31.     };
  32.     let requestInfo: geoLocationManager.LocationRequest = {
  33.       'scenario': geoLocationManager.LocationRequestScenario.NAVIGATION,
  34.       'timeInterval': 0,
  35.       'distanceInterval': 0,
  36.       'maxAccuracy': 0
  37.     };
  38.     geoLocationManager.on('locationChange', requestInfo, locationChange);
  39.   }
复制代码
常见题目

位置定位有偏差


  • 华为地图在中国大陆、中国香港和中国澳门利用GCJ02坐标系,若利用WGS84坐标系直接叠加在华为地图上,因坐标值差别,展示位置会有偏移。所以,在中国大陆、中国香港和中国澳门如果利用WGS84坐标调用Map Kit服务,须要先将其转换为GCJ02坐标系再访问。
  • 网络定位的精度较差,可能会有较大偏差。
  • 如果利用的是GNSS定位,在室内等强掩藏定位场景下,无法提供正确的位置服务。
先利用getCurrentLocation获取定位,再利用getLastLocation获取定位,两个值不同等

场景描述
用getCurrentLocation获取到的定位后,再利用getLastLocation获取到的位置和原来的值不一样
可能原因
定位缓存所有应用用的都是一份,有可能中间有其它应用定位把缓存位置刷新了。
办理方案
可以对比一下获取的时间,根据时间判定是否有更新。

欢迎大家评论留言,讨论!有其他开发方案也可以分享给我!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

守听

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表