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

介绍

本篇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中提供。

├──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
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');
}
}

后台任务

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

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

为了能让大家更好的学习鸿蒙 (Harmony OS) 开发技术,这边特意整理了《鸿蒙 (Harmony OS)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙 (Harmony OS)开发学习手册》

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. 应用开发导读(Java)

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/216529.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是Scss

Sass(Syntactically Awesome Style Sheets) ,是一种 css 预处理器和一种语言, 它可以用来定义一套新的语法规则和函数,以加强和提升 CSS. 它有很多很好的特性,但是它有类似 Ruby 的语法,没有花括号,没有分号,遵循严格的…

Ubuntu系统使用快速入门实践(七)——软件安装与使用(6)

Ubuntu系统使用快速入门实践系列文章 下面是Ubuntu系统使用系列文章的总链接,本人发表这个系列的文章链接均收录于此 Ubuntu系统使用快速入门实践系列文章总链接 下面是专栏地址: Ubuntu系统使用快速入门实践系列文章专栏 文章目录 Ubuntu系统使用快速…

外贸获客引流详细教程,小白也能懂!

一、引子 随着全球化的不断发展,国际贸易日益频繁,许多外贸企业为了拓展市场,获取更多客户,都在努力提高营销策略。 然而,对于许多外贸新手来说,如何高效地进行获客引流仍然是一个难题,今天&a…

手动搭建koa+ts项目框架(ts项目实现开发阶段实时查看)

文章目录 前言优化脚本如有启发,可点赞收藏哟~ 前言 上篇文章记录了手动简单搭建 koats项目步骤 虽然可以直接编译后并开启服务,但如果修改./src内的文件,没法实时编译 以下介绍使用其他方法实现实时效果 优化脚本 咱使用以下依赖可实现边写…

机械中常用的一些术语

目录 一、OEMSOP:SOP编写指南 WI(标准作业指导书):标准作业程序 (SOP):SOP和WI的区别:一、PFC、FMEA、PCP、WIPPAP、PSW:APQP:BOM(Bill of Material)物料清单DV(设计验证&#xff09…

“产学研用”深度融合,校企合作助力烟花产业数字化发展

为推动烟花行业数字化转型升级,充分发挥科教资源优势,技术成果及创新资源,推动构建产学研用高效协同,加快提升烟花产业创新能力,助力企业在国内外复杂的市场环境下提升发展能力及竞争能力。12月6日,烟花生产…

前端知识(十)———JavaScript 使用URL跳转传递数组对象数据类型的方法

目录 首先了解一下正常传递基本数据类型 JavaScript跳转页面方法 JavaScript路由传递参数 JavaScript路由接收参数传递对象、数组 在前端有的时候会需要用链接进行传递参数,基本数据类型的传递还是比较简单的,但是如果要传递引用数据类型就比较麻烦了…

final,finally,finalize的区别

final,finally,finalize的区别 在Java中,final、finally和finalize是三个不同的关键字,它们具有不同的作用和用法。 1、final: final是一个修饰符,可以用于修饰类、方法和变量。 用于修饰类时&#xff0…

python sort函数

得开个新坑学一下sort的用法了。 a [a, b, c, d] b [0, 1, 2, 3]sorted_list [x for _, x in sorted(zip(b, a))] 参数 sorted(iterable, cmpNone, keyNone, reverseFalse)菜鸟教程的例子: >>>a [5,7,6,3,4,1,2] >>> b sorted(a) #…

如何让弹出的.py文件窗口缩小

原图比例如下,很明显实际大小已经超出屏幕显示范围: 参考这篇文章的代码,新定义一个函数: def get_scaling():user32 windll.user32# 获取现在的尺寸(缩放后now_width user32.GetSystemMetrics(0)now_height user…

Day07 Liunx高级系统设计8-线程

概述 进程与线程 进程 : 系统分配资源的基本单位 , 可以简单理解为一个正在进行的程序 线程 : 操作系统调度的最小单位 , 就是一段代码的执行顺序 注意: 1, 一个进程必须要有一个线程 , 该线程被称为主线程 2, 一个进程可以有多个线程 , 除主线程外的其他线程都是…

我的创作三周年纪念日

今天收到CSDN官方的来信,创作三周纪念日到了。 Dear: Hann Yang ,有幸再次遇见你: 还记得 2020 年 12 月 12 日吗? 你撰写了第 1 篇技术博客: 《vba程序用7重循环来计算24》 在这平凡的一天,你赋予了它…

MacOS 12 开放指定端口 指定ip访问

MacOS 12 开放指定端口 指定ip访问 在 macOS 上开放一个端口,并指定只能特定的 IP 访问,你可以使用 macOS 内置的 pfctl(Packet Filter)工具来实现。 以下是一些基本的步骤: 1、 编辑 pf 配置文件: 打开 /…

Android开发之长log的打印

在开发过程中,我们想要打印长的log,这个时候我们就需要做特殊的处理,下面这段代码就是处理的长log的打印: public static void LogLong(String tag, String msg) { //信息太长,分段打印//因为String的length是字符数量不是字节数…

JavaScript中如何向URL添加参数

设url为https://yungot.com/ 求:向url中添加参数 ?page=1&limit=10 变成 https://yungot.com/?page=1&limit=10 解决方案:调用addUrlParams函数 解:addUrlParams({“page”: 1, “limit”: 10}) // url处理 function getRequestParams() {const requestParams = …

centos7部署docker环境

卸载旧版本 sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 安装软件包并设置存储库 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https:/…

时光机器:用rrweb打造可回溯的用户体验!

在现代Web应用中,理解用户如何与你的产品互动变得越来越重要。rrweb(record and replay the web)是一个开源库,它能够记录用户在网站上的所有操作,并能够像回放视频一样回放这些操作。这就像给你的网站装上了一台时光机…

leetcode 30. 串联所有单词的子串(优质解法)

代码&#xff1a; class Solution {public static List<Integer> findSubstring(String s, String[] words) {List<Integer> integerListnew ArrayList<>();int lengthwords.length; //words 数组中的字符串个数int sizewords[0].length(); //words 数组…

C++STL的vector模拟实现

文章目录 前言成员变量成员函数构造函数push_backpop_backinserterase析构函数拷贝构造 前言 成员变量 namespace but {template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;}; }我们之前实…

Docker的安装与简单操作命令

目录 前言 docker的安装 基础docker操作 容器管理 镜像管理 容器镜像封装与加载 前言 前文简单说明了容器技术出现的背景&#xff0c;与对docker做了结构上的介绍Container容器技术简介-CSDN博客https://blog.csdn.net/qq_72569959/article/details/134814887 讲到dock…