【HarmonyOS学习】定位相关知识(Locationkit)

avatar
作者
筋斗云
阅读量:0

简介

LocationKit提供了定位服务、地理围栏、地理编码、逆地理编码和国家码等功能。

可以实现点击获取用户位置信息、持续获取位置信息和区域进出监控等多项功能。

需要注意,需要确定用户已经开启定位信息,一下的代码没有做这一步的操作,默认开启了。

权限

申请位置权限的方式位置的精确度
只申请ohos.permission.APPROXIMATELY_LOCATION获取到模糊位置,精确度为5公里。
同时申请ohos.permission.APPROXIMATELY_LOCATION 和ohos.permission.LOCATION获取到精准位置,精准度在米级别。

如果应用需要在后台运行时访问设备位置,还需要申请ohos.permission.LOCATION_IN_BACKGROUND权限。

这里强烈推荐大家去使用 旺旺崔冰冰 大佬的工具库(ef-tool)以下的权限获取代码来自大佬的工具库权限相关的代码。

import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; import { bundleManager, common } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit';  export class AuthUtil {   /**    * 判断是否授权    * @param permissions  待判断的权限    * @returns 已授权true,未授权false    */   static async checkPermissions(permissions: Permissions): Promise<boolean> {     //判断是否授权     let grantStatus: abilityAccessCtrl.GrantStatus = await AuthUtil.checkAccessToken(permissions);     if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {       //已经授权       return true;     } else {       //未授权       return false;     }   }    /**    * 发起授权    * @param permissions  需要授权的权限    * @param callBack  授权成功后的回调,1为用户同意授权,-1为用户拒绝授权    * @returns    */   static async reqPermissionsFromUser(permissions: Permissions, callBack: (index: number) => void): Promise<void> {     let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();     // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗     let request = await atManager.requestPermissionsFromUser(getContext() as common.UIAbilityContext, [permissions]);     let grantStatus: Array<number> = request.authResults;     let length: number = grantStatus.length;     for (let i = 0; i < length; i++) {       if (grantStatus[i] === 0) {         // 用户授权,可以继续访问目标操作         callBack(1);       } else {         callBack(-1);         // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限         return;       }     }   }    /**    * 发起授权 以Promise方式返回    * @param permissions 需要授权的权限    * @returns 1表示授权成功继续业务操作,-1表示用户拒绝授权    */   static async reqPermissions(permissions: Permissions): Promise<number> {     let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();     // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗     let request = await atManager.requestPermissionsFromUser(getContext() as common.UIAbilityContext, [permissions]);     let grantStatus: Array<number> = request.authResults;     let length: number = grantStatus.length;     for (let i = 0; i < length; i++) {       if (grantStatus[i] === 0) {         // 用户授权,可以继续访问目标操作         return 1;       } else {         // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限         return -1;       }     }     return -1;   }    /**    * 检查是否授权    * @param permission 待检查权限    * @returns 授权状态    */   private static async checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {     let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();     let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;     // 获取应用程序的accessTokenID     let tokenId: number = 0;     try {       let bundleInfo: bundleManager.BundleInfo =         await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);       let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;       tokenId = appInfo.accessTokenId;     } catch (error) {       const err: BusinessError = error as BusinessError;       console.log('获取应用绑定包信息失败:原因为:' + err.message)     }     // 校验应用是否被授予权限     try {       grantStatus = await atManager.checkAccessToken(tokenId, permission);     } catch (error) {       const err: BusinessError = error as BusinessError;       console.log('校验授权信息失败:原因为:' + err.message)     }      return grantStatus;   } } 

定位信息Location参数

在这里插入图片描述

单次获取设备定位信息

有两种方式,分别是获取系统缓存的最新位置和获取当前位置。

获取缓存的位置,可以减少系统功耗。如果对时间精度要求较高,直接获取当前位置较好。

以下是完整的代码

import { geoLocationManager } from '@kit.LocationKit'; import { BusinessError } from '@kit.BasicServicesKit' import json from '@ohos.util.json'; import { AuthUtil } from '../Util/AuthUtil'; import { Permissions } from '@kit.AbilityKit';  @Entry @Component struct Index {   locationPermissions: Permissions = 'ohos.permission.LOCATION'   locationMatelyPermissions: Permissions = 'ohos.permission.APPROXIMATELY_LOCATION'    async aboutToAppear(): Promise<void> {     let permissionResult = await this.CheckPermission();     if (!permissionResult) {       //这里需要指引用户二次开启       return;     }   }    /**    * 查看缓存中的位置    */   GetLastLocation() {     //查看系统缓存的最新位置     let location = geoLocationManager.getLastLocation();     console.log(json.stringify(location))   }    /**    * 查看当前最新位置    *    *locatingPriority 有两个相关标签    *  1.geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED ->如果对定位速度要求较高建议使用这个    *  2.geoLocationManager.LocatingPriority.PRIORITY_ACCURACY ->如果对位置的返回精度要求较高使用这个    * locatingTimeoutMs 单次定位时间,建议10S    */   GetSingleLocation() {     let request: geoLocationManager.SingleLocationRequest = {       'locatingPriority': geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,       'locatingTimeoutMs': 10000     }     try {       geoLocationManager.getCurrentLocation(request).then(         (result) => { // 调用getCurrentLocation获取当前设备位置,通过promise接收上报的位置           console.log('current location: ' + JSON.stringify(result));         })         .catch((error: BusinessError) => { // 接收上报的错误码           console.error('promise, getCurrentLocation: error=' + JSON.stringify(error));         });     } catch (err) {       console.error("errCode:" + JSON.stringify(err));     }   }       build() {     Column() {       Button("查看系统中缓存的最新位置")         .width(220)         .height(50)         .margin({ bottom: 40 })         .onClick(() => this.GetLastLocation())       Button("查看最新位置").width(220).height(50)         .margin({ bottom: 40 })         .onClick(() => {           this.GetSingleLocation()         })     }     .height('100%')     .width('100%')     .justifyContent(FlexAlign.Center)   }    /**    * 检查定位权限是否添加    * @returns true为已经添加,false为未添加    */   private async CheckPermission(): Promise<boolean> {     let result: boolean = true;     let locationPermissionCheck = await AuthUtil.checkPermissions(this.locationPermissions)     if (!locationPermissionCheck) {       AuthUtil.reqPermissionsFromUser(this.locationPermissions, (index: number) => {         if (index === -1) {           result = false;         }       })     }     if (!result) {       return result;     }     let locationMatelyPermissionCheck = await AuthUtil.checkPermissions(this.locationMatelyPermissions)     if (!locationMatelyPermissionCheck) {       AuthUtil.reqPermissionsFromUser(this.locationMatelyPermissions, (index: number) => {         if (index === -1) {           result = false;         }       })     }     return result;   } } 

持续获取设备定位信息

import { geoLocationManager } from '@kit.LocationKit'; import { BusinessError } from '@kit.BasicServicesKit' import json from '@ohos.util.json'; import { AuthUtil } from '../Util/AuthUtil'; import { Permissions } from '@kit.AbilityKit';  @Entry @Component struct Index {   locationPermissions: Permissions = 'ohos.permission.LOCATION'   locationMatelyPermissions: Permissions = 'ohos.permission.APPROXIMATELY_LOCATION'    async aboutToAppear(): Promise<void> {     let permissionResult = await this.CheckPermission();     if (!permissionResult) {       //这里需要指引用户二次开启       return;     }   }    /**    * 持续定位(ContinuousLocationRequest对象)    *    * interval-> 上报位置信息的时间间隔,单位是秒    *    * locationScenario ->用户活动场景枚举    * 1. NAVIGATION:导航场景。需要高定位精度和实时性能。    * 2. SPORT:运动场景。要求高定位精度。    * 3. TRANSPORT:运输场景。需要高定位精度和实时性能。    * 4. TRANSPORT:运输场景。需要高定位精度和实时性能。    * 5. DAILY_LIFE_SERVICE:日常生活场景。定位精度要求低。    */   OpenContinuosLocation() {     let request: geoLocationManager.ContinuousLocationRequest = {       'interval': 1,       'locationScenario': geoLocationManager.UserActivityScenario.NAVIGATION     }     let locationCallback = (location: geoLocationManager.Location): void => {       console.log('定位信息: ' + JSON.stringify(location));     };     try {       geoLocationManager.on('locationChange', request, locationCallback);     } catch (err) {       console.error("errCode:" + JSON.stringify(err));     }   }    /**    * 关闭持续定位    */   ClosedContinuosLocation() {     geoLocationManager.off('locationChange', (loca: geoLocationManager.Location) => {       console.log("持续定位关闭");       console.log("最后一次定位" + json.stringify(loca));     })   }    build() {     Column() {       Button("开启持续定位").width(220).height(50)         .margin({ bottom: 40 })         .onClick(() => {           this.OpenContinuosLocation()         })       Button("关闭持续定位").width(220).height(50)         .margin({ bottom: 40 })         .onClick(() => {           this.ClosedContinuosLocation()         })     }     .height('100%')     .width('100%')     .justifyContent(FlexAlign.Center)   }    /**    * 检查定位权限是否添加    * @returns true为已经添加,false为未添加    */   private async CheckPermission(): Promise<boolean> {     let result: boolean = true;     let locationPermissionCheck = await AuthUtil.checkPermissions(this.locationPermissions)     if (!locationPermissionCheck) {       AuthUtil.reqPermissionsFromUser(this.locationPermissions, (index: number) => {         if (index === -1) {           result = false;         }       })     }     if (!result) {       return result;     }     let locationMatelyPermissionCheck = await AuthUtil.checkPermissions(this.locationMatelyPermissions)     if (!locationMatelyPermissionCheck) {       AuthUtil.reqPermissionsFromUser(this.locationMatelyPermissions, (index: number) => {         if (index === -1) {           result = false;         }       })     }     return result;   } } 

地理编码地址获取

两种方式:通过经纬度坐标获取和通过详细地址描述获取。

import { geoLocationManager } from '@kit.LocationKit'; import { Permissions } from '@kit.AbilityKit'; import { AuthUtil } from '../Util/AuthUtil';  @Entry @Component struct Loaction_Page2 {   locationPermissions: Permissions = 'ohos.permission.LOCATION'   locationMatelyPermissions: Permissions = 'ohos.permission.APPROXIMATELY_LOCATION'    async aboutToAppear(): Promise<void> {     let permissionResult = await this.CheckPermission();     if (!permissionResult) {       //这里需要指引用户二次开启       return;     }     this.CheckGeoService()   }    LocationToAddress() {     this.CheckGeoService()     let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest =       {         "locale": "zh",         "country": "CN",         "latitude": 40.02099028,         "longitude": 115.96965089,         "maxItems": 1       };     try {       geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, (err, data) => {         if (err) {           console.log('getAddressesFromLocation err: ' + JSON.stringify(err));         } else {           console.log('getAddressesFromLocation data: ' + JSON.stringify(data));         }       });     } catch (err) {       console.error("errCode:" + JSON.stringify(err));     }    }    LocationNameToAddress() {     let geocodeRequest: geoLocationManager.GeoCodeRequest = {       "description": "广东省广州市海珠区阅江西路222号(广州塔站B出口170米左右)",       "maxItems": 1     };     try {       geoLocationManager.getAddressesFromLocationName(geocodeRequest, (err, data) => {         if (err) {           console.log('getAddressesFromLocationName err: ' + JSON.stringify(err));         } else {           console.log('getAddressesFromLocationName data: ' + JSON.stringify(data));         }       });     } catch (err) {       console.error("errCode:" + JSON.stringify(err));     }   }    build() {     Column() {       Button("具体地址得到地理编码").width(220).height(50)         .margin({ bottom: 40 })         .onClick(() => {           this.LocationNameToAddress();         })       Button("具体坐标得到地理编码").width(220).height(50)         .margin({ bottom: 40 })         .onClick(() => {           this.LocationToAddress();         })     }     .height('100%')     .width('100%')     .justifyContent(FlexAlign.Center)   }    /**    * 查询地理编码和逆地理编码是否可用    */   private CheckGeoService(): boolean {     try {       let isAvailable = geoLocationManager.isGeocoderAvailable();       if (isAvailable) {         console.log("地理编码和逆地理编码可用")         return true;       } else {         console.log("地理编码和逆地理编码不可用")         return false;       }     } catch (err) {       console.error("errCode:" + JSON.stringify(err));       return false;     }   }    /**    * 检查定位权限是否添加    * @returns true为已经添加,false为未添加    */   private async CheckPermission(): Promise<boolean> {     let result: boolean = true;     let locationPermissionCheck = await AuthUtil.checkPermissions(this.locationPermissions)     if (!locationPermissionCheck) {       AuthUtil.reqPermissionsFromUser(this.locationPermissions, (index: number) => {         if (index === -1) {           result = false;         }       })     }     if (!result) {       return result;     }     let locationMatelyPermissionCheck = await AuthUtil.checkPermissions(this.locationMatelyPermissions)     if (!locationMatelyPermissionCheck) {       AuthUtil.reqPermissionsFromUser(this.locationMatelyPermissions, (index: number) => {         if (index === -1) {           result = false;         }       })     }     return result;   } } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!