简介
位置定位提供了GNSS定位、网络定位等多种功能。在实际开发场景中,经常会利用位置定位的功能,如都会定位功能、外卖与快递服务及时跟踪配送员位置、汽车及时导航等等。
常见开发场景如下所示:
- 利用精准定位确认具体位置
- 获取历史定位
- 及时获取当前位置
- 背景定位
申请定位权限
场景描述
应用在利用位置本领前,首先须要确认体系的位置开关为开启状态。如果体系位置本领没有开启,应用不能利用定位服务。
其次,装备的位置信息须要想用户申请对应的访问权限,用户授权后,应用才气利用定位服务。须要用户授权的用户如下所示。
- ohos.permission.LOCATION:用于获取精准位置,精准度在米级别。
- ohos.permission.APPROXIMATELY_LOCATION:用于获取含糊位置,精确度为5公里。
- ohos.permission.LOCATION_IN_BACKGROUND:用于应用切换到背景仍然须要获取定位信息的场景。
开发步骤
1.在module.json5中配置须要的权限。
- {
- // ...
- "requestPermissions": [
- {
- "name": "ohos.permission.LOCATION",
- "reason": "$string:location_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.INTERNET",
- "reason": "$string:internet_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.APPROXIMATELY_LOCATION",
- "reason": "$string:fuzzy_location_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- },
- {
- "name": "ohos.permission.LOCATION_IN_BACKGROUND",
- "reason": "$string:location_permission",
- "usedScene": {
- "abilities": [
- "EntryAbility"
- ],
- "when": "inuse"
- }
- }
- ]
- // ...
- }
复制代码 2.详细申请定位权限的代码如下所示。关于权限的申请,详情可以参考向用户申请授权。
- // 引入abilityAccessCtrl
- import { UIAbility, AbilityConstant, Want, abilityAccessCtrl } from '@kit.AbilityKit';
- // ...
- export default class EntryAbility extends UIAbility {
- async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
- Logger.info(TAG, `[Demo] EntryAbility onCreate`);
- let atManager = abilityAccessCtrl.createAtManager();
- try {
- // 申请权限
- atManager.requestPermissionsFromUser(this.context,
- ['ohos.permission.INTERNET', 'ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'])
- .then((data) => {
- Logger.info(TAG, `data: ${JSON.stringify(data)}`);
- })
- .catch((err: BusinessError) => {
- Logger.error(TAG, `err: ${JSON.stringify(err)}`);
- })
- } catch (err) {
- Logger.error(TAG, `catch err->${JSON.stringify(err)}`);
- }
- }
- // ...
- }
-
复制代码 利用精准定位确认具体位置
场景描述
关于位置定位,重要有两种方式GNSS定位和网络定位,如下表所示。
定位方式 | 阐明 | 优点 | GNSS定位 | 基于环球导航卫星体系,包含GPS、GLONASS、北斗、Galileo等,通过导航卫星、装备芯片提供的定位算法,来确定装备正确位置。 | 定位精准 | 网络定位 | 通过网络举行定位,包罗WLAN、蓝牙定位、基站定位。 | 定位速率快 | 位置定位的战略是重要是基于GNSS定位和网络定位实现的,定位精准的战略利用的是GNSS定位,定位快速的战略利用的网络定位。
获取定位信息的接口getCurrentLocation须要设置定位战略和单次定位超时时间,单次定位超时时间建议设置为10秒,定位战略支持两种参数配置,分别是CurrentLocationRequest和SingleLocationRequest。SingleLocationRequest从API version 12开始支持,在实现上更为简单,也是保举的实现方式。CurrentLocationRequest和SingleLocationRequest的定位战略对比如下所示:
参数范例 | 战略 | 值 | 阐明 | CurrentLocationRequest | PRIORITY_ACCURACY | 0x501 | 表现精度优先。(GNSS定位) | PRIORITY_LOCATING_SPEED | 0x502 | 表现快速获取位置优先。(网络定位) | SingleLocationRequest | UNSET | 0x200 | 表现未设置优先级,表现LocationRequestPriority无效。 | ACCURACY | 0x201 | 表现精度优先。(GNSS定位) | LOW_POWER | 0x202 | 表现低功耗优先。(网络定位) | PRIORITY_LOCATING_SPEED | 0x203 | 表现快速获取位置优先,如果应用希望快速拿到一个位置,可以将优先级设置为该字段。 快速定位优先战略会同时利用GNSS定位和网络定位技术。 | 开发步骤
如下流程图所示,利用精准定位确认具体位置分为以下多个步骤。
1.开启体系定位本领,向用户申请位置权限。
2.设置定位战略,确认当前定位的方式。
3.获取当前定位信息。
4.将定位坐标转化为地理描述。
如下代码所示,设置定位的战略为PRIORITY_LOCATING_SPEED,即速率优先,并根据PRIORITY_LOCATING_SPEED的战略调用getCurrentLocation获取当前位置。
- getLocationPosition(): void {
- // 设置LocatingPriority定位策略
- let request: geoLocationManager.SingleLocationRequest = {
- locatingPriority: geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,
- locatingTimeoutMs: CommonConstants.TEN_THOUSAND
- };
- // 根据策略获取当前定位信息
- geoLocationManager.getCurrentLocation(request).then((location: geoLocationManager.Location) => {
- // 位置转化
- this.getAddress({
- latitude: location.latitude,
- longitude: location.longitude
- });
- }).catch((err: BusinessError) => {
- promptAction.showToast({
- message: JSON.stringify(err),
- duration: CommonConstants.TWO_THOUSAND
- });
- });
- }
复制代码 通过getAddressesFromLocation将定位坐标转化为地理描述,代码如下所示:
- async getAddress(location: LocationInter) {
- try {
- // ...
- let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest = {
- locale: getContext(this).resourceManager.getStringSync($r('app.string.language')),
- latitude: location.latitude,
- longitude: location.longitude,
- maxItems: 1
- };
- // 通过getAddressesFromLocation将定位坐标转化为地理描述
- geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
- if (data) {
- this.address = data[0]?.placeName || '';
- this.marker?.setInfoWindowVisible(true)
- this.marker?.setSnippet(this.address)
- } else {
- promptAction.showToast({
- message: JSON.stringify(err),
- duration: CommonConstants.TWO_THOUSAND
- });
- }
- });
- } catch (error) {
- promptAction.showToast({
- message: JSON.stringify(error),
- duration: CommonConstants.TWO_THOUSAND
- });
- }
- }
复制代码 获取历史定位
场景描述
如下图所示,历史定位的缓存是所有应用公用的,应用1和应用2调用getLastLocation获取的缓存是同一个。
开发步骤
通过getLastLocation获取上一次的缓存定位,代码如下所示。
- getPreLocationPosition(): void {
- try {
- let location = geoLocationManager.getLastLocation();
- this.getAddress({
- latitude: location.latitude,
- longitude: location.longitude
- });
- } catch (err) {
- promptAction.showToast({
- message: JSON.stringify(err),
- duration: CommonConstants.TWO_THOUSAND
- });
- }
- }
-
复制代码 持续获取当前位置
场景描述
持续获取当前位置常用于导航、运动轨迹、出行等场景。持续获取须要设置位置请求参数,当前locationChange事件支持LocationRequest和ContinuousLocationRequest两种参数。ContinuousLocationRequest从API version 12开始支持,简单易用,保举利用ContinuousLocationRequest举行配置。
开发步骤
持续获取当前位置重要分为以下步骤:
- 设置位置请求参数ContinuousLocationRequest
- 开启位置变化订阅locationChange
- 设置回调接口
核心代码如下所示:
- onLocationChange(): void {
- // 设置位置请求参数
- let request: geoLocationManager.ContinuousLocationRequest = {
- interval: 1,
- locationScenario: CommonConstants.NAVIGATION
- };
- try {
- // 开启位置变化订阅
- geoLocationManager.on('locationChange', request, this.locationChange);
- } catch (err) {
- promptAction.showToast({
- message: JSON.stringify(err),
- duration: CommonConstants.TWO_THOUSAND
- });
- }
- }
-
- // 回调接口
- locationChange = (location: geoLocationManager.Location): void => {
- this.getAddress({
- latitude: location.latitude,
- longitude: location.longitude
- });
- }
复制代码 背景定位
场景描述
背景定位常用于应用切换到背景后,应用须要继承定位的场景。背景定位的功能须要获取ohos.permission.LOCATION_IN_BACKGROUND权限,同时须要申请长时任务。
核心代码
- let context = getContext(this) as common.UIAbilityContext;
- let wantAgentInfo: wantAgent.WantAgentInfo = {
- // 点击通知后,将要执行的动作列表
- wants: [
- {
- bundleName: context.abilityInfo.bundleName,
- abilityName: context.abilityInfo.name
- }
- ],
- operationType: wantAgent.OperationType.START_ABILITY,
- requestCode: 0,
- wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
- }
- wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
- backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj)
- .then(() => {
- console.log('cwq start background task success');
- this.startLocation()
- })
- .catch((err: BusinessError) => {
- console.error(`cwq Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
- });
- }).catch((err: BusinessError) => {
- console.error(`cwq Failed to operation getWantAgent. Code is ${err.code}, message is ${err.message}`);
- });
- }
- startLocation() {
- console.log('cwq start location');
- let locationChange = (location: geoLocationManager.Location): void => {
- console.log('cwq locationChanger: data: ' + JSON.stringify(location));
- };
- let requestInfo: geoLocationManager.LocationRequest = {
- 'scenario': geoLocationManager.LocationRequestScenario.NAVIGATION,
- 'timeInterval': 0,
- 'distanceInterval': 0,
- 'maxAccuracy': 0
- };
- geoLocationManager.on('locationChange', requestInfo, locationChange);
- }
-
复制代码 常见题目
位置定位有偏差
- 华为地图在中国大陆、中国香港和中国澳门利用GCJ02坐标系,若利用WGS84坐标系直接叠加在华为地图上,因坐标值差别,展示位置会有偏移。所以,在中国大陆、中国香港和中国澳门如果利用WGS84坐标调用Map Kit服务,须要先将其转换为GCJ02坐标系再访问。
- 网络定位的精度较差,可能会有较大偏差。
- 如果利用的是GNSS定位,在室内等强掩藏定位场景下,无法提供正确的位置服务。
先利用getCurrentLocation获取定位,再利用getLastLocation获取定位,两个值不同等
场景描述
用getCurrentLocation获取到的定位后,再利用getLastLocation获取到的位置和原来的值不一样
可能原因
定位缓存所有应用用的都是一份,有可能中间有其它应用定位把缓存位置刷新了。
办理方案
可以对比一下获取的时间,根据时间判定是否有更新。
欢迎大家评论留言,讨论!有其他开发方案也可以分享给我!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |