鸿蒙智能饮水提醒应用开发指南 原创
鸿蒙智能饮水提醒应用开发指南
一、系统架构设计
基于HarmonyOS的AI能力和分布式技术,我们设计了一套智能饮水提醒系统,主要功能包括:
人脸检测:通过摄像头检测用户面部特征
脱水分析:AI分析面部特征判断脱水状态
饮水记录:记录用户饮水时间和量
多设备同步:跨设备同步健康数据和提醒
健康建议:根据脱水程度提供饮水建议
!https://example.com/harmony-hydration-arch.png
二、核心代码实现
人脸检测服务
// FaceDetectionService.ets
import camera from ‘@ohos.multimedia.camera’;
import image from ‘@ohos.multimedia.image’;
import face from ‘@ohos.ai.face’;
class FaceDetectionService {
private static instance: FaceDetectionService;
private cameraManager: camera.CameraManager;
private faceDetector: face.FaceDetector;
private cameraInput: camera.CameraInput | null = null;
private previewOutput: camera.PreviewOutput | null = null;
private constructor() {
this.cameraManager = camera.getCameraManager();
this.faceDetector = face.createFaceDetector();
public static getInstance(): FaceDetectionService {
if (!FaceDetectionService.instance) {
  FaceDetectionService.instance = new FaceDetectionService();
return FaceDetectionService.instance;
public async initCamera(previewSurfaceId: string): Promise<void> {
const cameras = this.cameraManager.getSupportedCameras();
if (cameras.length === 0) {
  throw new Error('No camera available');
this.cameraInput = this.cameraManager.createCameraInput(cameras[0]);
await this.cameraInput.open();
const previewProfile = this.cameraManager.getSupportedOutputCapability(
  cameras[0],
  camera.ProfileMode.PROFILE_MODE_DEFAULT
).previewProfiles[0];
this.previewOutput = this.cameraManager.createPreviewOutput(
  previewProfile,
  previewSurfaceId
);
public async detectFace(image: image.Image): Promise<FaceDetectionResult> {
const detectionOptions = {
  featureType: face.FeatureType.FEATURE_TYPE_ALL,
  processMode: face.ProcessMode.PROCESS_MODE_FAST
};
return new Promise((resolve, reject) => {
  this.faceDetector.detect(image, detectionOptions, (err, result) => {
    if (err) {
      reject(err);
else {
      resolve(this.processFaceResult(result));
});
});
private processFaceResult(rawData: any): FaceDetectionResult {
if (!rawData || rawData.faces.length === 0) {
  return { faceDetected: false };
const face = rawData.faces[0];
return {
  faceDetected: true,
  boundingBox: face.boundingBox,
  landmarks: face.landmarks,
  skinTone: face.skinTone,
  skinMoisture: face.skinMoisture,
  darkCircles: face.darkCircles,
  confidence: face.confidence
};
}
export const faceDetectionService = FaceDetectionService.getInstance();
脱水分析服务
// HydrationAnalysisService.ets
import http from ‘@ohos.net.http’;
class HydrationAnalysisService {
private static instance: HydrationAnalysisService;
private httpClient: http.HttpRequest;
private apiKey = ‘YOUR_HYDRATION_API_KEY’;
private constructor() {
this.httpClient = http.createHttp();
public static getInstance(): HydrationAnalysisService {
if (!HydrationAnalysisService.instance) {
  HydrationAnalysisService.instance = new HydrationAnalysisService();
return HydrationAnalysisService.instance;
public async analyzeHydration(faceData: FaceDetectionResult): Promise<HydrationStatus> {
return new Promise((resolve, reject) => {
  this.httpClient.request(
    'https://hydration-api.example.com/analyze',
method: ‘POST’,
      header: { 'Content-Type': 'application/json' },
      extraData: JSON.stringify({
        skin_moisture: faceData.skinMoisture,
        skin_tone: faceData.skinTone,
        dark_circles: faceData.darkCircles,
        api_key: this.apiKey
      })
    },
    (err, data) => {
      if (err) {
        reject(err);
else {
        const result = JSON.parse(data.result);
        resolve(this.processHydrationResult(result));
}
  );
});
private processHydrationResult(rawData: any): HydrationStatus {
return {
  hydrationLevel: rawData.hydration_level || 'normal',
  dehydrationScore: rawData.dehydration_score || 0,
  suggestedWaterIntake: rawData.suggested_water_intake || 200,
  symptoms: rawData.symptoms || [],
  timestamp: Date.now()
};
public calculateDailyRequirement(userProfile: UserProfile): number {
// 基础水需求量计算(毫升)
let baseRequirement = userProfile.weight * 30; // 30ml/kg
// 根据活动量调整
if (userProfile.activityLevel === 'low') {
  baseRequirement *= 0.9;
else if (userProfile.activityLevel === ‘high’) {
  baseRequirement *= 1.2;
// 根据气候调整
if (userProfile.environment === 'hot') {
  baseRequirement *= 1.3;
else if (userProfile.environment === ‘cold’) {
  baseRequirement *= 0.9;
return Math.round(baseRequirement);
}
export const hydrationService = HydrationAnalysisService.getInstance();
多设备同步服务
// HydrationSyncService.ets
import distributedData from ‘@ohos.data.distributedData’;
import deviceManager from ‘@ohos.distributedHardware.deviceManager’;
class HydrationSyncService {
private static instance: HydrationSyncService;
private kvManager: distributedData.KVManager;
private kvStore: distributedData.KVStore;
private constructor() {
this.initKVStore();
private async initKVStore(): Promise<void> {
const config = {
  bundleName: 'com.example.hydrationReminder',
  userInfo: { userId: 'currentUser' }
};
this.kvManager = distributedData.createKVManager(config);
this.kvStore = await this.kvManager.getKVStore('hydration_store', {
  createIfMissing: true
});
this.kvStore.on('dataChange', (data) => {
  this.handleRemoteUpdate(data);
});
public static getInstance(): HydrationSyncService {
if (!HydrationSyncService.instance) {
  HydrationSyncService.instance = new HydrationSyncService();
return HydrationSyncService.instance;
public async syncHydrationRecord(record: HydrationRecord): Promise<void> {
await this.kvStore.put(hydration_${record.id}, JSON.stringify(record));
public async getHydrationRecords(date: string): Promise<HydrationRecord[]> {
const entries = await this.kvStore.getEntries('hydration_');
return Array.from(entries)
  .map(([_, value]) => JSON.parse(value))
  .filter(record => record.date === date);
public async syncUserProfile(profile: UserProfile): Promise<void> {
await this.kvStore.put('user_profile', JSON.stringify(profile));
public async getUserProfile(): Promise<UserProfile | null> {
const value = await this.kvStore.get('user_profile');
return value ? JSON.parse(value) : null;
public async syncHydrationStatus(status: HydrationStatus): Promise<void> {
await this.kvStore.put('hydration_status', JSON.stringify(status));
public async getHydrationStatus(): Promise<HydrationStatus | null> {
const value = await this.kvStore.get('hydration_status');
return value ? JSON.parse(value) : null;
private handleRemoteUpdate(data: distributedData.ChangeInfo): void {
if (data.deviceId === deviceInfo.deviceId) return;
const key = data.key as string;
if (key.startsWith('hydration_')) {
  const record = JSON.parse(data.value);
  EventBus.emit('hydrationRecordUpdated', record);
else if (key === ‘user_profile’) {
  const profile = JSON.parse(data.value);
  EventBus.emit('userProfileUpdated', profile);
else if (key === ‘hydration_status’) {
  const status = JSON.parse(data.value);
  EventBus.emit('hydrationStatusUpdated', status);
}
export const hydrationSyncService = HydrationSyncService.getInstance();
三、主界面实现
人脸检测界面
// FaceDetectionView.ets
@Component
struct FaceDetectionView {
@State previewSurfaceId: string = ‘’;
@State faceResult: FaceDetectionResult | null = null;
@State hydrationStatus: HydrationStatus | null = null;
@State isAnalyzing: boolean = false;
aboutToAppear() {
this.initCamera();
build() {
Stack() {
  // 相机预览
  XComponent({
    id: 'faceCameraPreview',
    type: 'surface',
    libraryname: 'libcamera.so',
    controller: this.previewController
  })
  .onLoad(() => {
    this.previewSurfaceId = this.previewController.getXComponentSurfaceId();
    faceDetectionService.initCamera(this.previewSurfaceId);
  })
  .width('100%')
  .height('100%')
  
  // 人脸检测框
  if (this.faceResult?.faceDetected) {
    Rect()
      .width(this.faceResult.boundingBox.width)
      .height(this.faceResult.boundingBox.height)
      .position({
        x: this.faceResult.boundingBox.x,
        y: this.faceResult.boundingBox.y
      })
      .borderWidth(2)
      .borderColor('#4CAF50')
// 检测按钮
  Button('检测水分状态')
    .onClick(() => this.detectAndAnalyze())
    .position({ x: '50%', y: '90%' })
  
  // 分析状态
  if (this.isAnalyzing) {
    LoadingProgress()
      .position({ x: '50%', y: '50%' })
// 结果显示
  if (this.hydrationStatus) {
    HydrationStatusView({ status: this.hydrationStatus })
      .position({ x: '50%', y: '30%' })
}
private async detectAndAnalyze(): Promise<void> {
this.isAnalyzing = true;
const image = await faceDetectionService.captureFaceImage();
this.faceResult = await faceDetectionService.detectFace(image);
if (this.faceResult.faceDetected) {
  this.hydrationStatus = await hydrationService.analyzeHydration(this.faceResult);
  await hydrationSyncService.syncHydrationStatus(this.hydrationStatus);
  
  // 根据状态决定是否提醒
  if (this.hydrationStatus.hydrationLevel === 'dehydrated') {
    EventBus.emit('hydrationAlert', this.hydrationStatus);
}
this.isAnalyzing = false;
}
@Component
struct HydrationStatusView {
private status: HydrationStatus;
build() {
Column() {
Text(this.getStatusTitle())
.fontSize(20)
.fontColor(this.getStatusColor())
  Text(建议饮水量: ${this.status.suggestedWaterIntake}ml)
    .fontSize(16)
    .margin({ top: 8 })
  
  if (this.status.symptoms.length > 0) {
    Text(症状: ${this.status.symptoms.join(', ')})
      .fontSize(14)
      .margin({ top: 8 })
Button(‘记录饮水’)
    .onClick(() => this.recordWaterIntake())
    .margin({ top: 16 })
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(8)
private getStatusTitle(): string {
switch (this.status.hydrationLevel) {
  case 'dehydrated': return '脱水状态!需要立即补水';
  case 'normal': return '水分状态正常';
  case 'hydrated': return '水分充足';
  default: return '未知状态';
}
private getStatusColor(): string {
switch (this.status.hydrationLevel) {
case ‘dehydrated’: return ‘#FF5722’;
case ‘normal’: return ‘#4CAF50’;
case ‘hydrated’: return ‘#2196F3’;
default: return ‘#000000’;
}
private async recordWaterIntake(): Promise<void> {
const record: HydrationRecord = {
id: generateId(),
amount: this.status.suggestedWaterIntake,
timestamp: Date.now(),
status: this.status.hydrationLevel
};
await hydrationSyncService.syncHydrationRecord(record);
EventBus.emit('waterIntakeRecorded', record);
}
function generateId(): string {
return Math.random().toString(36).substring(2) + Date.now().toString(36);
饮水记录界面
// HydrationHistoryView.ets
@Component
struct HydrationHistoryView {
@State records: HydrationRecord[] = [];
@State dailyGoal: number = 2000;
@State consumed: number = 0;
aboutToAppear() {
this.loadRecords();
this.loadUserProfile();
EventBus.on(‘hydrationRecordUpdated’, () => this.loadRecords());
build() {
Column() {
  // 今日饮水进度
  Text('今日饮水')
    .fontSize(24)
    .fontWeight(FontWeight.Bold)
    .margin({ top: 16 })
  
  Progress({
    value: this.consumed,
    total: this.dailyGoal,
    type: ProgressType.PROGRESS_TYPE_LINEAR
  })
  .width('90%')
  .height(20)
  .margin({ top: 16 })
  
  Text({this.consumed} / {this.dailyGoal} ml)
    .fontSize(16)
    .margin({ top: 8 })
  
  // 快速记录按钮
  Row() {
    Button('+200ml')
      .onClick(() => this.recordIntake(200))
    
    Button('+500ml')
      .onClick(() => this.recordIntake(500))
      .margin({ left: 16 })
.margin({ top: 24 })
  // 记录列表
  if (this.records.length === 0) {
    Text('暂无饮水记录')
      .fontSize(16)
      .margin({ top: 32 })
else {
    List({ space: 10 }) {
      ForEach(this.records, (record) => {
        ListItem() {
          HydrationRecordItem({ record })
})
.layoutWeight(1)
}
.padding(16)
private async loadRecords(): Promise<void> {
const today = new Date().toISOString().split('T')[0];
this.records = await hydrationSyncService.getHydrationRecords(today);
this.consumed = this.records.reduce((sum, r) => sum + r.amount, 0);
private async loadUserProfile(): Promise<void> {
const profile = await hydrationSyncService.getUserProfile();
if (profile) {
  this.dailyGoal = hydrationService.calculateDailyRequirement(profile);
}
private async recordIntake(amount: number): Promise<void> {
const record: HydrationRecord = {
id: generateId(),
amount,
timestamp: Date.now(),
status: ‘manual’
};
await hydrationSyncService.syncHydrationRecord(record);
}
@Component
struct HydrationRecordItem {
private record: HydrationRecord;
build() {
Row() {
Column() {
Text(${this.record.amount}ml)
.fontSize(18)
    Text(formatTime(this.record.timestamp))
      .fontSize(14)
      .fontColor('#666666')
      .margin({ top: 4 })
.layoutWeight(1)
  if (this.record.status === 'dehydrated') {
    Text('脱水状态')
      .fontSize(14)
      .fontColor('#FF5722')
}
.padding(12)
}
function formatTime(timestamp: number): string {
const date = new Date(timestamp);
return {date.getHours()}:{date.getMinutes().toString().padStart(2, ‘0’)};
健康报告界面
// HealthReportView.ets
@Component
struct HealthReportView {
@State hydrationData: HydrationData[] = [];
@State userProfile: UserProfile | null = null;
aboutToAppear() {
this.loadData();
this.loadUserProfile();
build() {
Column() {
  if (this.userProfile) {
    Text(${this.userProfile.name}的健康报告)
      .fontSize(24)
      .fontWeight(FontWeight.Bold)
      .margin({ top: 16 })
    
    // 本周饮水趋势
    Text('本周饮水趋势')
      .fontSize(20)
      .margin({ top: 24 })
    
    if (this.hydrationData.length > 0) {
      Row() {
        ForEach(this.hydrationData, (day) => {
          Column() {
            Text('')
              .width(20)
              .height(day.amount / 50) // 比例缩放
              .backgroundColor('#2196F3')
            
            Text(day.day)
              .fontSize(12)
              .margin({ top: 4 })
.margin({ right: 8 })
        })
.height(100)
      .margin({ top: 8 })
// 脱水状态统计
    Text('脱水状态统计')
      .fontSize(20)
      .margin({ top: 24 })
    
    if (this.hydrationData.some(d => d.dehydratedCount > 0)) {
      Row() {
        Text(脱水次数: ${this.hydrationData.reduce((sum, d) => sum + d.dehydratedCount, 0)})
          .fontSize(16)
        
        Text(最严重: ${Math.max(...this.hydrationData.map(d => d.dehydrationScore))}分)
          .fontSize(16)
          .margin({ left: 16 })
.margin({ top: 8 })
else {
      Text('本周未检测到脱水状态')
        .fontSize(16)
        .margin({ top: 8 })
// 健康建议
    Text('健康建议')
      .fontSize(20)
      .margin({ top: 24 })
    
    if (this.hydrationData.length > 0) {
      const avgIntake = this.hydrationData.reduce((sum, d) => sum + d.amount, 0) / this.hydrationData.length;
      const requirement = this.userProfile ? 
        hydrationService.calculateDailyRequirement(this.userProfile) : 2000;
      
      if (avgIntake < requirement * 0.8) {
        Text('您的平均饮水量低于建议值,建议增加每日饮水量')
          .fontSize(16)
          .margin({ top: 8 })
else if (avgIntake > requirement * 1.2) {
        Text('您的饮水量充足,继续保持')
          .fontSize(16)
          .margin({ top: 8 })
else {
        Text('您的饮水量在正常范围内,继续保持良好习惯')
          .fontSize(16)
          .margin({ top: 8 })
}
}
.padding(16)
private async loadData(): Promise<void> {
// 获取最近7天数据
const entries = await hydrationSyncService.getHydrationRecords();
const now = new Date();
this.hydrationData = Array.from({ length: 7 }, (_, i) => {
  const date = new Date(now);
  date.setDate(date.getDate() - i);
  const dateStr = date.toISOString().split('T')[0];
  const dayRecords = entries.filter(r => r.date === dateStr);
  
  return {
    day: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()],
    date: dateStr,
    amount: dayRecords.reduce((sum, r) => sum + r.amount, 0),
    dehydratedCount: dayRecords.filter(r => r.status === 'dehydrated').length,
    dehydrationScore: dayRecords.reduce((max, r) => 
      r.dehydrationScore ? Math.max(max, r.dehydrationScore) : max, 0
    )
  };
}).reverse();
private async loadUserProfile(): Promise<void> {
this.userProfile = await hydrationSyncService.getUserProfile();
}
四、高级功能实现
多设备协同提醒
// CollaborativeReminderService.ets
class CollaborativeReminderService {
private static instance: CollaborativeReminderService;
private constructor() {}
public static getInstance(): CollaborativeReminderService {
if (!CollaborativeReminderService.instance) {
CollaborativeReminderService.instance = new CollaborativeReminderService();
return CollaborativeReminderService.instance;
public async syncReminderToDevices(reminder: HydrationReminder): Promise<void> {
const devices = await deviceManager.getTrustedDevices();
await Promise.all(devices.map(device => 
  this.sendReminderToDevice(device.id, reminder)
));
private async sendReminderToDevice(deviceId: string, reminder: HydrationReminder): Promise<void> {
const ability = await featureAbility.startAbility({
  bundleName: 'com.example.hydrationReminder',
  abilityName: 'HydrationReminderAbility',
  deviceId
});
await ability.call({
  method: 'receiveReminder',
  parameters: [reminder]
});
public async syncEmergencyAlert(status: HydrationStatus): Promise<void> {
if (status.hydrationLevel !== 'dehydrated') return;
const devices = await deviceManager.getTrustedDevices();
await Promise.all(devices.map(device => 
  this.sendAlertToDevice(device.id, status)
));
private async sendAlertToDevice(deviceId: string, status: HydrationStatus): Promise<void> {
const ability = await featureAbility.startAbility({
  bundleName: 'com.example.hydrationReminder',
  abilityName: 'HydrationAlertAbility',
  deviceId
});
await ability.call({
  method: 'receiveEmergencyAlert',
  parameters: [status]
});
}
export const collaborativeReminderService = CollaborativeReminderService.getInstance();
智能饮水计划
// HydrationPlanService.ets
import reminderAgent from ‘@ohos.reminderAgent’;
class HydrationPlanService {
private static instance: HydrationPlanService;
private constructor() {}
public static getInstance(): HydrationPlanService {
if (!HydrationPlanService.instance) {
HydrationPlanService.instance = new HydrationPlanService();
return HydrationPlanService.instance;
public async createDailyPlan(userProfile: UserProfile): Promise<void> {
const dailyRequirement = hydrationService.calculateDailyRequirement(userProfile);
const intervals = this.calculateOptimalIntervals(dailyRequirement);
await this.cancelAllReminders();
for (const interval of intervals) {
  await this.scheduleReminder(interval.time, interval.amount);
}
private calculateOptimalIntervals(total: number): { time: string; amount: number }[] {
// 将总水量分配到一天中的最佳时间点
const intervals = [
time: ‘08:00’, amount: Math.round(total * 0.2) },
time: ‘11:00’, amount: Math.round(total * 0.2) },
time: ‘14:00’, amount: Math.round(total * 0.2) },
time: ‘17:00’, amount: Math.round(total * 0.2) },
time: ‘20:00’, amount: Math.round(total * 0.2) }
];
return intervals;
private async scheduleReminder(time: string, amount: number): Promise<void> {
const [hours, minutes] = time.split(':').map(Number);
const reminderTime = new Date();
reminderTime.setHours(hours, minutes, 0, 0);
const reminderRequest: reminderAgent.ReminderRequest = {
  reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER,
  actionButton: [{ title: '已饮水' }, { title: '稍后提醒' }],
  wantAgent: {
    pkgName: 'com.example.hydrationReminder',
    abilityName: 'HydrationReminderAbility'
  },
  ringDuration: 60,
  snoozeTimes: 2,
  triggerTime: reminderTime.getTime(),
  repeatInterval: 24  60  60 * 1000, // 每天重复
  title: '饮水提醒',
  content: 该喝水了!建议饮水量: ${amount}ml,
  expiredContent: "饮水提醒已过期"
};
await reminderAgent.publishReminder(reminderRequest);
public async cancelAllReminders(): Promise<void> {
const reminders = await reminderAgent.getValidReminders();
await Promise.all(reminders.map(rem => 
  reminderAgent.cancelReminder(rem.id)
));
}
export const hydrationPlanService = HydrationPlanService.getInstance();
环境因素分析
// EnvironmentAnalysisService.ets
import geolocation from ‘@ohos.geolocation’;
import sensor from ‘@ohos.sensor’;
class EnvironmentAnalysisService {
private static instance: EnvironmentAnalysisService;
private geoLocationManager: geolocation.GeoLocationManager;
private temperatureSensor: sensor.Sensor | null = null;
private constructor() {
this.geoLocationManager = geolocation.createGeoLocationManager();
public static getInstance(): EnvironmentAnalysisService {
if (!EnvironmentAnalysisService.instance) {
  EnvironmentAnalysisService.instance = new EnvironmentAnalysisService();
return EnvironmentAnalysisService.instance;
public async startMonitoring(): Promise<void> {
// 获取当前位置
const location = await this.geoLocationManager.getCurrentLocation();
// 获取天气数据
const weather = await this.getWeatherData(location.latitude, location.longitude);
// 启动温度传感器
this.temperatureSensor = await sensor.getSensor(sensor.SensorType.SENSOR_TYPE_AMBIENT_TEMPERATURE);
this.temperatureSensor.on('change', (data) => {
  this.handleTemperatureChange(data);
});
EventBus.emit('environmentDataUpdated', {
  location,
  weather,
  indoorTemperature: null
});
private async getWeatherData(lat: number, lon: number): Promise<WeatherData> {
const httpClient = http.createHttp();
return new Promise((resolve, reject) => {
  httpClient.request(
    https://weather-api.example.com/current?lat={lat}&lon={lon},
method: ‘GET’ },
    (err, data) => {
      if (err) {
        reject(err);
else {
        resolve(JSON.parse(data.result));
}
  );
});
private handleTemperatureChange(data: sensor.SensorData): void {
const temperature = data.value;
let environmentType: 'hot' 'normal'
‘cold’ = ‘normal’;
if (temperature > 28) {
  environmentType = 'hot';
else if (temperature < 15) {
  environmentType = 'cold';
EventBus.emit(‘temperatureUpdated’, {
  temperature,
  environmentType
});
public adjustHydrationPlan(environment: EnvironmentData, currentPlan: HydrationPlan): HydrationPlan {
let adjustmentFactor = 1.0;
// 根据环境温度调整
if (environment.temperature > 30) {
  adjustmentFactor *= 1.3;
else if (environment.temperature < 10) {
  adjustmentFactor *= 0.9;
// 根据湿度调整
if (environment.humidity < 40) {
  adjustmentFactor *= 1.2;
else if (environment.humidity > 70) {
  adjustmentFactor *= 0.9;
// 根据活动量调整
if (environment.activityLevel === 'high') {
  adjustmentFactor *= 1.2;
return {
  ...currentPlan,
  dailyGoal: Math.round(currentPlan.dailyGoal * adjustmentFactor),
  intervals: currentPlan.intervals.map(i => ({
    ...i,
    amount: Math.round(i.amount * adjustmentFactor)
  }))
};
}
export const environmentService = EnvironmentAnalysisService.getInstance();
五、总结
本智能饮水提醒应用实现了以下核心价值:
精准检测:通过面部特征分析准确判断脱水状态
个性化计划:根据用户特征和环境因素定制饮水计划
智能提醒:在最佳时间提醒用户补充水分
多设备协同:跨设备同步健康数据和提醒
健康追踪:长期记录和分析用户饮水习惯
扩展方向:
集成智能水杯数据
增加水分摄入来源分析(食物、饮料等)
开发家庭共享模式
增加健康知识推送
注意事项:
需要申请ohos.permission.CAMERA权限
面部检测准确率受光线和角度影响
脱水分析结果仅供参考,不能替代医学诊断
多设备协同需保持网络连接
环境数据需要位置权限和网络连接




















