基于HarmonyOS Next的生活服务应用开发:打造智能生活助手

本文将带您使用HarmonyOS Next 5.0和AppGallery Connect开发一款多功能生活服务应用"LifeHelper"。通过实际代码案例,您将掌握位置服务、天气数据集成、任务管理、社区分享等核心功能的实现方法。所有代码基于ArkTS编写,注释详尽易懂。

一、项目初始化与基础配置

  1. 创建HarmonyOS Next项目

    • 在DevEco Studio中选择"Empty Ability"模板
    • 语言选择ArkTS,项目命名为"LifeHelper"
  2. 添加必要依赖
    oh-package.json5中添加:

    "dependencies": {
      "@hw-agconnect/auth-ohos": "^1.9.0.300",
      "@hw-agconnect/clouddb-ohos": "^1.9.0.300",
      "@ohos.geolocation": "^1.0.0",
      "@ohos.reminderAgent": "^1.0.0",
      "@ohos.net.http": "^1.0.0"
    }

    运行ohpm install安装依赖

  3. 配置AGC服务

    • 在AppGallery Connect创建项目
    • 启用认证服务和云数据库
    • 下载agconnect-services.jsonentry/src/main/resources/rawfile

二、位置服务与周边探索

功能说明:获取用户位置并展示周边生活服务点

// src/main/ets/pages/ExplorePage.ets
import geolocation from '@ohos.geolocation';
import { BusinessError } from '@ohos.base';
import router from '@ohos.router';

@Entry
@Component
struct ExplorePage {
  @State currentLocation: string = "定位中...";
  @State nearbyPlaces: string[] = [];
  @State isLoading: boolean = true;

  // 获取当前位置
  async getLocation() {
    try {
      // 请求位置权限
      await geolocation.requestLocationPermission();
      
      // 获取位置信息
      const location = await geolocation.getCurrentLocation();
      this.currentLocation = `纬度: ${location.latitude.toFixed(4)}, 经度: ${location.longitude.toFixed(4)}`;
      
      // 模拟获取周边地点(实际应调用地图API)
      this.getNearbyPlaces(location);
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error("定位失败:", err.message);
      this.currentLocation = "获取位置失败";
    }
  }

  // 获取周边生活服务点
  getNearbyPlaces(location: geolocation.Location) {
    // 模拟数据 - 实际应调用地图服务API
    setTimeout(() => {
      this.nearbyPlaces = [
        "星巴克 - 300米",
        "永辉超市 - 500米",
        "建设银行 - 800米",
        "社区医院 - 1.2公里"
      ];
      this.isLoading = false;
    }, 1500);
  }

  aboutToAppear() {
    this.getLocation();
  }

  build() {
    Column() {
      Text("当前位置")
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 10 });
      
      Text(this.currentLocation)
        .fontSize(16)
        .margin({ bottom: 30 });
      
      Divider().strokeWidth(1).margin(10);
      
      Text("周边服务")
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 15 });
      
      if (this.isLoading) {
        LoadingProgress()
          .color(Color.Blue)
          .margin(20);
      } else {
        List() {
          ForEach(this.nearbyPlaces, (item: string) => {
            ListItem() {
              Text(item)
                .fontSize(16)
                .padding(15)
            }
          }, (item: string) => item)
        }
        .layoutWeight(1)
        .divider({ strokeWidth: 1, color: "#EEE" })
      }
    }
    .padding(20)
    .width('100%')
    .height('100%')
  }
}

关键注释

  • geolocation.requestLocationPermission():请求位置权限
  • geolocation.getCurrentLocation():获取当前经纬度
  • ForEach:动态渲染周边地点列表
  • aboutToAppear:组件生命周期函数,在页面显示时触发

三、天气信息服务集成

功能说明:调用天气API展示实时天气信息

// src/main/ets/utils/WeatherService.ts
import http from '@ohos.net.http';
import { BusinessError } from '@ohos.base';

export class WeatherService {
  // 获取天气数据(模拟)
  static async getWeatherData(city: string): Promise<any> {
    return new Promise((resolve, reject) => {
      // 实际项目中应替换为真实天气API
      setTimeout(() => {
        resolve({
          temperature: 26,
          condition: "晴",
          humidity: 65,
          windSpeed: 3.2
        });
      }, 800);
    });
  }
}

// src/main/ets/pages/WeatherPage.ets
import { WeatherService } from '../utils/WeatherService';

@Entry
@Component
struct WeatherPage {
  @State weatherData: any = null;
  @State city: string = "北京市";

  async getWeather() {
    try {
      this.weatherData = await WeatherService.getWeatherData(this.city);
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error("获取天气失败:", err.message);
    }
  }

  aboutToAppear() {
    this.getWeather();
  }

  build() {
    Column() {
      if (this.weatherData) {
        Text(this.city)
          .fontSize(24)
          .margin({ top: 20, bottom: 10 });
        
        Row() {
          Text(`${this.weatherData.temperature}℃`)
            .fontSize(36)
            .fontWeight(FontWeight.Bold);
          
          Column() {
            Text(this.weatherData.condition)
              .fontSize(18);
            Text(`湿度: ${this.weatherData.humidity}%`)
              .fontSize(14);
            Text(`风速: ${this.weatherData.windSpeed}km/h`)
              .fontSize(14);
          }
          .margin({ left: 20 })
        }
        .justifyContent(FlexAlign.Center)
        .margin({ bottom: 30 })
      } else {
        LoadingProgress()
          .color(Color.Blue)
          .margin(50)
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Start)
    .padding(20)
  }
}

关键注释

  • 模拟天气API调用(实际项目需替换为真实API)
  • 使用RowColumn进行灵活布局
  • 状态管理确保数据更新时UI自动刷新

四、智能任务管理

功能说明:创建带有提醒功能的任务管理系统

// src/main/ets/model/Task.ts
import { CloudDBZoneWrapper } from '@hw-agconnect/clouddb-ohos';

export class Task extends CloudDBZoneWrapper.objectWrapper() {
  id?: number = undefined;
  userId!: string;
  title!: string;
  description?: string;
  dueDate!: Date;
  completed: boolean = false;

  constructor() {
    super();
    CloudDBZoneWrapper.objectTypeName(this, 'Task');
    CloudDBZoneWrapper.objectFieldPrimaryKey(this, 'id');
    CloudDBZoneWrapper.objectFieldIndex(this, 'userId');
    CloudDBZoneWrapper.objectField(this, 'title');
    CloudDBZoneWrapper.objectField(this, 'description');
    CloudDBZoneWrapper.objectField(this, 'dueDate');
    CloudDBZoneWrapper.objectField(this, 'completed');
  }
}

// src/main/ets/pages/TaskPage.ets
import reminderAgent from '@ohos.reminderAgent';
import { Task } from '../model/Task';
import { CloudDBManager } from '../utils/CloudDBManager';

@Entry
@Component
struct TaskPage {
  @State tasks: Task[] = [];
  @State newTaskTitle: string = '';
  
  // 添加新任务
  async addTask() {
    if (!this.newTaskTitle.trim()) return;
    
    const newTask = new Task();
    newTask.userId = "current_user_id"; // 实际应用中从Auth获取
    newTask.title = this.newTaskTitle;
    newTask.dueDate = new Date();
    
    const dbManager = await CloudDBManager.getInstance();
    await dbManager.saveTask(newTask);
    this.newTaskTitle = '';
    this.loadTasks();
    
    // 设置提醒
    this.setReminder(newTask);
  }
  
  // 设置任务提醒
  async setReminder(task: Task) {
    try {
      const reminder: reminderAgent.ReminderRequest = {
        reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER,
        triggerTimeInSeconds: 10 // 10秒后提醒(实际按需设置)
      };
      
      const reminderId = await reminderAgent.publishReminder(reminder);
      console.info("提醒设置成功,ID:", reminderId);
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error("设置提醒失败:", err.message);
    }
  }
  
  // 加载任务
  async loadTasks() {
    const dbManager = await CloudDBManager.getInstance();
    this.tasks = await dbManager.getUserTasks("current_user_id");
  }
  
  aboutToAppear() {
    this.loadTasks();
  }
  
  build() {
    Column() {
      // 添加任务输入框
      Row() {
        TextInput({ placeholder: "添加新任务..." })
          .width('80%')
          .onChange((value: string) => { this.newTaskTitle = value })
        
        Button('添加')
          .width('20%')
          .onClick(() => this.addTask())
      }
      .padding(10)
      .borderRadius(8)
      .backgroundColor(Color.White)
      .shadow(2)
      .margin({ bottom: 20 })
      
      // 任务列表
      List() {
        ForEach(this.tasks, (task: Task) => {
          ListItem() {
            Row() {
              Column() {
                Text(task.title)
                  .fontSize(18)
                  .fontColor(task.completed ? "#999" : Color.Black)
                  .decoration({ type: task.completed ? TextDecorationType.LineThrough : TextDecorationType.None })
                
                if (task.description) {
                  Text(task.description)
                    .fontSize(14)
                    .fontColor("#666")
                    .margin({ top: 4 })
                }
              }
              .layoutWeight(1)
              
              // 任务状态切换
              Toggle({ type: ToggleType.Checkbox })
                .isOn(task.completed)
                .onChange((isOn) => {
                  task.completed = isOn;
                  this.updateTask(task);
                })
            }
            .padding(15)
          }
        }, (task: Task) => task.id?.toString() ?? '')
      }
      .layoutWeight(1)
    }
    .padding(20)
    .backgroundColor("#f5f5f5")
    .width('100%')
    .height('100%')
  }
  
  // 更新任务状态
  async updateTask(task: Task) {
    const dbManager = await CloudDBManager.getInstance();
    await dbManager.updateTask(task);
  }
}

关键注释

  • reminderAgent.publishReminder:设置定时提醒
  • 使用Toggle组件实现任务完成状态切换
  • CloudDB实现任务数据的云端存储和同步
  • 文本装饰效果展示已完成任务

五、社区分享功能

功能说明:用户分享生活小贴士并互动

// src/main/ets/model/Tip.ts
import { CloudDBZoneWrapper } from '@hw-agconnect/clouddb-ohos';

export class Tip extends CloudDBZoneWrapper.objectWrapper() {
  id?: number = undefined;
  userId!: string;
  userName!: string;
  content!: string;
  createTime: Date = new Date();
  likes: number = 0;
  
  constructor() {
    super();
    CloudDBZoneWrapper.objectTypeName(this, 'Tip');
    CloudDBZoneWrapper.objectFieldPrimaryKey(this, 'id');
    CloudDBZoneWrapper.objectFieldIndex(this, 'userId');
    CloudDBZoneWrapper.objectField(this, 'userName');
    CloudDBZoneWrapper.objectField(this, 'content');
    CloudDBZoneWrapper.objectField(this, 'createTime');
    CloudDBZoneWrapper.objectField(this, 'likes');
  }
}

// src/main/ets/pages/CommunityPage.ets
import { CloudDBManager } from '../utils/CloudDBManager';
import { Tip } from '../model/Tip';

@Entry
@Component
struct CommunityPage {
  @State tips: Tip[] = [];
  @State newTipContent: string = '';
  
  // 加载社区贴士
  async loadCommunityTips() {
    const dbManager = await CloudDBManager.getInstance();
    this.tips = await dbManager.getAllTips();
  }
  
  // 发布新贴士
  async postTip() {
    if (!this.newTipContent.trim()) return;
    
    const newTip = new Tip();
    newTip.userId = "user123"; // 实际应用中从Auth获取
    newTip.userName = "生活达人";
    newTip.content = this.newTipContent;
    
    const dbManager = await CloudDBManager.getInstance();
    await dbManager.saveTip(newTip);
    this.newTipContent = '';
    this.loadCommunityTips();
  }
  
  // 点赞贴士
  async likeTip(tip: Tip) {
    tip.likes += 1;
    const dbManager = await CloudDBManager.getInstance();
    await dbManager.updateTip(tip);
    this.loadCommunityTips();
  }
  
  aboutToAppear() {
    this.loadCommunityTips();
  }
  
  build() {
    Column() {
      // 发布新贴士区域
      Column() {
        Text("分享生活小贴士")
          .fontSize(18)
          .margin({ bottom: 10 });
        
        TextArea({ text: this.newTipContent })
          .height(100)
          .onChange((value: string) => { this.newTipContent = value })
        
        Button('发布')
          .width(120)
          .margin({ top: 10 })
          .onClick(() => this.postTip())
      }
      .padding(15)
      .backgroundColor(Color.White)
      .borderRadius(12)
      .margin({ bottom: 20 })
      
      // 贴士列表
      List() {
        ForEach(this.tips, (tip: Tip) => {
          ListItem() {
            Column() {
              Row() {
                Text(tip.userName)
                  .fontWeight(FontWeight.Bold)
                Text(this.formatDate(tip.createTime))
                  .fontSize(12)
                  .fontColor("#999")
                  .margin({ left: 10 })
              }
              .margin({ bottom: 8 })
              
              Text(tip.content)
                .fontSize(16)
                .margin({ bottom: 12 })
              
              Row() {
                Image($r('app.media.like_icon'))
                  .width(20)
                  .height(20)
                  .margin({ right: 5 })
                Text(tip.likes.toString())
                  .fontColor("#ff5252")
                
                Button("点赞")
                  .height(30)
                  .margin({ left: 15 })
                  .onClick(() => this.likeTip(tip))
              }
            }
            .padding(15)
            .backgroundColor("#ffffff")
            .borderRadius(12)
          }
        }, (tip: Tip) => tip.id?.toString() ?? '')
      }
      .layoutWeight(1)
    }
    .padding(20)
    .backgroundColor("#f8f8f8")
    .width('100%')
    .height('100%')
  }
  
  // 日期格式化
  formatDate(date: Date): string {
    return `${date.getMonth()+1}月${date.getDate()}日 ${date.getHours()}:${date.getMinutes()}`;
  }
}

关键注释

  • 使用TextArea实现多行文本输入
  • 时间格式化展示
  • 点赞互动功能
  • 列表项使用卡片式设计提升用户体验

六、用户系统集成

功能说明:实现用户登录和个人资料管理

// src/main/ets/pages/ProfilePage.ets
import { AuthService } from '@hw-agconnect/auth-ohos';
import router from '@ohos.router';

@Entry
@Component
struct ProfilePage {
  @State userName: string = "未登录";
  @State userEmail: string = "";
  @State isLoggedIn: boolean = false;
  
  // 检查登录状态
  async checkLoginStatus() {
    try {
      const user = AuthService.getCurrentUser();
      if (user) {
        this.userName = user.getDisplayName() || "用户";
        this.userEmail = user.getEmail() || "";
        this.isLoggedIn = true;
      }
    } catch (error) {
      console.error("获取用户信息失败");
    }
  }
  
  // 用户登录
  async login() {
    try {
      // 使用AGC Auth登录(此处简化流程)
      // 实际应调用AuthService.signIn()
      setTimeout(() => {
        this.userName = "张三";
        this.userEmail = "zhangsan@example.com";
        this.isLoggedIn = true;
      }, 800);
    } catch (error) {
      console.error("登录失败");
    }
  }
  
  // 用户退出
  logout() {
    AuthService.signOut();
    this.isLoggedIn = false;
    this.userName = "未登录";
    this.userEmail = "";
  }
  
  aboutToAppear() {
    this.checkLoginStatus();
  }
  
  build() {
    Column() {
      if (this.isLoggedIn) {
        Image($r('app.media.user_avatar'))
          .width(100)
          .height(100)
          .margin({ top: 30, bottom: 20 })
          .borderRadius(50)
        
        Text(this.userName)
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .margin({ bottom: 10 })
        
        Text(this.userEmail)
          .fontSize(16)
          .fontColor("#666")
          .margin({ bottom: 30 })
        
        Button("退出登录")
          .width('80%')
          .height(45)
          .onClick(() => this.logout())
      } else {
        Column() {
          Text("欢迎使用LifeHelper")
            .fontSize(24)
            .margin({ bottom: 30 })
          
          Button("登录/注册")
            .width('80%')
            .height(50)
            .fontSize(18)
            .onClick(() => this.login())
        }
        .height('100%')
        .justifyContent(FlexAlign.Center)
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

关键注释

  • 用户状态管理(登录/未登录)
  • 用户信息展示
  • 登录/登出功能实现
  • 响应式UI根据登录状态变化

总结

通过本教程,您已掌握了使用HarmonyOS Next 5.0和AppGallery Connect开发生活服务应用的核心技能:

  1. 位置服务集成:精准获取用户位置并提供周边服务
  2. 天气数据展示:集成第三方API展示实时天气信息
  3. 智能任务管理:创建带提醒功能的待办事项系统
  4. 社区互动功能:实现内容分享和用户互动
  5. 用户系统:完整的登录和个人资料管理

这些功能模块可以灵活组合,构建出各种生活服务类应用。HarmonyOS Next的分布式能力让您的应用可以无缝运行在手机、平板、智能手表等多种设备上,为用户提供一致的生活服务体验。

实际开发中,您还可以进一步扩展:

  • 集成支付服务实现生活缴费
  • 添加智能家居控制模块
  • 开发基于位置的生活提醒功能
  • 实现AI助手提供个性化建议

使用ArkTS的声明式UI开发模式和AppGallery Connect的后端服务,您可以高效构建功能丰富、性能卓越的生活服务应用,为用户打造更智能、便捷的生活方式。


林钟雪
4 声望0 粉丝