​ 简介

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参数


    
        名称
        类型
        可读
        可写
        说明
    
    
        latitude
        number
        是
        否
        表示纬度信息,正值表示北纬,负值表示南纬。取值范围为-90到90。仅支持WGS84坐标系。
    
    
        longitude
        number
        是
        否
        表示经度信息,正值表示东经,负值表是西经。取值范围为-180到180。仅支持WGS84坐标系。
    
    
        altitude
        number
        是
        否
        表示高度信息,单位米。
    
    
        accuracy
        number
        是
        否
        表示精度信息,单位米。
    
    
        speed
        number
        是
        否
        表示速度信息,单位米每秒。
    
    
        timeStamp
        number
        是
        否
        表示位置时间戳,UTC格式。
    
    
        direction
        number
        是
        否
        表示航向信息。单位是“度”,取值范围为0到360。
    
    
        timeSinceBoot
        number
        是
        否
        表示位置时间戳,开机时间格式。
    
    
        additions
        Array<string>
        是
        否
        附加信息。
    
    
        additionSize
        number
        是
        否
        附加信息数量。取值范围为大于等于0。
    
    
        additionsMap12+
        Map<string, string>
        是
        否
        附加信息。具体内容和顺序与additions一致。该字段暂未实现。
    
    
        altitudeAccuracy12+
        number
        是
        否
        表示高度信息的精度,单位米。
    
    
        speedAccuracy12+
        number
        是
        否
        表示速度信息的精度,单位米每秒。
    
    
        directionAccuracy12+
        number
        是
        否
        表示航向信息的精度。单位是“度”,取值范围为0到360。
    
    
        uncertaintyOfTimeSinceBoot12+
        number
        是
        否
        表示位置时间戳的不确定度。
    
    
        sourceType12+
        LocationSourceType
        是
        否
        表示定位结果的来源。
    




单次获取设备定位信息

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

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

以下是完整的代码

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:导航场景。需要高定位精度和实时性能。
    1. SPORT:运动场景。要求高定位精度。
    1. TRANSPORT:运输场景。需要高定位精度和实时性能。
    1. TRANSPORT:运输场景。需要高定位精度和实时性能。
    1. 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;

}
}

图片


奥尼ᴮᴵᴹᵉʳ
1 声望0 粉丝