在 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
完整示例
原始碼下載
環境搭建
我們首先需要完成 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部落格 ” ,連結:http://blog.itpub.net/70009402/viewspace-2995652/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 鴻蒙HarmonyOS實戰-ArkUI元件(Stack)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Flex)鴻蒙UI元件Flex
- 鴻蒙HarmonyOS實戰-ArkUI元件(mediaquery)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(List)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Swiper)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Button)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Progress)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Popup)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Menu)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Tabs)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Image)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Canvas)鴻蒙UI元件Canvas
- 鴻蒙HarmonyOS實戰-ArkUI元件(Row/Column)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Toggle)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(TextInput/TextArea)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Video)鴻蒙UI元件IDE
- 鴻蒙HarmonyOS實戰-ArkUI元件(Navigation)鴻蒙UI元件Navigation
- 鴻蒙HarmonyOS實戰-ArkUI元件(Shape)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI事件(觸屏事件)鴻蒙UI事件
- 鴻蒙HarmonyOS實戰-ArkUI事件(鍵鼠事件)鴻蒙UI事件
- 鴻蒙HarmonyOS實戰-ArkUI事件(焦點事件)鴻蒙UI事件
- 鴻蒙HarmonyOS實戰-ArkUI元件(RelativeContainer)鴻蒙UI元件AI
- 鴻蒙HarmonyOS實戰-ArkUI元件(CustomDialog)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(頁面路由)鴻蒙UI元件路由
- 鴻蒙HarmonyOS實戰-ArkUI事件(手勢方法)鴻蒙UI事件
- 鴻蒙HarmonyOS實戰-ArkUI動畫(佈局更新動畫)鴻蒙UI動畫
- 鴻蒙HarmonyOS實戰-ArkUI元件(GridRow/GridCol)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI元件(Grid/GridItem)鴻蒙UI元件
- 鴻蒙HarmonyOS實戰-ArkUI事件(組合手勢)鴻蒙UI事件
- 4天帶你上手HarmonyOS ArkUI開發——《HarmonyOS ArkUI入門訓練營之健康生活實戰》UI
- 鴻蒙HarmonyOS實戰-ArkUI動畫(放大縮小檢視)鴻蒙UI動畫
- 鴻蒙HarmonyOS實戰-ArkUI動畫(頁面轉場動畫)鴻蒙UI動畫
- 鴻蒙HarmonyOS實戰-ArkUI動畫(彈簧曲線動畫)鴻蒙UI動畫
- 鴻蒙HarmonyOS實戰-ArkUI事件(單一手勢)鴻蒙UI事件
- HarmonyOS NEXT應用開發—在Native側實現進度通知功能
- HarmonyOS NEXT應用開發案例——列表編輯實現
- 用js實現返回上一步操作JS
- HarmonyOS NEXT應用開發之使用AKI輕鬆實現跨語言呼叫