当前位置:   article > 正文

在 HarmonyOS 上使用 ArkUI 实现计步器应用_ohos.permission.activity_motion

ohos.permission.activity_motion

介绍

本篇 Codelab 使用 ArkTS 语言实现计步器应用,应用主要包括计步传感器、定位服务和后台任务功能:

1.  通过订阅计步器传感器获取计步器数据,处理后显示。

2.  通过订阅位置服务获取位置数据,处理后显示。

3.  通过服务开发实现后台任务功能。

相关概念

计步传感器:订阅计步器传感器数据,系统返回相关数据。

后台任务管理:应用中存在用户能够直观感受到的且需要一直在后台运行的业务时(如,后台播放音乐),可以使用长时任务机制。

位置服务:位置服务提供 GNSS 定位、网络定位、地理编码、逆地理编码、国家码和地理围栏等基本功能。

相关权限

本篇 Codelab 用到了计步传感器、后台任务及位置服务功能,需要在配置文件 module.json5 里添加权限:

● ohos.permission.ACTIVITY_MOTION

● ohos.permission.KEEP_BACKGROUND_RUNNING

● ohos.permission.APPROXIMATELY_LOCATION

● ohos.permission.LOCATION

● ohos.permission.LOCATION_IN_BACKGROUND

完整示例

gitee源码地址

源码下载

计步器应用(ArkTS).zip

环境搭建

我们首先需要完成 HarmonyOS 开发环境搭建,可参照如下步骤进行。

软件要求

DevEco Studio版本:DevEco Studio 3.1 Release。

HarmonyOS SDK版本:API version 9。

硬件要求

设备类型:华为手机或运行在 DevEco Studio 上的华为手机设备模拟器。

HarmonyOS 系统:3.1.0 Developer Release。

环境搭建

安装 DevEco Studio,详情请参考下载和安装软件

设置 DevEco Studio 开发环境,DevEco Studio 开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:如果可以直接访问 Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问 Internet,需要通过代理服务器才可以访问,请参考配置开发环境

开发者可以参考以下链接,完成设备调试的相关配置:使用真机进行调试

使用模拟器进行调试

代码结构解读

本篇 Codelab 只对核心代码进行讲解,对于完整代码,我们会在源码下载或 gitee 中提供。

├──entry/src/main/ets               // 代码区│  ├──common│  │  ├──constants│  │  │  └──CommonConstants.ets     // 公共常量│  │  └──utils                      // 日志类│  │     ├──BackgroundUtil.ets      // 后台任务工具类│  │     ├──GlobalContext.ets       // 首选项工具类│  │     ├──LocationUtil.ets        // 位置服务工具类│  │     ├──Logger.ets              // 日志工具类│  │     ├──NumberUtil.ets          // 数字处理工具类│  │     └──StepsUtil.ets           // 计步器工具类│  ├──entryability│  │  └──EntryAbility.ets           // 程序入口类│  ├──pages│  │  └──HomePage.ets               // 应用首页│  └──view│     ├──CompletionStatus.ets       // 目标设置页│     ├──CurrentSituation.ets       // 计步信息页│     └──InputDialog.ets            // 自定义弹窗└──entry/src/main/resources         // 资源文件夹

构建应用界面

计步器页面主要由 Stack 堆叠容器组件、Component 自定义组件和 CustomDialog 自定义弹窗组件完成页面布局,效果如图所示:

// HomePage.etsbuild() {  Stack({ alignContent: Alignment.TopStart }) {    CompletionStatus({      progressValue: $progressValue    })
    CurrentSituation({      currentSteps: this.currentSteps,      startPosition: this.startPosition,      currentLocation: this.currentLocation    })
    Row() {      Button(this.isStart ? $r('app.string.stop') : $r('app.string.start'))        ...    }    ...  }  ...}

计步传感器

应用启动后申请计步传感器权限,获取权限后订阅计步器传感器。通过订阅获取到计步传感器数据,解析处理后在页面显示。效果如图所示:

  1. // HomePage.ets
  2. requestPermissions(): void {
  3. let atManager = abilityAccessCtrl.createAtManager();
  4. try {
  5. atManager.requestPermissionsFromUser(this.context, CommonConstants.REQUEST_PERMISSIONS).then((data) => {
  6. if (data.authResults[0] !== 0 || data.authResults[1] !== 0) {
  7. return;
  8. }
  9. const that = this;
  10. try {
  11. sensor.on(sensor.SensorId.PEDOMETER, (data) => {
  12. try {
  13. if (that.isStart) {
  14. if (StepsUtil.checkStrIsEmpty(that.oldSteps)) {
  15. that.oldSteps = data.steps.toString();
  16. StepsUtil.putStorageValue(CommonConstants.OLD_STEPS, that.oldSteps);
  17. } else {
  18. that.currentSteps = (data.steps - NumberUtil._parseInt(that.oldSteps, 10)).toString();
  19. }
  20. } else {
  21. that.currentSteps = data.steps.toString();
  22. }
  23. if (StepsUtil.checkStrIsEmpty(that.stepGoal) || !that.isStart) {
  24. return;
  25. }
  26. StepsUtil.putStorageValue(CommonConstants.CURRENT_STEPS, that.currentSteps);
  27. that.progressValue = StepsUtil.getProgressValue(NumberUtil._parseInt(that.stepGoal, 10),
  28. NumberUtil._parseInt(that.currentSteps, 10));
  29. StepsUtil.putStorageValue(CommonConstants.PROGRESS_VALUE_TAG, String(that.progressValue));
  30. } catch (err) {
  31. Logger.error(TAG, 'Sensor on err' + JSON.stringify(err));
  32. }
  33. }, { interval: CommonConstants.SENSOR_INTERVAL });
  34. ...
  35. }


 

位置服务

应用启动后申请位置服务权限,获取权限后启动服务,启动服务后订阅位置服务。通过订阅获取到位置服务数据,解析处理后在页面显示。效果如图所示:

  1. // HomePage.ets
  2. requestPermissions(): void {
  3. ...
  4. LocationUtil.geolocationOn((location: geoLocationManager.Location) => {
  5. if (this.latitude === location.latitude && this.longitude === location.longitude) {
  6. return;
  7. }
  8. this.latitude = location.latitude;
  9. this.longitude = location.longitude;
  10. let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest = {
  11. 'latitude': this.latitude,
  12. 'longitude': this.longitude
  13. };
  14. geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest).then(data => {
  15. if (data[0].placeName) {
  16. this.currentLocation = data[0].placeName;
  17. }
  18. }).catch((err: Error) => {
  19. Logger.error(TAG, 'GetAddressesFromLocation err ' + JSON.stringify(err));
  20. });
  21. });
  22. ...
  23. }

将位置服务相关的函数封装到工具类中。

  1. // LocationUtil.ets
  2. class LocationUtil {
  3. geolocationOn(locationChange: (location: geoLocationManager.Location) => void): void {
  4.     let requestInfo: geoLocationManager.LocationRequest = {
  5. 'priority': 0x203,
  6. 'scenario': 0x300,
  7. 'timeInterval': 0,
  8. 'distanceInterval': 0,
  9. 'maxAccuracy': 0
  10. }
  11. try {
  12.       geoLocationManager.on('locationChange', requestInfo, locationChange);
  13. } catch (err) {
  14.       console.error("locationChange error:" + JSON.stringify(err));
  15. }
  16. }
  17. geolocationOff(): void {
  18.     geoLocationManager.off('locationChange');
  19. }
  20. }


 

后台任务

点击开始按钮开启后台任务,通过后台任务管理方法配置申请的后台模式等参数启动后台任务。
 

  1. // HomePage.ets
  2. build() {
  3. Stack({ alignContent: Alignment.TopStart }) {
  4. ...
  5. Row() {
  6. Button(this.isStart ? $r('app.string.stop') : $r('app.string.start'))
  7. ...
  8. .onClick(() => {
  9. if (this.isStart) {
  10. ...
  11. BackgroundUtil.stopContinuousTask(this.context);
  12. } else {
  13. if (this.stepGoal === '' || this.currentLocation === '') {
  14. promptAction.showToast({ message: CommonConstants.WAIT });
  15. } else {
  16. ...
  17. BackgroundUtil.startContinuousTask(this.context);
  18. }
  19. }
  20. StepsUtil.putStorageValue(CommonConstants.IS_START, String(this.isStart));
  21. })
  22. }
  23. ...
  24. }
  25. // BackgroundUtil.ets
  26. export class BackgroundUtil {
  27. public static startContinuousTask(context: common.UIAbilityContext): void {
  28. let wantAgentInfo: wantAgent.WantAgentInfo = {
  29. wants: [
  30. {
  31. bundleName: context.abilityInfo.bundleName,
  32. abilityName: context.abilityInfo.name
  33. }
  34. ],
  35. operationType: wantAgent.OperationType.START_ABILITY,
  36. requestCode: 0,
  37. wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
  38. };
  39. wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
  40. try {
  41. backgroundTaskManager.startBackgroundRunning(context,
  42. backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {
  43. Logger.info(TAG, 'startBackgroundRunning succeeded');
  44. }).catch((err: Error) => {
  45. Logger.error(TAG, `startBackgroundRunning failed Cause: ${JSON.stringify(err)}`);
  46. });
  47. } catch (error) {
  48. Logger.error(TAG, `stopBackgroundRunning failed. error: ${JSON.stringify(error)} `);
  49. }
  50. });
  51. }
  52. public static stopContinuousTask(context: common.UIAbilityContext): void {
  53. try {
  54. backgroundTaskManager.stopBackgroundRunning(context).then(() => {
  55. Logger.info(TAG, 'stopBackgroundRunning succeeded');
  56. }).catch((err: Error) => {
  57. Logger.error(TAG, `stopBackgroundRunning failed Cause: ${JSON.stringify(err)}`);
  58. });
  59. } catch (error) {
  60. Logger.error(TAG, `stopBackgroundRunning failed. error: ${JSON.stringify(error)} `);
  61. }
  62. }
  63. }

总结

您已经完成了本次 Codelab 的学习,并了解到以下知识点:

1.  计步器传感器的功能实现。

2.  位置服务的功能实现。

3.  后台任务的功能实现。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/285342
推荐阅读
相关标签
  

闽ICP备14008679号