Sign up for your FREE personalized newsletter featuring insights, trends, and news for America's Active Baby Boomers

Newsletter
New

Developing An Educational Application Based On Harmonyos Next

Card image cap

Developing an Educational Application Based on HarmonyOS Next: Building a Smart Learning Assistant from Scratch

1. Project Overview and Development Environment Setup

In the rapidly evolving landscape of digital education, developing educational applications on HarmonyOS Next holds immense potential. This tutorial will guide you through using AppGallery Connect services to build a "Smart Learning Assistant" application featuring course management, learning progress tracking, and knowledge assessment.

First, ensure your development environment is ready:

  1. Install the latest version of DevEco Studio (recommended 4.0 or above).
  2. Register a Huawei Developer account and complete identity verification.
  3. Create a new project in AppGallery Connect and enable the required services.
// Example of project initialization configuration    
import { Ability, AbilityConstant, UIAbility, Want } from '@ohos.app.ability.UIAbility';    
import { window } from '@ohos.window';    
  
export default class EntryAbility extends UIAbility {    
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {    
    console.info('EducationApp onCreate');    
    // Initialize the application's global state    
    globalThis.educationContext = this.context;    
  }    
  
  onWindowStageCreate(windowStage: window.WindowStage) {    
    console.info('EducationApp onWindowStageCreate');    
    // Load the home page    
    windowStage.loadContent('pages/Index', (err) => {    
      if (err.code) {    
        console.error('Failed to load the content. Cause:' + JSON.stringify(err));    
        return;    
      }    
      console.info('Succeeded in loading the content');    
    });    
  }    
}    

2. Application Architecture Design and Core Feature Planning

2.1 Overall Architecture Design

Our Smart Learning Assistant adopts a layered architecture:

  • Presentation Layer: ArkUI-based page components
  • Business Logic Layer: Handles education-related business logic
  • Data Access Layer: Uses AppGallery Connect's Cloud DB and authentication services
  • Service Layer: Integrates Huawei's analytics and push services

2.2 Core Feature Modules

  1. User Authentication Module: Supports login for teachers and students
  2. Course Management Module: Create, edit, and browse course content
  3. Learning Progress Module: Tracks and visualizes learning progress
  4. Assessment Module: Provides knowledge tests and a wrong-answer notebook

3. Implementing the User Authentication Module

Educational apps often require distinguishing between teacher and student roles, which can be achieved using AppGallery Connect's authentication service.

// Import authentication modules    
import { agconnect } from '@hw-agconnect/api-ohos';    
import '@hw-agconnect/auth-ohos';    
  
// User authentication service class    
export class AuthService {    
  // User login method    
  async login(email: string, password: string): Promise<boolean> {    
    try {    
      const user = await agconnect.auth().signInWithEmailAndPassword(email, password);    
      console.info('Login success:', user);    
      return true;    
    } catch (error) {    
      console.error('Login failed:', error);    
      return false;    
    }    
  }    
  
  // User registration method    
  async register(email: string, password: string, role: string): Promise<boolean> {    
    try {    
      const user = await agconnect.auth().createUserWithEmailAndPassword(email, password);    
      // Save user role to Cloud DB    
      await this.saveUserRole(user.uid, role);    
      return true;    
    } catch (error) {    
      console.error('Registration failed:', error);    
      return false;    
    }    
  }    
  
  // Save user role to Cloud DB    
  private async saveUserRole(uid: string, role: string): Promise<void> {    
    const db = agconnect.cloudDB();    
    const userRole = {    
      userId: uid,    
      role: role,    
      createdAt: new Date().toISOString()    
    };    
    await db.insert('UserRoles', userRole);    
  }    
}    

4. Developing the Course Management Module

Courses are the core content of educational apps, requiring well-designed database structures and related functionalities.

4.1 Data Model Design

Create a Course object type in AppGallery Connect with the following fields:

  • courseId: String (primary key)
  • title: String (course title)
  • description: String (course description)
  • teacherId: String (teacher ID)
  • chapters: Array (list of chapters)
  • createTime: Timestamp
// Course service class    
export class CourseService {    
  private db: any;    
  
  constructor() {    
    this.db = agconnect.cloudDB();    
  }    
  
  // Create a new course    
  async createCourse(courseData: any): Promise<string> {    
    try {    
      const result = await this.db.insert('Courses', courseData);    
      console.info('Course created:', result);    
      return result.id;    
    } catch (error) {    
      console.error('Failed to create course:', error);    
      throw error;    
    }    
  }    
  
  // Get all courses by a teacher    
  async getCoursesByTeacher(teacherId: string): Promise<Array<any>> {    
    try {    
      const query = this.db.createQuery();    
      query.equalTo('teacherId', teacherId);    
      query.orderByDesc('createTime');    
      const result = await this.db.executeQuery('Courses', query);    
      return result.getSnapshotObjects();    
    } catch (error) {    
      console.error('Failed to get courses:', error);    
      return [];    
    }    
  }    
  
  // Get course details    
  async getCourseDetail(courseId: string): Promise<any> {    
    try {    
      const query = this.db.createQuery();    
      query.equalTo('courseId', courseId);    
      const result = await this.db.executeQuery('Courses', query);    
      const courses = result.getSnapshotObjects();    
      return courses.length > 0 ? courses[0] : null;    
    } catch (error) {    
      console.error('Failed to get course detail:', error);    
      return null;    
    }    
  }    
}    

5. Implementing Learning Progress Tracking

Learning progress is a crucial feature in educational apps, helping students track their learning journey.

// Learning progress service class    
export class ProgressService {    
  private db: any;    
  
  constructor() {    
    this.db = agconnect.cloudDB();    
  }    
  
  // Update learning progress    
  async updateProgress(userId: string, courseId: string, chapterId: string, progress: number): Promise<void> {    
    try {    
      const record = {    
        userId,    
        courseId,    
        chapterId,    
        progress,    
        lastUpdate: new Date().toISOString()    
      };    
  
      // Check if a record already exists    
      const query = this.db.createQuery();    
      query.equalTo('userId', userId);    
      query.equalTo('courseId', courseId);    
      query.equalTo('chapterId', chapterId);    
      const result = await this.db.executeQuery('LearningProgress', query);    
      const existingRecords = result.getSnapshotObjects();    
  
      if (existingRecords.length > 0) {    
        // Update existing record    
        record.id = existingRecords[0].id;    
        await this.db.update('LearningProgress', record);    
      } else {    
        // Insert new record    
        await this.db.insert('LearningProgress', record);    
      }    
    } catch (error) {    
      console.error('Failed to update progress:', error);    
      throw error;    
    }    
  }    
  
  // Get a user's progress in a course    
  async getCourseProgress(userId: string, courseId: string): Promise<Array<any>> {    
    try {    
      const query = this.db.createQuery();    
      query.equalTo('userId', userId);    
      query.equalTo('courseId', courseId);    
      const result = await this.db.executeQuery('LearningProgress', query);    
      return result.getSnapshotObjects();    
    } catch (error) {    
      console.error('Failed to get progress:', error);    
      return [];    
    }    
  }    
}    

6. Developing the Assessment Module

Tests help students reinforce knowledge, while teachers can evaluate teaching effectiveness through results.

// Quiz service class    
export class QuizService {    
  private db: any;    
  
  constructor() {    
    this.db = agconnect.cloudDB();    
  }    
  
  // Get quiz questions for a course    
  async getQuizQuestions(courseId: string, chapterId: string): Promise<Array<any>> {    
    try {    
      const query = this.db.createQuery();    
      query.equalTo('courseId', courseId);    
      query.equalTo('chapterId', chapterId);    
      query.orderByAsc('questionNumber');    
      const result = await this.db.executeQuery('QuizQuestions', query);    
      return result.getSnapshotObjects();    
    } catch (error) {    
      console.error('Failed to get quiz questions:', error);    
      return [];    
    }    
  }    
  
  // Submit quiz answers    
  async submitQuizAnswers(userId: string, quizId: string, answers: Array<any>): Promise<any> {    
    try {    
      const resultRecord = {    
        userId,    
        quizId,    
        answers,    
        submitTime: new Date().toISOString(),    
        score: this.calculateScore(answers)    
      };    
  
      await this.db.insert('QuizResults', resultRecord);    
      return resultRecord;    
    } catch (error) {    
      console.error('Failed to submit quiz:', error);    
      throw error;    
    }    
  }    
  
  // Calculate quiz score    
  private calculateScore(answers: Array<any>): number {    
    let correctCount = 0;    
    answers.forEach(answer => {    
      if (answer.isCorrect) {    
        correctCount++;    
      }    
    });    
    return Math.round((correctCount / answers.length) * 100);    
  }    
}    

7. UI Implementation Example

Below is an example implementation of a course list page:

// Course list page    
@Entry    
@Component    
struct CourseListPage {    
  @State courses: Array<any> = [];    
  @State isLoading: boolean = true;    
  
  private courseService: CourseService = new CourseService();    
  
  aboutToAppear() {    
    this.loadCourses();    
  }    
  
  async loadCourses() {    
    try {    
      // Get current user ID    
      const currentUser = agconnect.auth().getCurrentUser();    
      if (!currentUser) return;    
  
      this.isLoading = true;    
      this.courses = await this.courseService.getCoursesByTeacher(currentUser.uid);    
    } catch (error) {    
      console.error('Failed to load courses:', error);    
    } finally {    
      this.isLoading = false;    
    }    
  }    
  
  build() {    
    Column() {    
      // Title bar    
      Row() {    
        Text('My Courses')    
          .fontSize(24)    
          .fontWeight(FontWeight.Bold)    
        Blank()    
        Button('+ New Course')    
          .onClick(() => {    
            // Navigate to create course page    
            router.pushUrl({ url: 'pages/CreateCoursePage' });    
          })    
      }    
      .width('100%')    
      .padding(20)    
      .justifyContent(FlexAlign.SpaceBetween)    
  
      // Loading indicator    
      if (this.isLoading) {    
        LoadingProgress()    
          .height(100)    
          .width(100)    
      } else {    
        // Course list    
        List({ space: 20 }) {    
          ForEach(this.courses, (course: any) => {    
            ListItem() {    
              CourseCard({ course: course })    
                .onClick(() => {    
                  // Navigate to course details page    
                  router.pushUrl({    
                    url: 'pages/CourseDetailPage',    
                    params: { courseId: course.courseId }    
                  });    
                })    
            }    
          })    
        }    
        .width('100%')    
        .layoutWeight(1)    
        .divider({ strokeWidth: 1, color: '#F1F1F1' })    
      }    
    }    
    .height('100%')    
    .width('100%')    
    .backgroundColor('#F5F5F5')    
  }    
}    
  
// Course card component    
@Component    
struct CourseCard {    
  @Prop course: any;    
  
  build() {    
    Column() {    
      // Course cover image    
      Image(this.course.coverUrl || '/common/default_course.png')    
        .width('100%')    
        .height(120)    
        .objectFit(ImageFit.Cover)    
        .borderRadius(8)    
  
      // Course information    
      Column() {    
        Text(this.course.title)    
          .fontSize(18)    
          .fontWeight(FontWeight.Medium)    
          .margin({ bottom: 4 })    
        Text(this.course.description)    
          .fontSize(14)    
          .fontColor('#666')    
          .maxLines(2)    
          .textOverflow({ overflow: TextOverflow.Ellipsis })    
      }    
      .padding(10)    
      .width('100%')    
    }    
    .width('100%')    
    .backgroundColor(Color.White)    
    .borderRadius(8)    
    .shadow({ radius: 8, color: '#1A000000', offsetX: 2, offsetY: 2 })    
  }    
}    

8. Application Optimization and Expansion Suggestions

8.1 Performance Optimization

  1. Data Caching: Use local databases to cache frequently accessed data and reduce network requests.
  2. Image Optimization: Implement thumbnail techniques to reduce image loading times.
  3. Lazy Loading: Apply lazy loading for long lists to improve scrolling performance.

8.2 Feature Expansion

  1. Real-Time Interaction: Integrate Huawei's Real-Time Communication service for teacher-student interaction.
  2. Data Analytics: Use AppGallery Connect's analytics service to study learning behavior.
  3. Offline Learning: Enable offline support for core features to enhance user experience.
// Example of offline data synchronization    
async syncOfflineData() {    
  try {    
    const db = agconnect.cloudDB();    
    // Sync course data    
    await db.sync('Courses', { policy: 'LOCAL_FIRST' });    
    // Sync learning progress    
    await db.sync('LearningProgress', { policy: 'LOCAL_FIRST' });    
    console.info('Data sync completed');    
  } catch (error) {    
    console.error('Data sync failed:', error);    
  }    
}    

9. Conclusion and Release Preparation

Through this tutorial, we've developed the core features of a Smart Learning Assistant application based on HarmonyOS Next. Before release, ensure:

  1. Complete testing of all features.
  2. Configure app information in AppGallery Connect.
  3. Prepare app screenshots and descriptions.
  4. Follow Huawei AppGallery's publishing guidelines.

Educational app development requires special attention to data security and user experience. HarmonyOS Next provides robust security mechanisms and smooth animations, making it ideal for educational scenarios. This tutorial aims to help you quickly get started with HarmonyOS development and create more outstanding educational applications.


Recent