Developing Fitness and Health Applications Based on HarmonyOS Next: From Health Data to Cloud Synchronization
In the era of all things connected, fitness and health applications are becoming essential companions for personal health management. HarmonyOS Next provides an exceptional platform for developers to create intelligent, interconnected health applications with its robust distributed capabilities, smooth performance, and rich application service interfaces. This article delves into building a fully functional fitness and health application using HarmonyOS SDK application services—specifically Health Kit, Cloud DB, and Cloud Functions from AppGallery Connect.
I. Core Application Function Planning
We will develop an application named "Harmony Health Assistant" with the following core features:
- Step Tracking and Display: Real-time step data reading and visualization.
- Health Data Synchronization: Securely storing user step data in the cloud (AppGallery Connect).
- Goal Setting and Reminders: Allowing users to set daily step goals and triggering local notifications upon achievement.
- Device Interconnection (Optional): Discovering nearby compatible fitness devices (e.g., smart bands) and displaying their status.
II. Development Environment and Prerequisites
- Setup Development Tools: Ensure the latest version of DevEco Studio is installed with HarmonyOS SDK configured.
- Create HarmonyOS Project: In DevEco Studio, create a new project (Application → Empty Ability) using ArkTS.
-
Enable AppGallery Connect Services:
- Create a project and app in the AppGallery Connect console (ensure package name matches the local project).
- Enable Cloud DB and Cloud Functions services. Integrate the SDK and configure the
agconnect-services.json
file.
-
Health Kit Permissions:
Declare permissions in
module.json5
:
"requestPermissions": [
{ "name": "ohos.permission.health.READ_HEALTH_DATA" },
{ "name": "ohos.permission.health.WRITE_HEALTH_DATA" },
{ "name": "ohos.permission.NOTIFICATION" },
{ "name": "ohos.permission.DISTRIBUTED_DATASYNC" }
]
Dynamically request these permissions during runtime.
III. Core Function Implementation (ArkTS Code)
1. Reading and Displaying Real-Time Steps (Health Kit)
import health from '@ohos.health';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';
@Component
struct StepCounterDisplay {
@State currentSteps: number = 0;
@State dailyGoal: number = 10000;
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
aboutToAppear() {
this.startStepCounter();
}
private startStepCounter() {
try {
const options: health.HealthDataOptions = {
startTime: new Date(new Date().setHours(0, 0, 0, 0)), // Today at 00:00
endTime: new Date(), // Current time
dataType: health.HealthDataType.STEP_COUNT,
timeUnit: health.TimeUnit.MILLISECONDS
};
const healthHelper = health.createHealthHelper(this.context);
healthHelper.getSum(options).then((result: health.HealthData) => {
this.currentSteps = result.value; // Update UI
}).catch((err: BusinessError) => {
console.error(`Step fetch failed: ${err.message}`);
});
// Real-time step listener
healthHelper.on(health.HealthType.STEP_COUNT, (data: health.HealthData) => {
this.currentSteps = data.value;
if (this.currentSteps >= this.dailyGoal) this.sendGoalAchievedNotification();
});
} catch (error) {
console.error("Step counter error: " + (error as BusinessError).message);
}
}
private sendGoalAchievedNotification() {
// Implementation using @ohos.notificationManager
console.info(`Goal achieved: ${this.dailyGoal} steps!`);
}
build() {
Column() {
Text(`Today's Steps: ${this.currentSteps}`).fontSize(30).margin(20)
TextInput({ text: this.dailyGoal.toString() })
.onChange((value: string) => {
this.dailyGoal = parseInt(value) || 10000;
})
.width('80%')
Button('Save Goal').onClick(() => { /* Save logic */ })
}
.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
2. Syncing Step Data to Cloud (AppGallery Connect Cloud DB)
Step 1: Define Cloud DB Object Type
Create a StepRecord
object in AppGallery Connect Cloud DB with fields:
-
id
(String, primary key) -
userId
(String) -
date
(String, format 'YYYY-MM-DD') -
steps
(Integer) -
deviceId
(String)
Step 2: Initialize Cloud DB in App
import cloud from '@hw-agconnect/cloud';
import '@hw-agconnect/instance';
export class StepRecord {
id?: string;
userId?: string;
date?: string;
steps?: number;
deviceId?: string;
constructor(userId: string, date: string, steps: number, deviceId: string) {
this.userId = userId;
this.date = date;
this.steps = steps;
this.deviceId = deviceId;
}
}
const cloudDBZone = cloud.CloudDBZoneConfig.getCloudDBZoneConfig('your_zone_name');
Step 3: Upload Daily Steps
Button('Sync to Cloud').onClick(async () => {
try {
const currentUser = 'user123'; // From AGC Auth
const today = new Date().toISOString().split('T')[0];
const record = new StepRecord(currentUser, today, this.currentSteps, 'HarmonyPhone');
const cloudDBZone = await cloud.CloudDBZone.open(cloudDBZone);
await cloudDBZone.executeUpsert([record]);
console.info("Steps synced successfully!");
} catch (error) {
console.error("Sync failed: " + (error as BusinessError).message);
}
});
Step 4: Query Historical Data
async function queryHistorySteps(userId: string) {
try {
const cloudDBZone = await cloud.CloudDBZone.open(cloudDBZone);
const query = cloud.CloudDBZoneQuery.where(StepRecord)
.equalTo('userId', userId)
.orderByDesc('date');
const result = await cloudDBZone.executeQuery(query);
const records: StepRecord[] = [];
// Process result snapshot into records array
return records; // For charts/lists
} catch (error) {
console.error("Query error: " + (error as BusinessError).message);
return [];
}
}
3. Device Interconnection (DeviceManager)
import deviceManager from '@ohos.distributedDeviceManager';
@Entry
@Component
struct NearbyDevicesPage {
@State discoveredDevices: deviceManager.DeviceBasicInfo[] = [];
startDiscovery() {
try {
const dmInstance = deviceManager.createDeviceManager('com.example.healthapp');
dmInstance.on('deviceStateChange', (data) => {
if (data.action === deviceManager.DeviceStateChangeAction.ONLINE) {
this.discoveredDevices = [...this.discoveredDevices, data.device];
} else if (data.action === deviceManager.DeviceStateChangeAction.OFFLINE) {
this.discoveredDevices = this.discoveredDevices.filter(d => d.deviceId !== data.device.deviceId);
}
});
const discoverParams: deviceManager.DiscoverParam = {
mode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE,
filter: { deviceType: [deviceManager.DeviceType.WEARABLE] }
};
dmInstance.startDeviceDiscovery(discoverParams);
setTimeout(() => dmInstance.stopDeviceDiscovery(), 10000); // Stop after 10s
} catch (error) {
console.error("Device scan failed: " + (error as BusinessError).message);
}
}
build() {
Column() {
Button('Scan Nearby Devices').onClick(() => this.startDiscovery()).margin(20)
List() {
ForEach(this.discoveredDevices, (device) =>
ListItem() {
Text(`${device.deviceName} (${device.deviceId})`).padding(10)
}
)
}.layoutWeight(1)
}
}
}
IV. Advanced Features & Optimization
-
Data Visualization: Use
<Canvas>
or third-party libraries to draw step trends. -
Cloud-Triggered Goal Alerts:
- Use Cloud Functions to trigger push notifications (via Push Kit) when step goals are met.
-
Multi-Device Data Aggregation:
- Aggregate step data from phones/watches using distributed data management.
-
Health Data Analysis:
- Leverage Serverless Analytics for weekly/monthly user reports.
-
Performance Optimization:
- Batch upload data to reduce frequency.
- Optimize Health Kit listener intervals.
-
Privacy & Security:
- Encrypt sensitive local data (e.g., userId).
- Implement Cloud DB fine-grained access control.
- Explicit user consent for health data usage.
V. Conclusion
By combining HarmonyOS Next’s local capabilities (Health Kit, DeviceManager) with AppGallery Connect’s cloud services (Cloud DB, Cloud Functions, Auth), developers can efficiently build secure, feature-rich fitness applications. The provided ArkTS examples establish a foundation for extending these concepts—leveraging HarmonyOS’ distributed architecture to pioneer innovative health management experiences.
Top comments (0)