Location Kit简介

位置子系统使用多种定位技术提供服务,如GNSS定位、基站定位、WLAN/蓝牙定位(基站定位、WLAN/蓝牙定位后续统称“网络定位技术”);通过这些定位技术,无论用户设备在室内或是户外,都可以准确地确定设备位置。
Location Kit除了提供基础的定位服务之外,还提供了地理围栏、地理编码、逆地理编码、国家码等功能和接口。

步骤

1.权限申请

在使用Location Kit系统能力前,需要获取user_grant权限,这个有点烦,所以我封装成了可以直接用的
系统提供的定位权限有:

  • ohos.permission.LOCATION:用于获取精准位置,精准度在米级别。
  • ohos.permission.APPROXIMATELY_LOCATION:用于获取模糊位置,精确度为5公里。
  • ohos.permission.LOCATION_IN_BACKGROUND:用于应用切换到后台仍然需要获取定位信息的场景。
    我们要申请权限首先在module.json5中的module中添加如下权限信息:

    HarmonyOS Next 中user_grant权限的申请以及Location Kit部分功能的整理封装-鸿蒙开发者社区

{
  "module": {
    "requestPermissions":[
      {
        "name" : "ohos.permission.APPROXIMATELY_LOCATION",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "EntryAbility",
          ],
          "when":"inuse"
        }
      },
      {
        "name" : "ohos.permission.LOCATION",
        "reason": "$string:reason",
        "usedScene": {
          "abilities": [
            "EntryAbility",
          ],
          "when":"inuse"
        }
      }
    ]
  }
}

我们添加完这个权限后,发现$string:reason会出现红色报错,这个时我们需要在string.json中对reason值进行一个设置,如下

{
      "name": "reason",
      "value": "reason"
    }

    HarmonyOS Next 中user_grant权限的申请以及Location Kit部分功能的整理封装-鸿蒙开发者社区


    这样权限都声明好了,然后就需要用户同意我们权限的申请了,我也给整理封装好了,拿过来直接就可以用

    同时这个权限申请不光Location Kit可以使用,其他需要的user_grant权限申请也可以使用,比如相机权限,日历权限等,只不过需要更改一下permissions的内容

    import { abilityAccessCtrl, Permissions,common } from '@kit.AbilityKit';
    import { BusinessError } from '@kit.BasicServicesKit'
    
    
    // 权限申请 里面放我们刚刚在module.json5中申请的几个权限,不光Location Kit可以使用,其他需要的user_grant权限申请也可以更改一下这个值,直接使用
    export const permissions: Array<Permissions> = ['ohos.permission.LOCATION','ohos.permission.APPROXIMATELY_LOCATION'];
    
    // 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContext
    export  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;
          }
        }
        // 授权成功
      }).catch((err: BusinessError) => {
        console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
      })
    }
    

    接着我们就需要在页面的生命周期函数中运行这个代码
    我的文件结构为:
     

    HarmonyOS Next 中user_grant权限的申请以及Location Kit部分功能的整理封装-鸿蒙开发者社区


    PermissionsRequest.ets为刚刚的代码存放的位置,index.ets为我的主页面,可以根据自己的需求进行更改

    先要加载这个文件

    import {reqPermissionsFromUser,permissions} from './PermissionsRequest'
    

      然后在aboutToAppear() 函数中运行刚刚封装的内容,aboutToAppear() 为页面创建时调用的生命周期函数,这样我们加载这个页面的时候就会申请权限,可以让用户进行同意

      import { geoLocationManager } from '@kit.LocationKit';
      import { common } from '@kit.AbilityKit';
      import {reqPermissionsFromUser,permissions} from './PermissionsRequest'
      
      @Entry
      @Component
      struct Index {
          
        aboutToAppear() {
          const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
          reqPermissionsFromUser(permissions, context);
        }
      
      
        build() {}
      
      }
      
      

        这样申请权限的部分就解决了,进入应用时会跳出申请权限的弹窗,就像下面这样

        HarmonyOS Next 中user_grant权限的申请以及Location Kit部分功能的整理封装-鸿蒙开发者社区

        2.获取位置信息整理封装

        单次获取位置信息

        方式一:获取系统缓存的最新位置。

        如果系统当前没有缓存位置会返回错误码。

        推荐优先使用该接口获取位置,可以减少系统功耗。

        如果对位置的新鲜度比较敏感,可以先获取缓存位置,将位置中的时间戳与当前时间对比,若新鲜度不满足预期可以使用方式二获取位置。

        导入包

        import { geoLocationManager } from '@kit.LocationKit';
        import { BusinessError } from '@kit.BasicServicesKit'
        

          函数

            SingleGetLocation(){
              try {
                let location = geoLocationManager.getLastLocation();
                console.log("zzx - " + JSON.stringify(location))
              } catch (err) {
                console.error("zzx - errCode:" + JSON.stringify(err));
              }
            }
          

            使用方法:

            直接调用 SingleGetLocation()就可以

            比如在页面创建时就调用:

              aboutToAppear() {
                this.SingleGetLocation()
              }
            
              方式二:获取当前位置。

              首先要实例化SingleLocationRequest对象,用于告知系统该向应用提供何种类型的位置服务,以及单次定位超时时间。

              • 设置LocatingPriority:

                如果对位置的返回精度要求较高,建议LocatingPriority参数优先选择PRIORITY_ACCURACY,会将一段时间内精度较好的结果返回给应用。

                如果对定位速度要求较高,建议LocatingPriority参数选择PRIORITY_LOCATING_SPEED,会将最先拿到的定位结果返回给应用。

                两种定位策略均会同时使用GNSS定位和网络定位技术,以便在室内和户外场景下均可以获取到位置结果,对设备的硬件资源消耗较大,功耗也较大。

              • 设置locatingTimeoutMs:

                因为设备环境、设备所处状态、系统功耗管控策略等的影响,定位返回的时延会有较大波动,建议把单次定位超时时间设置为10秒。

              导包

              import { geoLocationManager } from '@kit.LocationKit';
              import { BusinessError } from '@kit.BasicServicesKit'
              

                实例化SingleLocationRequest 对象

                let request: geoLocationManager.SingleLocationRequest = {
                   'locatingPriority': geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,
                   'locatingTimeoutMs': 10000
                }
                

                  调用方法

                    SingleGetLocation(){
                      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));
                      }
                    }
                  

                  使用方法:
                  直接调用 SingleGetLocation()就可以
                  比如在页面创建时就调用:

                    aboutToAppear() {
                      this.SingleGetLocation()
                    }
                  

                    持续定位

                    首先要实例化ContinuousLocationRequest对象,用于告知系统该向应用提供何种类型的位置服务,以及位置结果上报的频率。

                    • 设置locationScenario:

                      建议locationScenario参数优先根据应用的使用场景进行设置,该参数枚举值定义参见UserActivityScenario,例如地图在导航时使用NAVIGATION参数,可以持续在室内和室外场景获取位置用于导航。

                    • 设置interval:

                      表示上报位置信息的时间间隔,单位是秒,默认值为1秒。如果对位置上报时间间隔无特殊要求,可以不填写该字段。

                    以地图导航场景为例,调用方式如下:

                    导包:

                    import { geoLocationManager } from '@kit.LocationKit';
                    

                      实例化ContinuousLocationRequest对象和回调函数:

                      let request: geoLocationManager.ContinuousLocationRequest= {
                         'interval': 1,
                         'locationScenario': geoLocationManager.UserActivityScenario.NAVIGATION
                      }
                      let locationCallback = (location:geoLocationManager.Location):void => {
                          // 进行需要进行的操作,更新位置信息等
                         console.log('locationCallback: data: ' + JSON.stringify(location));
                      };
                      

                        封装函数:

                          // 开始定位
                          GetLocation(){
                            try {
                              geoLocationManager.on('locationChange', request, locationCallback);
                            } catch (err) {
                              console.error("errCode:" + JSON.stringify(err));
                            }
                          }
                          // 结束定位
                          stopLocation(){
                            try {
                              geoLocationManager.off('locationChange', locationCallback);
                            } catch (err) {
                              console.error("errCode:" + JSON.stringify(err));
                            }
                          }
                        

                        使用方法:

                        需要在locationCallback中更改我们需要进行的操作

                        然后直接调用GetLocation()和stopLocation()就可以

                        HarmonyOS Next 中user_grant权限的申请以及Location Kit部分功能的整理封装-鸿蒙开发者社区


                        这是我不断获取位置时打印的日志

                        3.获取地址编码转化与逆地址转化整理封装

                        导包

                        import { geoLocationManager } from '@kit.LocationKit';
                        

                          经纬度转地址:

                          封装

                          三个参数分别时经纬度 、指定返回位置信息的最大个数、以及回调函数

                          // 三个参数分别时经纬度 、指定返回位置信息的最大个数、以及回调函数
                          LocationToLocationName(latitude:number,longitude:number,maxItems:number,callback: AsyncCallback<geoLocationManager.GeoAddress[], void>){
                              let reverseGeocodeRequest:geoLocationManager.ReverseGeoCodeRequest = {"latitude": latitude, "longitude": longitude, "maxItems": maxItems};
                              try {
                                geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, callback);
                              } catch (err) {
                                console.error("errCode:" + JSON.stringify(err));
                              }
                            }
                          

                            使用方法:

                            三个参数分别时经纬度 、指定返回位置信息的最大个数、以及回调函数

                                       
                            			this.LocationToLocationName(31.910545929899772,118.89219428752291,1,(err,data)=>{
                                          console.log('getAddressesFromLocation: data=' + JSON.stringify(data));
                                        })
                            

                              地址转经纬度:

                              封装:

                              三个参数分别为地址位置,返回位置信息最大个数以及回调函数

                               LocationNameToLocation(description:string,maxItems:number,callback: AsyncCallback<geoLocationManager.GeoAddress[], void>){
                                  let geocodeRequest:geoLocationManager.GeoCodeRequest = {"description": description, "maxItems": maxItems};
                                  try {
                                    geoLocationManager.getAddressesFromLocationName(geocodeRequest, callback);
                                  } catch (err) {
                                    console.error("errCode:" + JSON.stringify(err));
                                  }
                                }
                              

                                使用方法:

                                this.LocationNameToLocation("xxxxxxxxx",1,(err,data)=>{
                                              console.log('getAddressesFromLocationName data: ' + JSON.stringify(data));
                                            })
                                Logo

                                讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

                                更多推荐