DEV Community

linzhongxue
linzhongxue

Posted on

Comprehensive Guide to Developing Smart Life Service Applications Based on HarmonyOS Next

Comprehensive Guide to Developing Smart Life Service Applications Based on HarmonyOS Next

1. Preparation for AppGallery Connect Service Integration

1.1 Setting Up the Development Environment

First, ensure that the latest version of DevEco Studio and the HarmonyOS SDK are installed. When creating a new project, select the "Application" template, choose "Phone" as the device type, and select ArkTS as the programming language.

// Example code for environment configuration check  
import hilog from '@ohos.hilog';  

@Entry  
@Component  
struct EnvCheckPage {  
  build() {  
    Column() {  
      Text('Environment Check')  
        .fontSize(24)  
        .margin({ bottom: 20 })  

      Button('Verify Development Environment')  
        .onClick(() => {  
          try {  
            hilog.info(0x0000, 'EnvCheck', 'Environment verification passed');  
            // Additional environment check logic can be added here  
          } catch (error) {  
            hilog.error(0x0000, 'EnvCheck', 'Environment verification failed: %{public}s', error.message);  
          }  
        })  
    }  
    .width('100%')  
    .height('100%')  
    .justifyContent(FlexAlign.Center)  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

1.2 Configuring the AppGallery Connect Project

  1. Log in to the AppGallery Connect console.
  2. Create a new project and add a HarmonyOS application.
  3. Download the agconnect-services.json configuration file.
  4. Place the configuration file in the entry/src/main/resources/rawfile/ directory.

2. Developing the User Authentication Module

2.1 Implementing Phone Number Authentication

// Example of phone number authentication component  
import { AGConnectAuth, PhoneAuthProvider } from '@hw-agconnect/auth-ohos';  

@Entry  
@Component  
struct PhoneLogin {  
  @State phoneNumber: string = ''  
  @State verifyCode: string = ''  
  @State countdown: number = 0  
  private timer: number = 0  

  // Send verification code  
  sendCode() {  
    if (!this.phoneNumber) return  

    const provider = PhoneAuthProvider.createProvider()  
    provider.requestVerifyCode(this.phoneNumber, {  
      action: 0, // 0: Login/Register 1: Reset Password  
      locale: 'zh_CN',  
      sendInterval: 30  
    }).then(() => {  
      hilog.info(0x0000, 'Auth', 'Verification code sent successfully')  
      this.startCountdown()  
    }).catch((err) => {  
      hilog.error(0x0000, 'Auth', 'Failed to send verification code: %{public}s', err.message)  
    })  
  }  

  // Countdown handling  
  startCountdown() {  
    this.countdown = 60  
    this.timer = setInterval(() => {  
      if (this.countdown <= 0) {  
        clearInterval(this.timer)  
        return  
      }  
      this.countdown--  
    }, 1000)  
  }  

  // Login with verification code  
  loginWithCode() {  
    const credential = PhoneAuthProvider.credentialWithVerifyCode(  
      this.phoneNumber,   
      this.verifyCode  
    )  

    AGConnectAuth.getInstance().signIn(credential).then((user) => {  
      hilog.info(0x0000, 'Auth', 'Login successful: %{public}s', user.uid)  
      // Navigate to the home page  
    }).catch((err) => {  
      hilog.error(0x0000, 'Auth', 'Login failed: %{public}s', err.message)  
    })  
  }  

  build() {  
    Column({ space: 15 }) {  
      TextInput({ placeholder: 'Enter phone number' })  
        .width('80%')  
        .onChange((value: string) => {  
          this.phoneNumber = value  
        })  

      Row({ space: 10 }) {  
        TextInput({ placeholder: 'Verification code' })  
          .width('60%')  
          .onChange((value: string) => {  
            this.verifyCode = value  
          })  

        Button(this.countdown > 0 ? `${this.countdown}s` : 'Get Verification Code')  
          .width('40%')  
          .enabled(this.countdown === 0)  
          .onClick(() => this.sendCode())  
      }  
      .width('80%')  

      Button('Login')  
        .width('80%')  
        .onClick(() => this.loginWithCode())  
    }  
    .width('100%')  
    .height('100%')  
    .justifyContent(FlexAlign.Center)  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

3. Integrating Cloud Database

3.1 Defining and Operating Data Models

// Example of life service data model operations  
import { AGConnectCloudDB } from '@hw-agconnect/database-ohos';  

// Define service data model  
class ServiceItem {  
  id: string = ''  
  name: string = ''  
  category: string = ''  
  price: number = 0  
  rating: number = 0  
  description?: string  
}  

@Entry  
@Component  
struct ServiceList {  
  private cloudDB: AGConnectCloudDB | null = null  
  @State serviceList: ServiceItem[] = []  

  aboutToAppear() {  
    this.initCloudDB()  
  }  

  // Initialize cloud database  
  async initCloudDB() {  
    try {  
      this.cloudDB = AGConnectCloudDB.getInstance()  
      await this.cloudDB.createObjectType('ServiceItem')  
      await this.cloudDB.openCloudDBZone('services')  
      this.queryServices()  
    } catch (error) {  
      hilog.error(0x0000, 'CloudDB', 'Initialization failed: %{public}s', error.message)  
    }  
  }  

  // Query service list  
  async queryServices() {  
    if (!this.cloudDB) return  

    const query = this.cloudDB.createQuery(ServiceItem)  
    const snapshot = await this.cloudDB.executeQuery(query)  
    this.serviceList = snapshot.getSnapshotObjects()  
  }  

  // Add new service  
  async addService(item: ServiceItem) {  
    if (!this.cloudDB) return  

    try {  
      await this.cloudDB.executeUpsert(item)  
      hilog.info(0x0000, 'CloudDB', 'Service added successfully')  
      this.queryServices() // Refresh the list  
    } catch (error) {  
      hilog.error(0x0000, 'CloudDB', 'Failed to add: %{public}s', error.message)  
    }  
  }  

  build() {  
    Column() {  
      List({ space: 10 }) {  
        ForEach(this.serviceList, (item: ServiceItem) => {  
          ListItem() {  
            ServiceCard({ item: item })  
          }  
        })  
      }  
      .width('100%')  
      .layoutWeight(1)  

      Button('Add Test Data')  
        .margin(10)  
        .onClick(() => {  
          const newItem = new ServiceItem()  
          newItem.id = Date.now().toString()  
          newItem.name = 'Test Service'  
          newItem.category = 'Home Service'  
          newItem.price = 99  
          newItem.rating = 4.5  
          this.addService(newItem)  
        })  
    }  
  }  
}  

@Component  
struct ServiceCard {  
  @Prop item: ServiceItem  

  build() {  
    Row() {  
      Column() {  
        Text(this.item.name)  
          .fontSize(18)  
          .fontWeight(FontWeight.Bold)  

        Text(`Category: ${this.item.category}`)  
          .fontSize(14)  
          .margin({ top: 5 })  

        Row() {  
          Text(${this.item.price}`)  
            .fontColor(Color.Red)  

          Text(`Rating: ${this.item.rating}`)  
            .margin({ left: 15 })  
        }  
        .margin({ top: 5 })  
      }  
      .margin(10)  
    }  
    .width('90%')  
    .padding(10)  
    .borderRadius(8)  
    .backgroundColor('#FFF')  
    .margin({ top: 5, bottom: 5 })  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

4. Practical Application: Service Booking Function

4.1 Implementing the Complete Booking Process

// Implementation of the service booking module  
import { AGConnectFunction } from '@hw-agconnect/function-ohos';  

@Entry  
@Component  
struct ServiceBooking {  
  @State selectedService: ServiceItem | null = null  
  @State bookingDate: string = new Date().toLocaleDateString()  
  @State bookingTime: string = '10:00'  
  @State address: string = ''  
  @State contacts: string = ''  
  @State phone: string = ''  

  // Submit booking  
  submitBooking() {  
    if (!this.selectedService || !this.address || !this.contacts || !this.phone) {  
      hilog.warn(0x0000, 'Booking', 'Please fill in all information')  
      return  
    }  

    const bookingData = {  
      serviceId: this.selectedService.id,  
      serviceName: this.selectedService.name,  
      bookingTime: `${this.bookingDate} ${this.bookingTime}`,  
      address: this.address,  
      contacts: this.contacts,  
      phone: this.phone,  
      status: 'pending',  
      createTime: new Date().toISOString()  
    }  

    // Call cloud function to handle booking logic  
    AGConnectFunction.getInstance()  
      .wrap('bookService')  
      .call(bookingData)  
      .then((result) => {  
        const response = result.getValue()  
        hilog.info(0x0000, 'Booking', 'Booking successful: %{public}s', response.orderId)  
        // Navigate to order details page  
      })  
      .catch((error) => {  
        hilog.error(0x0000, 'Booking', 'Booking failed: %{public}s', error.message)  
      })  
  }  

  build() {  
    Column({ space: 15 }) {  
      if (this.selectedService) {  
        ServiceCard({ item: this.selectedService })  

        Text('Booking Information').fontSize(18).margin({ top: 20 })  

        DatePicker({  
          start: new Date(),  
          end: new Date(2025, 11, 31)  
        })  
        .onChange((value: DatePickerResult) => {  
          this.bookingDate = `${value.year}-${value.month}-${value.day}`  
        })  

        TimePicker()  
          .onChange((value: TimePickerResult) => {  
            this.bookingTime = `${value.hour}:${value.minute}`  
          })  

        TextInput({ placeholder: 'Service Address' })  
          .onChange((value: string) => {  
            this.address = value  
          })  

        TextInput({ placeholder: 'Contact Person' })  
          .onChange((value: string) => {  
            this.contacts = value  
          })  

        TextInput({ placeholder: 'Contact Phone' })  
          .onChange((value: string) => {  
            this.phone = value  
          })  

        Button('Confirm Booking')  
          .width('80%')  
          .onClick(() => this.submitBooking())  
      } else {  
        Text('Please select a service first').fontSize(18)  
      }  
    }  
    .padding(20)  
    .width('100%')  
    .height('100%')  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

5. Application Publishing and Operations

5.1 Packaging and Publishing the Application

  1. In DevEco Studio, select Build > Generate Key and CSR to generate a signing certificate.
  2. Configure the signing information in the project's build-profile.json5 file.
  3. Execute Build > Build HAP(s)/APP(s) > Build APP to generate the release package.
  4. Log in to AppGallery Connect and submit the application for review.

5.2 Integrating Operational Data Analysis

// Integrating application data analysis  
import { AGConnectAnalytics } from '@hw-agconnect/analytics-ohos';  

// Initialize in the application entry  
export default class AppAnalytics {  
  static init() {  
    AGConnectAnalytics.getInstance().setAnalyticsEnabled(true)  
    // Set user attributes  
    AGConnectAnalytics.getInstance().setUserProfile('user_level', 'normal')  
  }  

  // Record custom events  
  static trackEvent(eventName: string, params?: Record<string, string>) {  
    AGConnectAnalytics.getInstance().onEvent(eventName, params)  
  }  
}  

// Call in aboutToAppear  
AppAnalytics.init()  
AppAnalytics.trackEvent('app_launch')  
Enter fullscreen mode Exit fullscreen mode

Through the above complete development process, you have mastered the core technologies for developing life service applications based on HarmonyOS Next and AppGallery Connect. From user authentication to data storage, from business logic to operational analysis, these modules can be combined to build feature-rich, high-quality smart life service applications.

Top comments (0)