ITPub博客

首页 > 应用开发 > IT综合 > 在 HarmonyOS 上使用 ArkUI 实现计步器应用

在 HarmonyOS 上使用 ArkUI 实现计步器应用

IT综合 作者:HarmonyOS开发者社区 时间:2023-11-16 11:26:00 0 删除 编辑

介绍

本篇 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.ets
build() {
  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'))        ...    }    ...  }  ... }


计步传感器

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



// HomePage.ets
requestPermissions(): void {
  let atManager = abilityAccessCtrl.createAtManager();
  try {
    atManager.requestPermissionsFromUser(this.context, CommonConstants.REQUEST_PERMISSIONS).then((data) => {
      if (data.authResults[0] !== 0 || data.authResults[1] !== 0) {
        return;
      }
      const that = this;
      try {
        sensor.on(sensor.SensorId.PEDOMETER, (data) => {
          try {
            if (that.isStart) {
              if (StepsUtil.checkStrIsEmpty(that.oldSteps)) {
                that.oldSteps = data.steps.toString();
                StepsUtil.putStorageValue(CommonConstants.OLD_STEPS, that.oldSteps);
              } else {
                that.currentSteps = (data.steps - NumberUtil._parseInt(that.oldSteps, 10)).toString();
              }
            } else {
              that.currentSteps = data.steps.toString();
            }


           if (StepsUtil.checkStrIsEmpty(that.stepGoal) || !that.isStart) {              return;            }            StepsUtil.putStorageValue(CommonConstants.CURRENT_STEPS, that.currentSteps);            that.progressValue = StepsUtil.getProgressValue(NumberUtil._parseInt(that.stepGoal, 10),              NumberUtil._parseInt(that.currentSteps, 10));            StepsUtil.putStorageValue(CommonConstants.PROGRESS_VALUE_TAG, String(that.progressValue));          } catch (err) {            Logger.error(TAG, 'Sensor on err' + JSON.stringify(err));          }        }, { interval: CommonConstants.SENSOR_INTERVAL });        ... }


位置服务

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



// HomePage.ets
requestPermissions(): void {
  ...
  LocationUtil.geolocationOn((location: geoLocationManager.Location) => {
    if (this.latitude === location.latitude && this.longitude === location.longitude) {
      return;
    }
    this.latitude = location.latitude;
    this.longitude = location.longitude;
    let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest = {
      'latitude': this.latitude,
      'longitude': this.longitude
    };
    geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest).then(data => {
      if (data[0].placeName) {
        this.currentLocation = data[0].placeName;
      }
    }).catch((err: Error) => {
      Logger.error(TAG, 'GetAddressesFromLocation err ' + JSON.stringify(err));
    });
  });
  ...
}



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



// LocationUtil.ets

class 
LocationUtil {
  
geolocationOn(
locationChange: 
(
location: geoLocationManager.Location) => 
void): 
void {
    
let 
requestInfo: geoLocationManager.
LocationRequest = {
      
'priority': 
0x203,
      
'scenario': 
0x300,
      
'timeInterval': 
0,
      
'distanceInterval': 
0,
      
'maxAccuracy': 
0
    }
    
try {
      geoLocationManager.
on(
'locationChange', requestInfo, locationChange);
    } 
catch (err) {
      
console.
error(
"locationChange error:" + 
JSON.
stringify(err));
    }
  }


  geolocationOff(): void {     geoLocationManager. off( 'locationChange');  } }


后台任务

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

// HomePage.ets
build() {
  Stack({ alignContent: Alignment.TopStart }) {
    ...
    Row() {
      Button(this.isStart ? $r('app.string.stop') : $r('app.string.start'))
        ...
        .onClick(() => {
          if (this.isStart) {
            ...
            BackgroundUtil.stopContinuousTask(this.context);
          } else {
            if (this.stepGoal === '' || this.currentLocation === '') {
              promptAction.showToast({ message: CommonConstants.WAIT });
            } else {
              ...
              BackgroundUtil.startContinuousTask(this.context);
            }
          }
          StepsUtil.putStorageValue(CommonConstants.IS_START, String(this.isStart));
        })
    }
    ...
}


// BackgroundUtil.ets export class BackgroundUtil {  public static startContinuousTask(context: common.UIAbilityContext): void {    let wantAgentInfo: wantAgent.WantAgentInfo = {      wants: [        {          bundleName: context.abilityInfo.bundleName,          abilityName: context.abilityInfo.name        }      ],      operationType: wantAgent.OperationType.START_ABILITY,      requestCode: 0,      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]    };
   wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {      try {        backgroundTaskManager.startBackgroundRunning(context,          backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {          Logger.info(TAG, 'startBackgroundRunning succeeded');        }).catch((err: Error) => {          Logger.error(TAG, `startBackgroundRunning failed Cause:  ${JSON.stringify(err)}`);        });      } catch (error) {        Logger.error(TAG, `stopBackgroundRunning failed. error: ${JSON.stringify(error)} `);      }    });  }
 public static stopContinuousTask(context: common.UIAbilityContext): void {    try {      backgroundTaskManager.stopBackgroundRunning(context).then(() => {        Logger.info(TAG, 'stopBackgroundRunning succeeded');      }).catch((err: Error) => {        Logger.error(TAG, `stopBackgroundRunning failed Cause:  ${JSON.stringify(err)}`);      });    } catch (error) {      Logger.error(TAG, `stopBackgroundRunning failed. error: ${JSON.stringify(error)} `);    }  } }


总结

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

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

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

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


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047792/viewspace-2995652/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2021-11-18

  • 博文量
    401
  • 访问量
    296746