简介
LocationKit提供了定位服务、地理围栏、地理编码、逆地理编码和国家码等功能。
可以实现点击获取用户位置信息、持续获取位置信息和区域进出监控等多项功能。
需要注意,需要确定用户已经开启定位信息,一下的代码没有做这一步的操作,默认开启了。
权限
如果应用需要在后台运行时访问设备位置,还需要申请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;
}
}
写在最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、openHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V3.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
《鸿蒙进阶实战》
●ArkTS实践
●UIAbility应用
●网络案例
……