Developing Fitness and Health Applications Based on HarmonyOS Next: From Sensors to Cloud Sync
This hands-on guide will walk you through building core modules of a "HealthTracker" fitness app, covering motion data collection, local storage, cross-device sync, cloud backup, and dynamic card display using ArkTS and AppGallery Connect (AGC) services.
1. Project Initialization and Permission Configuration
1.1 Project Setup & Dependencies
Create a "HealthTracker" project in DevEco Studio (Type: Application, Model: Stage). Add health service and distributed data dependencies in oh-package.json5
:
"dependencies": {
"@ohos.sensor": "2.0", // Sensor service
"@ohos.distributedData": "1.0", // Distributed data
"@agconnect/database": "1.0" // AGC cloud database
}
1.2 Permission Declaration
Declare permissions in module.json5
:
"requestPermissions": [
{
"name": "ohos.permission.HEALTH_DATA" // Health data access
},
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC" // Cross-device sync
},
{
"name": "ohos.permission.ACTIVITY_MOTION" // Motion recognition
}
]
2. Core Function Implementation
2.1 Real-time Step Counting
Create StepCounterService.ets
for step monitoring:
import sensor from '@ohos.sensor';
// Step counter service
export class StepCounterService {
private sensorId: number | null = null;
private stepCount: number = 0;
// Start step monitoring
startStepCounter(callback: (step: number) => void): void {
try {
// Get pedometer sensor
const sensorType = sensor.SensorType.SENSOR_TYPE_PEDOMETER;
this.sensorId = sensor.on(sensorType, (data) => {
this.stepCount = data.steps;
callback(this.stepCount); // Real-time callback
});
console.info('Step counter activated');
} catch (error) {
console.error(`Activation failed: ${error.code}, ${error.message}`);
}
}
// Stop monitoring
stopStepCounter(): void {
this.sensorId && sensor.off(this.sensorId);
}
}
2.2 Heart Rate Monitoring (Hardware-dependent)
In HeartRateMonitor.ets
:
import sensor from '@ohos.sensor';
export class HeartRateMonitor {
private sensorId: number | null = null;
// Start heart rate monitoring
startMonitoring(callback: (bpm: number) => void): void {
try {
const sensorType = sensor.SensorType.SENSOR_TYPE_HEART_RATE;
this.sensorId = sensor.on(sensorType, (data) => {
if (data.heartRate > 0) callback(data.heartRate);
});
} catch (error) {
console.error(`Monitoring error: ${error.message}`);
}
}
// Stop monitoring
stopMonitoring(): void {
this.sensorId && sensor.off(this.sensorId);
}
}
3. Data Storage and Synchronization
3.1 Local Device Storage
Store daily fitness data using distributed objects:
import distributedData from '@ohos.distributedData';
// Create distributed data object
const context = getContext(this) as common.UIAbilityContext;
let kvManager = distributedData.createKVManager({
context,
bundleName: 'com.example.healthtracker'
});
// Health data structure
interface HealthData {
steps: number;
heartRate?: number;
lastUpdate: string;
}
// Save data locally
async function saveLocalData(data: HealthData): Promise<void> {
const key = `health_${new Date().toLocaleDateString()}`;
const kvStore = await kvManager.getKVStore('healthStore');
await kvStore.put(key, JSON.stringify(data));
}
3.2 Cross-Device Sync
Synchronize data across devices:
// Sync data to other devices
async function syncDataAcrossDevices(): Promise<void> {
const allDevices = distributedData.getAvailableDevicesInfo();
const deviceIds = allDevices.map(device => device.deviceId);
if (deviceIds.length > 0) {
const kvStore = await kvManager.getKVStore('healthStore');
await kvStore.sync(deviceIds, distributedData.SyncMode.PUSH_PULL);
}
}
3.3 Cloud Backup (AGC CloudDB)
Persist data using AppGallery Connect:
import cloudDB from '@agconnect/database';
// Initialize cloud database
const agcCloudDB = cloudDB.initialize({
zoneName: "HealthDataZone", // Data zone
persistenceEnabled: true // Enable persistence
});
// Define cloud data object
@cloudDB.object()
class CloudHealthData {
userId: string = ''; // AGC user ID
date: string = ''; // Date
steps: number = 0; // Steps
avgHeartRate: number = 0; // Avg heart rate
}
// Upload to cloud
async function uploadToCloud(data: HealthData): Promise<void> {
const cloudObject = new CloudHealthData();
cloudObject.userId = getUserId(); // Get logged-in user
cloudObject.date = new Date().toISOString().split('T')[0];
cloudObject.steps = data.steps;
const store = await agcCloudDB.getCloudDBZone();
await store.upsert(cloudObject); // Insert/update
}
4. Dynamic Card Display
4.1 Card UI Layout (StepCard.ets
)
// Step display card
@Component
export struct StepCard {
@LocalStorageProp('currentSteps') steps: number = 0;
build() {
Column() {
Text("Today's Steps")
.fontSize(16)
.fontColor(Color.Gray)
Text(`${this.steps}`)
.fontSize(36)
.margin({ top: 8 })
Progress({ value: this.steps, total: 10000 }) // 10k goal
.height(10)
.margin({ top: 15 })
}
.padding(20)
}
}
4.2 Real-time Card Updates
In card provider FormAbility.ts
:
import formBindingData from '@ohos.app.form.formBindingData';
// Update card data
onUpdateForm(formId: string): void {
let stepData = { 'currentSteps': 6850 }; // Get live data
let formData = formBindingData.createFormBindingData(stepData);
formProvider.updateForm(formId, formData)
.catch(err => console.error('Update failed: ' + err));
}
5. Troubleshooting Guide
-
Sensor Best Practices
- Request
ohos.permission.KEEP_BACKGROUND_RUNNING
for background ops - Wrap sensor operations in
try/catch
blocks
- Request
Sync Optimization
// Low-power sync strategy:
const options = {
syncMode: distributedData.SYNC_MODE_LOW_POWER,
delay: 500 // Batch sync every 500ms
};
kvStore.sync(deviceIds, distributedData.SyncMode.PUSH, options);
- Cloud Security Configure data access rules in AGC console:
{
"read": "auth != null", // Authenticated users only
"write": "auth.uid == userId" // Data owner only
}
6. Complete Example: Fitness Dashboard
// HealthDashboard.ets
import { StepCounterService } from './StepCounterService';
@Entry
@Component
struct HealthDashboard {
@State steps: number = 0;
private stepService: StepCounterService = new StepCounterService();
aboutToAppear() {
this.stepService.startStepCounter((step) => {
this.steps = step;
// Sync every 10 minutes
if (step % 10 === 0) {
saveLocalData({ steps, lastUpdate: new Date().toISOString() });
uploadToCloud({ steps });
}
});
}
build() {
Column() {
// Step progress ring
Progress({
value: this.steps,
total: 10000,
type: ProgressType.Ring
}).width(200)
// Sync button
Button("Sync to Watch")
.onClick(() => syncDataAcrossDevices())
}
}
}
Conclusion
You've now mastered core HarmonyOS fitness app development:
- Hardware sensor data acquisition
- Distributed data flow
- Cloud persistence solutions
- Real-time card visualization
Leveraging HarmonyOS Next's distributed architecture and AGC's backend capabilities, developers can seamlessly create consistent cross-device fitness experiences. Always test sensor features on real devices and configure detailed data security policies in the AGC console.
Top comments (0)