HarmonyOS位置服务开发全攻略:权限申请与功能实现

前言

在移动应用开发中,位置服务是许多应用的核心功能之一。HarmonyOS提供了完善的位置服务能力,包括位置权限管理、实时定位、地理编码等功能。本文将详细介绍如何在HarmonyOS应用中实现位置服务的各种功能,包括权限申请、位置开关检测、实时定位获取等。

一、位置权限申请

在HarmonyOS中,位置权限分为两种:

  • ohos.permission.APPROXIMATELY_LOCATION:模糊定位权限
  • ohos.permission.LOCATION:精确定位权限

1.1 权限检查与申请实现

首先,我们需要创建一个权限工具类来管理位置权限的检查和申请:

typescript 复制代码
import { abilityAccessCtrl, bundleManager, Permissions, common, UIAbility } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';

const TAG = 'PermissionGrant ';

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

export async function checkPermissions(): Promise<string> {
  let permissions: Array<Permissons> = ['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'];
  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;
  
  let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  if (grantStatus2 && !grantStatus1 || !grantStatus1 && !grantStatus2) {
    console.log(TAG + '获取权限失败')
    const result = await atManager.requestPermissionsFromUser(getContext(), permissions)
    return '权限首次获取成功' + JSON.stringify(result)
  } else {
    console.log(TAG + '获取权限成功')
    return '权限已经获取成功'
  }
}

1.2 页面中调用权限申请

在页面中,我们可以通过按钮点击来触发权限申请:

typescript 复制代码
import { checkPermissions } from '../utils/PermissionGrant';

@Entry
@Component
struct LocationKitTestPage {
  @State message: string = 'hello'
  
  build() {
    Column({ space: 20 }) {
      Button('用户申请位置授权')
        .onClick(async () => {
          const promiseString: Promise<string> = checkPermissions()
          promiseString.then((stringValue: string) => {
            this.message = stringValue
          });
        })
      
      Text(this.message)
    }
  }
}

二、位置服务功能实现

2.1 检测位置开关状态

在使用位置服务前,最好先检查设备的位置服务是否已开启:

php 复制代码
Button('判断位置开关是否打开')
  .onClick(() => {
    try {
      let locationEnabled = geoLocationManager.isLocationEnabled();
      if (locationEnabled == true) promptAction.showToast({ message: '开关已打开' })
      else promptAction.showToast({ message: '开关未打开' })
    } catch (err) {
      promptAction.showToast({ message: "errCode:" + err.code + ", message:" + err.message })
    }
  })

2.2 获取实时位置信息

获取实时位置是位置服务的核心功能:

typescript 复制代码
@State location: geoLocationManager.Location | null = null

Button('获取当前的实时位置')
  .onClick(() => {
    try {
      geoLocationManager.on('locationChange', {}, (location) => {
        this.location = location
      });
    } catch (err) {
      promptAction.showToast({ message: "errCode:" + err.code + ", message:" + err.message })
    }
  })

Text(JSON.stringify(this.location, null, 2))

2.3 地理编码服务

HarmonyOS还提供了地理编码服务,可以将地址转换为坐标或反之:

javascript 复制代码
Button('地理解析')
  .onClick(async () => {
    const location = await geoLocationManager.getAddressesFromLocationName({
      description: '广州市'
    })
    promptAction.showToast({ message: JSON.stringify(location, null, 2) })
  })

2.4 检查服务可用性

在使用地理编码服务前,可以先检查服务是否可用:

javascript 复制代码
Button('判断服务是否可用')
  .onClick(() => {
    const isAvailable = geoLocationManager.isGeocoderAvailable()
    promptAction.showToast({ message: '服务是否支持' + isAvailable })
  })

三、完整页面实现

以下是完整的页面实现代码:

typescript 复制代码
import { checkPermissions } from '../utils/PermissionGrant';
import { geoLocationManager } from '@kit.LocationKit';
import { AlertDialog, promptAction } from '@kit.ArkUI';

const TAG = 'LoacationKitTestPage ';

@Entry
@Component
struct LocationKitTestPage {
  @State message: string = 'hello'
  @State location: geoLocationManager.Location | null = null
  
  build() {
    Column({ space: 20 }) {
      Button('用户申请位置授权')
        .onClick(async () => {
          const promiseString: Promise<string> = checkPermissions()
          promiseString.then((stringValue: string) => {
            this.message = stringValue
          });
        })

      Button('判断位置开关是否打开')
        .onClick(() => {
          try {
            let locationEnabled = geoLocationManager.isLocationEnabled();
            if (locationEnabled == true) promptAction.showToast({ message: '开关已打开' })
            else promptAction.showToast({ message: '开关未打开' })
          } catch (err) {
            promptAction.showToast({ message: "errCode:" + err.code + ", message:" + err.message })
          }
        })

      Button('获取当前的实时位置')
        .onClick(() => {
          try {
            geoLocationManager.on('locationChange', {}, (location) => {
              this.location = location
            });
          } catch (err) {
            promptAction.showToast({ message: "errCode:" + err.code + ", message:" + err.message })
          }
        })

      Button('判断服务是否可用')
        .onClick(() => {
          const isAvailable = geoLocationManager.isGeocoderAvailable()
          promptAction.showToast({ message: '服务是否支持' + isAvailable })
        })

      Button('地理解析')
        .onClick(async () => {
          const location = await geoLocationManager.getAddressesFromLocationName({
            description: '广州市'
          })
          promptAction.showToast({ message: JSON.stringify(location, null, 2) })
        })

      Text(JSON.stringify(this.location, null, 2))
    }
    .height('100%')
    .width('100%')
  }
}

四、注意事项

  1. 权限声明 :在module.json5文件中需要声明所需的位置权限:

    json 复制代码
    "requestPermissions": [
      {
        "name": "ohos.permission.LOCATION"
      },
      {
        "name": "ohos.permission.APPROXIMATELY_LOCATION"
      }
    ]
  2. 权限申请策略:精确定位权限只能与模糊定位权限一起申请,或者已经有模糊定位权限才能申请精确定位权限。

五、总结

本文详细介绍了HarmonyOS中位置服务的开发流程,包括:

  1. 位置权限的检查与申请
  2. 设备位置服务的开关检测
  3. 实时位置信息的获取
  4. 地理编码服务的实现
  5. 服务可用性检查

通过这些功能的组合,开发者可以轻松实现各种基于位置的服务和应用。在实际开发中,应根据应用需求合理使用这些功能,并注意权限管理和性能优化。

希望本文对您的HarmonyOS开发有所帮助!如果有任何问题,欢迎在评论区留言讨论。

相关推荐
李游Leo9 分钟前
HarmonyOS:ComposeTitleBar 组件自学指南
harmonyos
抓鱼猫L16 分钟前
鸿蒙Next(四)文字识别
harmonyos
IT乐手1 小时前
3.7、HarmonyOS Next 自定义弹窗(CustomDialog)
harmonyos
李游Leo1 小时前
HarmonyOS:ArkTS 多态样式自学指南
harmonyos
zacksleo1 小时前
鸿蒙Flutter实战:20. Flutter集成高德地图,同层渲染
flutter·harmonyos
李游Leo1 小时前
HarmonyOS:ArkTS RowSplit 组件自学指南
harmonyos
NodeMedia1 小时前
如何快速集成NodeMediaClient-Harmony
harmonyos
IT乐手1 小时前
3.8、HarmonyOS Next 气泡提示(Popup)
harmonyos
zacksleo1 小时前
鸿蒙Flutter实战:19-Flutter集成高德地图,跳转页面方式
flutter·harmonyos
BensionLZ2 小时前
HO与OH差异之Navigation三
harmonyos