鸿蒙 Location Kit(位置服务)

移动终端设备已经深入人们日常生活的方方面面,如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录。这些习以为常的活动,都离不开定位用户终端设备的位置。

Location Kit 使用多种定位技术提供服务,可以准确地确定设备在室外/室内的位置:

  • 坐标
    系统以 1984 年世界大地坐标系统为参考,使用经度、纬度、海拔高度数据描述地球上的一个位置。
  • GNSS 定位
    全球导航卫星系统,包含:GPS、GLONASS、北斗、Galileo 等,通过导航卫星、设备芯片提供的定位算法,来确定设备准确位置。定位过程具体使用哪些定位系统,取决于用户设备的硬件能力。
  • 基站定位
    根据设备当前驻网基站和相邻基站的位置,估算设备当前位置。此定位方式的定位结果精度相对较低,并且需要设备可以访问蜂窝网络。
  • WLAN、蓝牙定位
    根据设备可搜索到的周围 WLAN、蓝牙设备位置,估算设备当前位置。此定位方式的定位结果精度依赖设备周围可见的固定 WLAN、蓝牙设备的分布,密度较高时,精度也相较于基站定位方式更高,同时也需要设备可以访问网络

申请定位权限

应用在使用 Location Kit 系统能力前,需要检查是否已经获取用户授权访问设备位置信息。如未获得授权,可以向用户申请需要的位置权限。系统提供的定位相关权限有:

  • ohos.permission.LOCATION:用于获取精准位置,精准度在米级别
  • ohos.permission.APPROXIMATELY_LOCATION:用于获取模糊位置,精确度为 5 公里
  • ohos.permission.LOCATION_IN_BACKGROUND:用于应用切换到后台仍然需要获取定位信息的场景

当 APP 运行在前台,访问设备位置信息时,申请位置权限的方式有两种:
获取模糊位置: ohos.permission.APPROXIMATELY_LOCATION
获取精确位置: ohos.permission.APPROXIMATELY_LOCATION + ohos.permission.LOCATION

当 APP 运行在后台时,除了上述两组权限外,还需要申请如下权限:
后台定位权限: ohos.permission.LOCATION_IN_BACKGROUND
或者申请定位类型的长时任务:backgroundModes: "location"

申请用户权限

import {abilityAccessCtrl,bundleManager,common,Permissions,
} from "@kit.AbilityKit";let permissions: Permissions[] = ["ohos.permission.APPROXIMATELY_LOCATION","ohos.permission.LOCATION",
];let accessMgr = abilityAccessCtrl.createAtManager();
const flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION;
const bundleInfo = await bundleManager.getBundleInfoForSelf(flags);
const grantStatus0 = await accessMgr.checkAccessToken(bundleInfo.appInfo.accessTokenId,permissions[0]
);
const grantStatus1 = await accessMgr.checkAccessToken(bundleInfo.appInfo.accessTokenId,permissions[1]
);if (grantStatus0 === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED &&grantStatus1 === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED
) {let results = await accessMgr.requestPermissionsFromUser(getContext(),permissions);if (results.authResults[0] == 0 && results.authResults[1] == 0) {// 通过授权} else {// 拒绝授权}
}

相关接口

接口名功能描述
on(type: 'locationChange', request: LocationRequest | ContinuousLocationRequest, callback: Callback<Location>): void开启位置变化订阅,并发起定位请求,持续性定位
off(type: 'locationChange', callback?: Callback<Location>): void关闭位置变化订阅,并删除对应的定位请求,如果不关闭就会产生内存泄漏
getCurrentLocation(request: CurrentLocationRequest | SingleLocationRequest, callback: AsyncCallback<Location>): void获取当前位置,使用 callback 回调异步返回结果,一次性定位
getCurrentLocation(request?: CurrentLocationRequest | SingleLocationRequest): Promise<Location>获取当前位置,使用 Promise 方式异步返回结果
getLastLocation(): Location获取最近一次定位结果
isLocationEnabled(): boolean判断位置服务是否已经开启

示例

{"module":{"extensionAbilities":["requestPermissions": [//当前应用申请数据和功能的访问权限//系统授予级权限 —— 只需要声明name即可{"name": "ohos.permission.INTERNET"    //互联网访问权限},//用户授予级权限 —— 必须声明name/reason/usedScene三个属性{"name": "ohos.permission.APPROXIMATELY_LOCATION",   //模糊定位"reason": "$string:Location_Reason","usedScene": {"abilities": ["EntryAbility"],"when": "always"}},{"name": "ohos.permission.LOCATION",  //精确定位"reason": "$string:Location_Reason", //当前应用需要向用户解释使用该权限的原因"usedScene": {                       //权限在何种场景下被使用"abilities": ["EntryAbility"],    //哪些Ability/窗口中需要使用该权限"when": "always"  //何时使用该权限  inuse:当前应用在前台运行时需要使用   always:总是需要该权限,即使应用没在运行}}]]}
}
import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit'
import { geoLocationManager } from '@kit.LocationKit'
import { JSON } from '@kit.ArkTS'
import { router } from '@kit.ArkUI'@Entry
@Component
struct Index {//页面显式时,先弹出“申请定位权限”授权窗口async onPageShow() {//① 声明需要用户授权的权限列表let list: Permissions[] = ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION']//② 获得当前应用的“访问令牌”let flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION //需要获得整个应用的信息,而不是模块的/应用组件的let bundleInfo = await bundleManager.getBundleInfoForSelf(flags) //得到当前资源包信息let tokenId = bundleInfo.appInfo.accessTokenId //当前应用的当前分身在当前用户使用场景下,系统分配的令牌编号let atManager = abilityAccessCtrl.createAtManager() //At: Access Token,访问令牌,即当前应用的授权列表let grantStatus0 = await atManager.checkAccessToken(tokenId, list[0])let grantStatus1 = await atManager.checkAccessToken(tokenId, list[1])//③ 从访问令牌中查询,用户是否授予过定位权限if (grantStatus0 == -1 && grantStatus1 == -1) { //0表示已经通过授权了  -1表尚未尚未授权/之前拒绝授权了//④ 如果尚未授权过,则弹出申请授权对话框let result = await atManager.requestPermissionsFromUser(getContext(), list)if (result.authResults[0] == 0) {console.log('1.模糊定位权限已经从用户处申请到')} else {console.log('2.用户拒绝授予模糊定位权限')}if (result.authResults[1] == 0) {console.log('3.精确定位权限已经从用户处申请到')} else {console.log('4.用户拒绝授予精确定位权限')}}}//当页面隐藏时,取消“持续性定位改变监听”onPageHide() {try {geoLocationManager.off('locationChange')console.log('--持续性定位改变监听已经关闭')} catch (err) {console.log('--关闭持续性定位改变监听失败:', JSON.stringify(err))}}build() {Column({ space: 10 }) {Text('首页').fontSize(30)Button('1.获取用户当前的定位信息——一次性定位').onClick(async _ => {if (geoLocationManager.isLocationEnabled()) {console.log('--当前系统已打开定位开关,正在获取位置信息....')let loc = await geoLocationManager.getCurrentLocation()console.log('--成功获取到当前定位信息:', JSON.stringify(loc))if (geoLocationManager.isGeocoderAvailable()) {let address = await geoLocationManager.getAddressesFromLocation(loc)console.log('--当前系统可以进行地理<=>坐标转化',address[0].placeName)} else {console.log('--当前系统无法进行地理<=>坐标转化')}} else {console.log('--当前系统未启用定位服务,请用户打开定位开关!')}})Button('2.获取用户当前的定位信息——持续性定位').onClick(_ => {if (!geoLocationManager.isLocationEnabled()) {console.log('--当前系统没有打开定位开关!')return}let count = 0geoLocationManager.on('locationChange', {}, (loc) => {count++console.log('--当前设备位置改变了:', count, JSON.stringify(loc))})})Button('3.跳转到下一个页面,测试是否仍然监听定位改变').onClick(_ => {router.pushUrl({url: 'pages/Page1'})})}.height('100%').width('100%').padding(10)}
}

地理编码

使用坐标描述一个位置,非常准确,但是并不直观,面向用户表达并不友好。系统向开发者提供了以下两种转化能力:

  • 地理编码转化:将地理描述转化为具体坐标。
  • 逆地理编码转化:将坐标转化为地理描述。

其中地理编码包含多个属性来描述位置,包括国家、行政区划、街道、门牌号、地址描述等等,这样的信息更便于用户理解

import { geoLocationManager } from '@kit.LocationKit'try {if( geoLocationManager.isGeocoderAvailable() ){ //查询地理编码与逆地理编码服务是否可用let loc = {"latitude": 31.12, "longitude": 121.11, ... }let addr = await geoLocationManager.getAddressesFromLocation( loc ) //逆地理编码转化}
} catch (err) {console.error("逆地理编码转化失败:" + JSON.stringify(err));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/81888.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树深搜:在算法森林中寻找路径

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 目录 一、搜索算法 二、回溯算法 三、例题讲解 3.1. 计算布尔二叉树的值 3.2. 求根节点到叶节点数字之和 3.3. 二叉树剪枝 3.4. 验证二叉搜索树 3.5. 二叉搜索树中第 K 小的元素 3.6. 二叉树的所有路径 …

企业级AI搜索解决方案:阿里云AI搜索开放平台

随着信息技术的飞速发展&#xff0c;搜索引擎作为信息获取的重要工具&#xff0c;扮演着不可或缺的角色。阿里云 AI 搜索开放平台以其强大的技术支持和灵活的开放性&#xff0c;持续为用户提供高效的搜索解决方案。 一、阿里云 AI 搜索开放平台 一站式的 AI 搜索开放平台作为…

自动驾驶中的预测控制算法:用 Python 让无人车更智能

自动驾驶中的预测控制算法:用 Python 让无人车更智能 自动驾驶技术近年来取得了令人惊叹的进步,AI 与边缘计算的结合让车辆能够实时感知环境、规划路径并执行驾驶决策。其中,预测控制(Model Predictive Control,MPC) 作为一种先进的控制算法,凭借其对未来驾驶行为的优化…

量子计算机超越超级计算机——它们解决了哪些问题?

“ 南加州大学的研究人员取得了重大突破&#xff0c;证明量子计算机在解决某些复杂问题时甚至可以胜过最快的超级计算机。” 量子退火最终显示出扩展优势&#xff0c;得益于错误抑制的量子处理&#xff0c;它比传统超级计算机提供更快、接近最优的解决方案。 南加州大学的研究人…

Java虚拟机 -方法调用

方法调用 方法调用静态链接动态链接案例虚方法与非虚方法虚方法&#xff08;Virtual Method&#xff09;非虚方法&#xff08;Non-Virtual Method&#xff09; 方法返回地址 方法调用 我们编写Java程序的时候&#xff0c;我们自己写的类通常不仅仅是调用自己本类的方法。调用别…

【 开源:跨平台网络数据传输的万能工具libcurl】

在当今这个互联互通的世界中&#xff0c;数据在各种设备和平台之间自由流动&#xff0c;而 libcurl&#xff0c;就像一把跨平台的万能工具&#xff0c;为开发者提供了处理各种网络数据传输任务所需的强大功能。它不仅是一个库&#xff0c;更是一种通用的解决方案&#xff0c;可…

ElasticSearch 8.x 快速上手并了解核心概念

目录 核心概念概念总结 常见操作索引的常见操作常见的数据类型指定索引库字段类型mapping查看索引库的字段类型最高频使用的数据类型 核心概念 在新版Elasticsearch中&#xff0c;文档document就是一行记录(json)&#xff0c;而这些记录存在于索引库(index)中, 索引名称必须是…

优化 CRM 架构,解锁企业竞争力密码

引言 “在所有企业面临的挑战中&#xff0c;客户关系管理无疑是最为关键的一环。” —— 彼得德鲁克 在数字化浪潮席卷的当下&#xff0c;企业面临着前所未有的机遇与挑战。客户关系管理&#xff08;CRM&#xff09;作为企业运营的核心环节&#xff0c;其架构的优劣直接影响着…

深入理解Docker和K8S

深入理解Docker和K8S Docker 是大型架构的必备技能&#xff0c;也是云原生核心。Docker 容器化作为一种轻量级的虚拟化技术&#xff0c;其核心思想&#xff1a;将应用程序及其所有依赖项打包在一起&#xff0c;形成一个可移植的单元。 容器的本质是进程&#xff1a; 容器是在…

list.forEach(s -> countService.refreshArticleStatisticInfo(s.getId())); 讲解一下语法

这段代码使用了Java中的forEach方法结合Lambda表达式来遍历一个列表&#xff0c;并对列表中的每个元素执行特定操作。具体来说&#xff0c;它会遍历列表中的每一个元素&#xff0c;并调用countService.refreshArticleStatisticInfo(s.getId())方法来刷新每个文章的统计信息。下…

AI开发者的算力革命:GpuGeek平台全景实战指南(大模型训练/推理/微调全解析)

目录 背景一、AI工业化时代的算力困局与破局之道1.1 中小企业AI落地的三大障碍1.2 GpuGeek的破局创新1.3 核心价值 二、GpuGeek技术全景剖析2.1 核心架构设计 三、核心优势详解‌3.1 优势1&#xff1a;工业级显卡舰队‌‌‌3.2 优势2&#xff1a;开箱即用生态‌3.2.1 预置镜像库…

05算法学习_59. 螺旋矩阵 II

05算法学习_59. 螺旋矩阵 II 05算法学习_59. 螺旋矩阵 II题目描述&#xff1a;个人代码&#xff1a;学习思路&#xff1a;第一种写法&#xff1a;题解关键点&#xff1a; 个人学习时疑惑点解答&#xff1a; 05算法学习_59. 螺旋矩阵 II 力扣题目链接: 59. 螺旋矩阵 II 题目描…

JDK7Hashmap的头插法造成的环问题

单线程下的扩容 多线程下的扩容 next&#xff1d;e 然后e的next变成e

JAVA|后端编码规范

目录 零、引言 一、基础 二、集合 三、并发 四、日志 五、安全 零、引言 规范等级&#xff1a; 【强制】&#xff1a;强制遵守&#xff0c;来源于线上历史故障&#xff0c;将通过工具进行检查。【推荐】&#xff1a;推荐遵守&#xff0c;来源于日常代码审查、开发人员反馈…

2025-05-21 Python深度学习5——数据读取

文章目录 1 数据准备2 Dataset2.1 自定义 Dataset2.2 使用示例 3 TensorBoard3.1 安装3.2 标量可视化&#xff08;Scalars&#xff09;3.3 图像可视化&#xff08;Images&#xff09;3.4 其他常用功能 4 transform4.1 ToTensor()4.2 Normalize()4.3 Resize()4.4 Compose()4.5 C…

5月21日学习笔记

MYSQL三层结构 表1 数据库DB1 表2 数据库管理系统 客户端命令终端&#xff08;Dos&#xff09; DBMS 数据库DB2 表1 表2 数据库………. Mysql数据库-表的本质仍然是文件 表的一行称之为一条记录->在java程序中一行记录往往使用对象表示 SQL语…

二十、面向对象底层逻辑-ServiceRegistry接口设计集成注册中心

一、服务治理的基石接口 在微服务架构中&#xff0c;服务实例的动态注册与发现是保证系统弹性的关键机制。Spring Cloud Commons模块通过ServiceRegistry与Registration接口定义了服务注册的标准化模型&#xff0c;为不同服务发现组件&#xff08;Eureka、Consul、Nacos等&…

DeepSeek:以开源之力,引领AI技术新风潮

在年春节&#xff0c;大语言模型DeepSeek如同一枚震撼弹&#xff0c;在全球范围内引发了轰动&#xff0c;成功“破圈”&#xff0c;将中国的人工智能&#xff08;AI&#xff09;技术成果推向了世界舞台。 开源策略&#xff1a;打破技术壁垒 在AI行业&#xff0c;OpenAI等巨头…

完整改进RIME算法,基于修正多项式微分学习算子Rime-ice增长优化器,完整MATLAB代码获取

1 简介 为了有效地利用雾状冰生长的物理现象&#xff0c;最近开发了一种优化算法——雾状优化算法&#xff08;RIME&#xff09;。它模拟硬雾状和软雾状过程&#xff0c;构建硬雾状穿刺和软雾状搜索机制。在本研究中&#xff0c;引入了一种增强版本&#xff0c;称为修改的RIME…

PyTorch可视化工具——使用Visdom进行深度学习可视化

文章目录 前置环境Visdom安装并启动VisdomVisdom图形APIVisdom静态更新API详解通用参数说明使用示例Visdom动态更新API详解1. 使用updateappend参数2. ~~使用vis.updateTrace方法~~3. 完整训练监控示例 Visdom可视化操作散点图plot.scatter()散点图案例线性图vis.line()vis.lin…