DEV Community

linzhongxue
linzhongxue

Posted on

Building a Fitness and Health App Based on HarmonyOS Next: Creating an Intelligent Health Data Tracking System

Building a Fitness and Health App Based on HarmonyOS Next: Creating an Intelligent Health Data Tracking System

Introduction: New Opportunities in Smart Health Applications

With growing public health awareness, fitness and health applications have become essential in the mobile ecosystem. HarmonyOS Next provides developers with comprehensive health data management capabilities and cloud collaboration solutions. This tutorial guides you through building a fully functional fitness app from scratch, covering the entire workflow from health data collection to cloud synchronization and visual presentation.


1. Development Environment and Project Initialization

1.1 Creating a HarmonyOS Next Project

In DevEco Studio, create a new project:

  • Select the "Application" template
  • Choose ArkTS as the language
  • Select "Phone" as the device type
# Project directory structure  
MyHealthApp/  
├── entry/  
│   ├── src/  
│   │   ├── main/  
│   │   │   ├── ets/  
│   │   │   │   ├── pages/          # Page components  
│   │   │   │   ├── model/          # Data models  
│   │   │   │   └── service/        # Service layer  
Enter fullscreen mode Exit fullscreen mode

1.2 Integrating AppGallery Connect Services

  1. In the AGC console, create a project and enable:

    • Authentication Service (phone/email login)
    • Cloud DB (health data storage)
    • Cloud Storage (user avatars)
  2. Add dependencies in build.gradle:

dependencies {  
  implementation 'io.agconnect.agconnect-auth-harmony:1.8.0.300' // Auth  
  implementation 'io.agconnect.agconnect-cloud-database-harmony:1.5.0.10' // Cloud DB  
}  
Enter fullscreen mode Exit fullscreen mode

2. Health Data Collection and Management

2.1 Obtaining Health Data Permissions

Add permissions in module.json5:

"requestPermissions": [  
  {  
    "name": "ohos.permission.health.READ_HEALTH_DATA",  
    "reason": "Access step count data"  
  }  
]  
Enter fullscreen mode Exit fullscreen mode

2.2 Step Data Collection Implementation

// service/HealthService.ets  
import { health } from '@kit.HealthKit';  

export class HealthService {  
  // Get today's step count  
  async getTodaySteps(): Promise<number> {  
    try {  
      const options: health.HealthDataOptions = {  
        startTime: new Date().setHours(0, 0, 0, 0), // Midnight  
        endTime: new Date().getTime(),  
        dataType: health.DataType.DATA_TYPE_STEP_COUNT  
      };  

      const result = await health.getHealthData(options);  
      return result.reduce((sum, item) => sum + item.value, 0);  
    } catch (err) {  
      console.error("Failed to get steps:", err);  
      return 0;  
    }  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

3. User Authentication and Data Synchronization

3.1 User Login Module

// service/AuthService.ets  
import agconnect from '@hw-agconnect/api-harmony';  
import '@hw-agconnect/auth-harmony';  

export class AuthService {  
  // Phone login  
  async phoneLogin(phone: string, code: string): Promise<boolean> {  
    try {  
      const credential = agconnect.auth.PhoneAuthProvider.credentialWithVerifyCode(  
        phone,   
        null,   
        code  
      );  
      await agconnect.auth().signIn(credential);  
      return true;  
    } catch (err) {  
      console.error("Login failed:", err);  
      return false;  
    }  
  }  

  getCurrentUser() {  
    return agconnect.auth().currentUser;  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

3.2 Syncing Health Data to Cloud

// service/CloudService.ets  
import agconnect from '@hw-agconnect/api-harmony';  
import { cloud } from '@hw-agconnect/database-harmony';  

@cloud.object  
export class HealthRecord {  
  @cloud.field()  
  userId: string = "";  

  @cloud.field()  
  steps: number = 0;  

  @cloud.field()  
  date: string = ""; // YYYY-MM-DD  
}  

export class CloudService {  
  private getCollection() {  
    const cloudDB = agconnect.cloudDB();  
    return cloudDB.cloudZone("HealthZone").collection(HealthRecord);  
  }  

  // Save daily data  
  async saveDailyRecord(record: HealthRecord) {  
    try {  
      const collection = this.getCollection();  
      await collection.upsert(record);  
      console.log("Data synced successfully");  
    } catch (err) {  
      console.error("Sync failed:", err);  
    }  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

4. Data Visualization

4.1 Step Trend Chart Component

// components/StepChart.ets  
@Component  
struct StepChart {  
  @State data: Array<number> = [3500, 4200, 7800, 6500, 8900, 9200];  

  build() {  
    Column() {  
      Row() {  
        Text("Weekly Step Trend").fontSize(18).fontWeight(500)  
        Text(`Total: ${this.data.reduce((a, b) => a + b)} steps`).margin({ left: 10 })  
      }  

      Grid() {  
        ForEach(this.data, (value, index) => {  
          GridItem() {  
            Column({ space: 5 }) {  
              Stack() {  
                Column()  
                  .width(20)  
                  .height(value / 30)  
                  .backgroundColor('#FF6A6A')  
                  .borderRadius(10)  
              }.height(150).align(Alignment.Bottom)  

              Text(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][index])  
                .fontSize(14)  
            }.alignItems(HorizontalAlign.Center)  
          }  
        })  
      }  
      .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')  
      .height(200)  
    }  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

4.2 Health Dashboard Integration

// pages/HealthDashboard.ets  
import { HealthService } from '../service/HealthService';  
import { StepChart } from '../components/StepChart';  

@Entry  
@Component  
struct HealthDashboard {  
  @State steps: number = 0;  
  private healthService: HealthService = new HealthService();  

  aboutToAppear() {  
    this.loadData();  
  }  

  async loadData() {  
    this.steps = await this.healthService.getTodaySteps();  
  }  

  build() {  
    Column({ space: 20 }) {  
      // Today's steps card  
      Row() {  
        Image($r('app.media.footsteps'))  
          .width(40)  
          .height(40)  
        Column() {  
          Text("Today's Steps").fontSize(16)  
          Text(`${this.steps}`).fontSize(28).fontWeight(700)  
        }  
      }  
      .padding(20)  
      .backgroundColor('#FFFFFF')  
      .borderRadius(16)  

      // Weekly chart  
      StepChart()  

      // Goal progress  
      Progress({  
        value: this.steps,  
        total: 8000,  
        type: ProgressType.Ring  
      })  
        .width(150)  
        .height(150)  
    }  
    .padding(20)  
    .backgroundColor('#F5F5F5')  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

5. Feature Extensions

5.1 Fitness Reminders

// utils/ReminderManager.ets  
import { reminderAgent } from '@kit.ReminderAgentKit';  

export async function setDailyReminder() {  
  try {  
    const reminder: reminderAgent.ReminderRequest = {  
      reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER,  
      triggerTime: { hour: 19, minute: 30 },  
      actionButton: [  
        { title: 'Start Workout', type: reminderAgent.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE }  
      ],  
      wantAgent: {  
        pkgName: "com.example.myhealthapp",  
        abilityName: "MainAbility"  
      },  
      title: "Daily Fitness Reminder",  
      content: "You haven't completed today's goal!"  
    };  

    await reminderAgent.publishReminder(reminder);  
  } catch (err) {  
    console.error("Reminder setup failed:", err);  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

5.2 Health Data Sharing

// service/ShareService.ets  
import { share } from '@kit.ShareKit';  

export class ShareService {  
  async shareHealthData(summary: string) {  
    try {  
      const shareData: share.ShareData = {  
        type: share.ShareType.TEXT,  
        text: `My Health Report: ${summary}`  
      };  

      await share.share(shareData);  
    } catch (err) {  
      console.error("Share failed:", err);  
    }  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

6. Optimization Best Practices

6.1 Performance Optimization

// Data caching  
import { dataPreferences } from '@kit.DataPreferencesKit';  

const PREF_KEY = 'healthCache';  

async function cacheSteps(steps: number) {  
  await dataPreferences.put(PREF_KEY, 'dailySteps', steps);  
}  
Enter fullscreen mode Exit fullscreen mode

6.2 User Experience Enhancements

// Achievement system  
calculateBadges(steps: number) {  
  if (steps > 10000) return 'gold';  
  if (steps > 8000) return 'silver';  
  if (steps > 5000) return 'bronze';  
  return '';  
}  
Enter fullscreen mode Exit fullscreen mode

Conclusion: Building Next-Gen Health Experiences

Through this tutorial, we implemented core features:

  1. Local health data collection with permission management
  2. User authentication and cloud synchronization
  3. Multi-dimensional data visualization
  4. Fitness reminders and social sharing

HarmonyOS Next's health framework combined with AppGallery Connect's BaaS capabilities provides an out-of-the-box solution. Recommended next steps:

  • Integrate Huawei Health Kit for richer data
  • Use A/B testing to optimize fitness plans
  • Develop cross-device features with wearables

Full project code: github.com/example/health-app-harmonyos

(Note: Code samples use HarmonyOS SDK. Ensure latest SDK for deployment)

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.