简介
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;// 获取应用程序的accessTokenIDlet 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;}
}