一、简介
位置服务提供GNSS定位、网络定位(蜂窝基站、WLAN、蓝牙定位技术)、地理编码、逆地理编码、国家码和地理围栏等基本功能。
使用位置服务时请打开设备"位置"开关。如果"位置"开关关闭并且代码未设置捕获异常,可能导致应用异常。
二、申请位置权限
2.1 场景概述
应用在使用Location Kit系统能力前,需要检查是否已经获取用户授权访问设备位置信息。如未获得授权,可以向用户申请需要的位置权限。
系统提供的定位权限有:
- ohos.permission.LOCATION:用于获取精准位置,精准度在米级别。
- ohos.permission.APPROXIMATELY_LOCATION:用于获取模糊位置,精确度为5公里。
- ohos.permission.LOCATION_IN_BACKGROUND:用于应用切换到后台仍然需要获取定位信息的场景。
2.2 开发步骤
- 开发者可以在应用配置文件中声明所需要的权限并向用户申请授权,具体可参考向用户申请授权。
- 当APP运行在前台,且访问设备位置信息时,申请位置权限的方式如下:
申请位置权限的方式 | 是否允许申请 | 申请成功后获取的位置的精确度 |
---|---|---|
申请ohos.permission.APPROXIMATELY_LOCATION | 是 | 获取到模糊位置,精确度为5公里。 |
同时申请ohos.permission.APPROXIMATELY_LOCATION和ohos.permission.LOCATION | 是 | 获取到精准位置,精准度在米级别。 |
当APP运行在后台时,申请位置权限的方式如下:
如果应用在后台运行时也需要访问设备位置,除了按照步骤2申请权限外,还需要申请LOCATION类型的长时任务。
三、导入模块
c
import { geoLocationManager } from '@kit.LocationKit';
四、示例
效果图
示例代码
c
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { geoLocationManager } from '@kit.LocationKit';
import { intl } from '@kit.LocalizationKit';
async function checkPermissionGrant(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.error(`获取应用程序的accessTokenID Failed to get bundle info for self. Code is ${err.code}, message is ${err.message}`);
}
// 校验应用是否被授予权限
try {
grantStatus = await atManager.checkAccessToken(tokenId, permission);
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`校验应用是否被授予权限 Failed to check access token. Code is ${err.code}, message is ${err.message}`);
}
return grantStatus;
}
async function checkPermissions(context: common.UIAbilityContext): Promise<void> {
let grantStatus1: boolean = await checkPermissionGrant('ohos.permission.LOCATION') ===
abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED; // 获取精确定位权限状态
let grantStatus2: boolean = await checkPermissionGrant('ohos.permission.APPROXIMATELY_LOCATION') ===
abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED; // 获取模糊定位权限状态
// 精确定位权限只能跟模糊定位权限一起申请,或者已经有模糊定位权限才能申请精确定位权限
if (grantStatus2 && !grantStatus1) {
// 申请精确定位权限
reqPermissionsFromUser(permissionsOne, context)
} else if (!grantStatus1 && !grantStatus2) {
// 申请模糊定位权限与精确定位权限或单独申请模糊定位权限
reqPermissionsFromUser(permissionsTow, context)
} else {
// 已经授权,可以继续访问目标操作
getCurrentLocation()
}
}
const permissionsOne: Array<Permissions> = ['ohos.permission.LOCATION'];
const permissionsTow: Array<Permissions> = ['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'];
// 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
for (let i = 0; i < length; i++) {
if (grantStatus[i] === 0) {
// 用户授权,可以继续访问目标操作
} else {
// 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
return;
}
}
// 授权成功
getCurrentLocation()
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
})
}
function getCurrentLocation() {
// 实例化位置信息请求对象,确认当前定位策略。以实例化SingleLocationRequest对象为例,将其定位方式优先级设置为快速获取位置优先,定位超时时间设置为10秒
let request: geoLocationManager.SingleLocationRequest = {
locatingPriority: geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,
locatingTimeoutMs: 10000
};
// 根据定位策略,调用getCurrentLocation()接口获取当前位置信息
geoLocationManager.getCurrentLocation(request).then((location: geoLocationManager.Location) => {
// Receive the reported location through the promise.
const latitude = location.latitude;// 纬度
const longitude = location.longitude;// 经度
const speed = location.speed;
const accuracy = location.accuracy;// 精度
const sourceType = location.sourceType;// 定位来源
const direction = location.direction;// 表示航向信息。单位是"度",取值范围为0到360。
const timeStamp = location.timeStamp;
let dateFormat8 = new intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
let formattedTimeDate = dateFormat8.format(new Date(timeStamp))
formattedTimeDate = formattedTimeDate.replaceAll('/', ".");// 2025.04.03 18:16:08
console.log(`formattedTimeDate = ${formattedTimeDate} 获取当前位置信息 latitude = ${latitude} , longitude = ${longitude}, speed = ${speed}, accuracy = ${accuracy} , sourceType = ${sourceType} , direction = ${direction}`);
}).catch((err: BusinessError) => {
console.log(`获取当前位置信息 getCurrentLocationPosition failed, code: ${err.code}, message: ${err.message}`)
});
// 调用getAddressesFromLocation()接口进行逆地理编码转化,将位置坐标信息转换为对应的地理位置描述。
// geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
// if (data) {
// this.address = data[0]?.placeName || '';
// // ...
// } else {
// console.log(`将位置坐标信息转换为对应的地理位置描述 getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`)
// }
// });
}
@Entry
@Component
struct TestLocation {
@State message: string = '当前位置信息';
private context = getContext(this) as common.UIAbilityContext;
build() {
Column({ space: 10 }) {
Text(this.message)
.id('TestLocationMapHelloWorld')
.fontSize(20)
.fontWeight(FontWeight.Medium)
Button("获取位置信息")
.fontColor(Color.Black)
.fontSize(20).onClick(() => {
checkPermissions(this.context)
})
}
.height('100%')
.width('100%')
.margin({ top: 50 })
}
}