前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在HarmonyOS上使用ArkUI实现计步器应用

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

原创
作者头像
小帅聊鸿蒙
发布2024-06-30 20:32:50
400
发布2024-06-30 20:32:50
举报
文章被收录于专栏:鸿蒙开发笔记鸿蒙开发笔记

介绍

本篇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

环境搭建

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

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

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

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

使用模拟器进行调试

代码结构解读

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

代码语言:c
复制
├──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自定义弹窗组件完成页面布局,效果如图所示:

代码语言:ts
复制
// 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'))
...
}
...
}
...
}

计步传感器

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

代码语言:ts
复制
// 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 });
...
}

位置服务

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

代码语言:ts
复制
// 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));
});
});
...
}

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

代码语言:ts
复制
// LocationUtil.ets
classLocationUtil{
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');
}
}

后台任务

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

代码语言:ts
复制
// 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 classBackgroundUtil{
publicstaticstartContinuousTask(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)} `);
}
});
}

publicstaticstopContinuousTask(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. 后台任务的功能实现。

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 相关概念
  • 相关权限
  • 环境搭建
  • 代码结构解读
  • 构建应用界面
  • 计步传感器
  • 位置服务
  • 后台任务
  • 总结
  • 写在最后
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档