【HarmonyOS学习】定位相关知识(Locationkit)

news2024/11/14 13:56:01

简介

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

在这里插入图片描述

单次获取设备定位信息

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

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

以下是完整的代码

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;
  }
}

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

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

相关文章

p17面试题

品茗面试题 1.交换两个int变量的值&#xff0c;不能使用第三个变量&#xff0c;即a3,b5,交换后&#xff0c;a5,b3&#xff1b; #include<stdio.h> //int main(){ // //打印函数&#xff0c;引用头文件.stdio.h // printf("hello world\n");//打印函数 …

C++STL详解(二)——string类的模拟实现

首先&#xff0c;我们为了防止命名冲突&#xff0c;我们需要在自己的命名空间内实现string类。 一.string类基本结构 string类的基本结构和顺序表是相似的&#xff0c;结构如下&#xff1a; //.h namespace kuzi {class string{private:char* _str;//字符串size_t _size;//长…

算法基础之回溯法

本文将详细介绍回溯法的基本原理和适用条件&#xff0c;并通过经典例题辅助读者理解回溯法的思想、掌握回溯法的使用。本文给出的例题包括&#xff1a;N皇后问题、子集和问题。 算法原理 在问题的解空间树中&#xff0c;回溯法按照深度优先的搜索策略&#xff0c;从根结点出发…

LDR6020:重塑iPad一体式有线键盘体验的创新力量

在移动办公与娱乐日益融合的时代&#xff0c;iPad凭借其强大的性能和便携性&#xff0c;成为了众多用户不可或缺的生产力工具。然而&#xff0c;为了进一步提升iPad的使用体验&#xff0c;一款高效、便捷的键盘成为了不可或缺的配件。今天&#xff0c;我们要介绍的&#xff0c;…

TYPE-C接口PD取电快充协议芯片ECP5701:支持PD 2.0和PD 3.0(5V,9V,12V,15V,20V)

随着智能设备的普及&#xff0c;快充技术成为了越来越多用户的刚需。而TYPE-C接口作为新一代的USB接口&#xff0c;具有正反插、传输速度快、充电体验好等优点&#xff0c;已经成为了快充技术的主要接口形式。而TYPE-C接口的PD&#xff08;Power Delivery&#xff09;取电快充协…

【数据结构】线性结构——数组、链表、栈和队列

目录 前言 一、数组&#xff08;Array&#xff09; 1.1优点 1.2缺点 1.3适用场景 二、链表&#xff08;Linked List&#xff09; 2.1优点 2.2缺点 2.3适用场景 三、栈&#xff08;Stack&#xff09; 3.1优点 3.2缺点 3.3适用场景 四、队列&#xff08;Queue&#xff09; 4.1优点…

【python】Python高阶函数--reduce函数的高阶用法解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Redis常用的5大数据类型

Reids字符串&#xff08;String&#xff09; 设置相同的key&#xff0c;之前内容会覆盖掉 Redis列表&#xff08;List&#xff09; 常用命令 从左往右放值 数据结构 Redis集合&#xff08;set&#xff09; sadd<key><value1><value2>...... 数据结构 Set数据…

前端组件化开发:以Vue自定义底部操作栏组件为例

摘要 随着前端技术的不断演进&#xff0c;组件化开发逐渐成为提升前端开发效率和代码可维护性的关键手段。本文将通过介绍一款Vue自定义的底部操作栏组件&#xff0c;探讨前端组件化开发的重要性、实践过程及其带来的优势。 一、引言 随着Web应用的日益复杂&#xff0c;传统的…

「豆包Marscode体验官」 | 云端 IDE 启动 Rust 体验

theme: cyanosis 我正在参加「豆包MarsCode初体验」征文活动 MarsCode 可以看作一个运行在服务端的远程 VSCode开发环境。 对于我这种想要学习体验某些语言&#xff0c;但不想在电脑里装环境的人来说非常友好。本文就来介绍一下在 MarsCode里&#xff0c;我的体验 rust 开发体验…

Games101学习笔记 Lecture22 Animation(cont.)

Lecture22 Animation(cont. 一、单个粒子模拟Ordinary Differential Equation ODE 常微分方程ODE求解方法——欧拉方法解决不稳定中点法改进欧拉方法自适应步长隐式欧拉方法 二、流体模拟基于位置的方法物质点方法 一、单个粒子模拟 想模拟粒子在场中的运动 Ordinary Differe…

Token Labeling(NeurIPS 2021, ByteDance)论文解读

paper&#xff1a;All Tokens Matter: Token Labeling for Training Better Vision Transformers official implementation&#xff1a;https://github.com/zihangJiang/TokenLabeling 出发点 ViTs的局限性&#xff1a;尽管ViTs在捕捉长距离依赖方面表现出色&#xff0c; 但…

代码随想录算法训练营第五十八天|108.冗余连接、109.冗余连接II

108.冗余连接 题目链接&#xff1a;108.冗余连接 文档讲解&#xff1a;代码随想录 状态&#xff1a;还行 思路&#xff1a; 并查集可以解决什么问题&#xff1a;两个节点是否在一个集合&#xff0c;也可以将两个节点添加到一个集合中。 题解&#xff1a; public class Main {p…

套用BI方案做数据可视化是种什么体验?

在数字化转型的浪潮中&#xff0c;数据可视化作为连接数据与决策的桥梁&#xff0c;其重要性日益凸显。近期&#xff0c;我有幸体验了奥威BI方案进行数据可视化的全过程&#xff0c;这不仅是一次技术上的探索&#xff0c;更是一次对高效、智能数据分析的深刻感受。 初识奥威&a…

.net dataexcel 脚本公式 函数源码

示例如: ScriptExec(""sum(1, 2, 3, 4)"") 结果等于10 using Feng.Excel.Builder; using Feng.Excel.Collections; using Feng.Excel.Interfaces; using Feng.Script.CBEexpress; using Feng.Script.Method; using System; using System.Collections.Gen…

场景分析法挖掘需求的常见4大步骤

场景分析方法&#xff0c;有助于精确定位需求&#xff0c;优化产品设计&#xff0c;促进团队协同&#xff0c;减少项目风险&#xff0c;提升用户满意度与市场竞争力。若场景分析不足&#xff0c;产品可能偏离用户需求&#xff0c;导致功能冗余或缺失&#xff0c;用户体验差&…

java中传引用问题

在 Java 中&#xff0c;所有对象都是通过引用传递的&#xff0c;而基本数据类型是通过值传递的。 引用传递&#xff1a; 当一个对象作为参数传递给方法时&#xff0c;传递的是对象的引用。对这个对象引用进行的修改会影响到原始对象。例如&#xff1a; public class Test {p…

Designing Data-Intensive Applications数据密集型应用系统设计-读书笔记

目录 第一部分可靠性、可扩展性、可维护性硬件故障描述负载 吞吐与延迟可维护性 第二章 数据模型与查询语言第三章索引哈希索引B-tree事务 第三章 编码第二部分、分布式数据系统第五章 数据复制单主从复制节点失效日志实现复制滞后问题 多主节点复制 第六章、数据分区3 第一部分…

10个常见的电缆载流表,值得收藏!

众所周知,电线电缆的载流是所有电工、电气人员都必须具备的基本储备,但是如果要将那么多的“数字”都记得清清楚楚,还是有一点困难的!今天咱们就做了一个电力电缆载流量对照表,速度收藏!下次参考不迷路! 1、0.6/1KV聚氯乙烯绝缘电力电缆载流量 以上电缆载流量计算条件:…

世界启动Ⅳ--利用AI和费曼技巧学习一切

前言 有无数的学习技巧可以帮助你消化复杂的概念&#xff0c;并有信心记住它们。如果你像我一样是一个不断学习的学生&#xff0c;你就会明白有效学习方法的重要性。其中最简单的一种就是费曼技巧。 在本文中&#xff0c;我将解释如何有效地应用费曼学习方法&#xff0c;以及…