鸿蒙应用开发学习:手机位置信息进阶,从经纬度数据获取地理位置描述信息

一、前言

前几天,我通过学习华为官网的位置服务开发指南,实现了获取手机位置信息的功能,但当时的代码存在两个不足,一是我按照官网的指南使用的是getLastLocation()方法,得到的是最近一次的位置,第一次执行该应用获取到位置信息后,之后再次执行,获取的还是之前的位置信息,与实际位置不符;第二是获取到的位置信息是经度、纬度和海拔等数字信息,不能直管的显示做在的地理位置。

遇到不足,我就希望尽量去解决,这几天通过进一步的学习,我在网上找到了别的网友发布的关于鸿蒙系统获取地理位置的文章,参考他们的文章,我对之前写的代码进行了改进解决了上述两个问题。

二、实现方法

这次改进代码主要参考了以下两篇文章:

鸿蒙harmonyos4获取定位信息

【木棉花】获取设备的地理位置

我的代码的修改主要有四处:

1.添加了权限检查功能代码,在发现没有权限时会出现弹窗,提供开启权限的选项,这样就不用手工到手机设置里给应用添加权限了。

鸿蒙应用开发学习:手机位置信息进阶,从经纬度数据获取地理位置描述信息_第1张图片

2. 将getLastLocation()方法替换为getCurrentLocation()方法,这样每次执行该应用都是获取到的当前的位置信息。

3. 在获取到经纬度后,添加了一段代码,通过getAddressesFromLocation()方法获取经纬度对应的地理描述信息。

另外,之前的方法使用了try语句进行错误处理,这次将相关的函数和方法都改为了异步操作,剔除了try语句,使代码更简洁。

4. 对布局进行了修改,增加了显示地址、县区、省份、国家四个文本组件。

这四处改动也是在不断的测试中逐渐完善的。刚开始是添加第一部分,修改第二部分,并添加了第三部分的基础代码。将代码修改后,在真机上测试,首先通过日志信息打印getAddressesFromLocation()方法获取到的地理描述返回结果,发现是一个形如[{, , , , , }]的数据结构,其中有地址、县区、省份、国家等信息。之后通过尝试,成功从返回结果中获取到了我需要的信息,完成了第二部分的代码,最后在添加第三部分的代码将获取到的信息显示在页面中。

鸿蒙应用开发学习:手机位置信息进阶,从经纬度数据获取地理位置描述信息_第2张图片

上真机测试,显示了获取到的信息,但美中不足的是,信息都是英文的。

鸿蒙应用开发学习:手机位置信息进阶,从经纬度数据获取地理位置描述信息_第3张图片

我又在网上一阵搜索,终于在华为开发者联盟官网的论坛里找打了一篇“逆地理编码getAddressesFromLocation获取结果都是英文”的帖子,在这个帖子中找到了解决答案。

方法很简单,在使用getAddressesFromLocation()方法之前,创建reverseGeocodeRequest时,添加"locale": "zh"参数即可。

最终结果如下:

鸿蒙应用开发学习:手机位置信息进阶,从经纬度数据获取地理位置描述信息_第4张图片

三、代码展示

最后上完整的ets文件代码

import geoLocationManager from '@ohos.geoLocationManager'
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common';

// 权限列表
const permissions: Array = ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION']

let requestInfo = {
  'priority': geoLocationManager.LocationRequestPriority.ACCURACY,
  'timeInterval': 0,
  'distanceInterval': 0,
  'maxAccuracy': 0
};

@Entry
@Component
struct LocationPage {

  // 检测权限是否已经授权,如果未授权就弹出授权弹窗
  reqPermissionsFromUser(permissions: Array): void {
    let context = getContext(this) as common.UIAbilityContext;
    let atManager = abilityAccessCtrl.createAtManager();
    // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
    atManager.requestPermissionsFromUser(context, permissions).then((data) => {
      let grantStatus: Array = data.authResults;
      let length: number = grantStatus.length;
      for (let i = 0; i < length; i++) {
        if (grantStatus[i] === 0) {
          // 用户授权,可以继续操作
        } else {
          // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
          return;
        }
      }
      // 授权成功
    }).catch((err) => {
      console.error(`requestPermissionsFromUser failed, code is ${err.code}, message is ${err.message}`);
    })
  }

  // 组件即将出现时回调该接口,具体实际未在创建自定义组件的新实例后,在执行其build()函数之前执行
  aboutToAppear() {
    this.reqPermissionsFromUser(permissions)
  }

  @State mLatitude: string = '' // 经度
  @State mLongitude: string = '' // 纬度
  @State mAltitude: string = '' // 海拔(米)
  @State mAccuracy: string = '' // 精度(米)
  @State mSpeed: string = '' //速度(米/秒)
  @State mTimeStamp: string = '' // 时间戳
  @State mDirection: string = '' // 方向
  @State mAddresses: string = '' // 地址
  @State mCountryName: string = '' // 国家名称
  @State mAdministrativeArea: string = '' // 省份
  @State mLocality: string = '' // 地市
  @State mSubLocality: string = '' // 县区

  build() {
    Column() {

      Button("获取位置")
        .width(100)
        .backgroundColor($r('app.color.button_bgColor_lightBlue'))
        .margin({ top: 10, bottom: 10 })
        .onClick(() => {
          this.getLocation()
        })
      Text('【当前位置信息】')
        .fontSize(20)
      Grid() {
        GridItem() {
          Text('经度:')
        }

        GridItem() {
          Text(this.mLatitude)
        }

        GridItem() {
          Text('纬度:')
        }

        GridItem() {
          Text(this.mLongitude)
        }

        GridItem() {
          Text('海拔:')
        }

        GridItem() {
          Text(this.mAltitude)
        }

        GridItem() {
          Text('精度:')
        }

        GridItem() {
          Text(this.mAccuracy)
        }

        GridItem() {
          Text('速度:')
        }

        GridItem() {
          Text(this.mSpeed)
        }

        GridItem() {
          Text('时间:')
        }

        GridItem() {
          Text(this.mSpeed)
        }

        GridItem() {
          Text('方向:')
        }

        GridItem() {
          Text(this.mDirection)
        }

        GridItem() {
          Text('-----------------')
        }
        .columnStart(0)
        .columnEnd(1)

        GridItem() {
          Text('地址:')
        }

        GridItem() {
          Text(this.mAddresses)
        }

        GridItem() {
          Text('区县:')
        }

        GridItem() {
          Text(this.mSubLocality)
        }

        GridItem() {
          Text('地市:')
        }

        GridItem() {
          Text(this.mLocality)
        }

        GridItem() {
          Text('省份:')
        }

        GridItem() {
          Text(this.mAdministrativeArea)
        }


        GridItem() {
          Text('国家:')
        }

        GridItem() {
          Text(this.mCountryName)
        }
      }
      .columnsTemplate('1fr 4fr')
      .rowsGap(15)
      .padding(10)
      .width('90%')
    }
    .width('100%')
    .backgroundColor('#EAEAEA')
    .padding(10)
  }

  // 获取手机当前位置
  async getLocation() {
    let locationChange = (location) => {
      console.log('locationChanger: data: ' + JSON.stringify(location));
    };
    geoLocationManager.on('locationChange', requestInfo, locationChange);
    // 等待获取当前位置-异步操作
    await geoLocationManager.getCurrentLocation(requestInfo).then((result) => {
      this.mLatitude = result.latitude.toString();
      this.mLongitude = result.longitude.toString();
      this.mAltitude = result.altitude.toString() + '米';
      this.mAccuracy = result.accuracy.toString() + '米';
      this.mSpeed = result.speed.toString() + '米/秒';
      this.mTimeStamp = result.timeStamp.toString();
      this.mDirection = result.direction.toString();

      //console.log('当前位置:' + JSON.stringify(result));
      console.log("testTag", "获取到的位置信息:")
      console.log("testTag", "纬度latitude " + this.mLatitude)
      console.log("testTag", "经度longitude " + this.mLongitude)
      console.log("testTag", "海拔(米)altitude " + this.mAltitude)
      console.log("testTag", "精度(米)accuracy " + this.mAccuracy)
      console.log("testTag", "速度(米/秒)speed " + this.mSpeed)
      console.log("testTag", "时间戳timeStamp " + this.mTimeStamp)
      console.log("testTag", "方向direction " + this.mDirection)
      // 获取地址信息
      this.getAddresses(result.latitude, result.longitude)
    })
      .catch((error) => {
        console.log('promise, getCurrentLocation: error=' + JSON.stringify(error));
      })
    geoLocationManager.off('locationChange', locationChange);
  } // getLocation-end

  // 将坐标转化为地理描述
  async getAddresses(latitude: number, longitude: number) {
    // 查询geoCoder服务是否可用
    let isAvailable = geoLocationManager.isGeocoderAvailable();
    if (isAvailable) {
      let reverseGeocodeRequest = { "locale": "zh", "latitude": latitude, "longitude": longitude, "maxItems": 1 };
      await geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest).then((result) => {
        console.log('getAddressesFromLocation data: ' + JSON.stringify(result));
        this.mAddresses = result[0].placeName;
        this.mCountryName = result[0].countryName;
        this.mAdministrativeArea = result[0].administrativeArea;
        this.mLocality = result[0].locality;
        this.mSubLocality = result[0].subLocality;
      })
        .catch((error) => {
          console.log('promise, getAddressesFromLocation: error=' + JSON.stringify(error));
        })
    }
  }
  

}

你可能感兴趣的:(学习笔记,鸿蒙应用开发学习,问题解决,鸿蒙,个人开发,手机,华为,ArkTs)