Android 原生植物养护 App,基于 Jetpack Compose + Material 3。当前版本 v2.1.0。
通过通义千问多模态 API 实现植物识别、病害诊断、健康评估等 AI 功能,结合和风天气 API 实现天气感知的智能养护决策。
┌─────────────────────────────────────────────────┐
│ UI Layer │
│ Jetpack Compose + Material 3 + Navigation │
│ (10 Screen Modules, 21 Reusable Components) │
├─────────────────────────────────────────────────┤
│ Domain Layer │
│ PlantPhotoAnalyzer · CareDecisionEngine │
│ WateringPeriodSuggester · PlantProfileMatcher │
│ HealthCalculator · CareStatsAggregator │
├─────────────────────────────────────────────────┤
│ Data Layer │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ SQLite │ │ Retrofit │ │ DataStore │ │
│ │ (9 Tables│ │ (DashScope│ │ (Preferences) │ │
│ │ 11 DAOs)│ │ QWeather)│ │ │ │
│ └──────────┘ └──────────┘ └───────────────┘ │
├─────────────────────────────────────────────────┤
│ Background Tasks │
│ WorkManager: DailyCare / PlantReminder / │
│ ExtremeWeather Workers │
│ Glance AppWidget · Notification Channels │
└─────────────────────────────────────────────────┘
app/src/main/java/com/example/plantnet/
├── PlantNetApp.kt # Application 类,手动 DI 容器
├── MainActivity.kt # 入口 Activity
├── data/
│ ├── db/ # 11 DAO + PlantDatabaseHelper
│ ├── model/ # 17 数据模型
│ ├── network/ # Retrofit 接口定义
│ └── repository/ # 13 Repository
├── domain/ # 13 领域逻辑类
├── notification/ # 11 通知/Worker 类
├── ui/
│ ├── component/ # 21 可复用 UI 组件
│ ├── navigation/ # 路由定义
│ ├── screen/ # 10 功能模块
│ └── theme/ # 主题/设计系统
├── util/ # 工具类
└── widget/ # 桌面小组件
| 层面 | 技术 |
|---|---|
| 语言 | Kotlin |
| UI | Jetpack Compose + Material 3 |
| 导航 | Navigation Compose 2.8.5 |
| 数据库 | SQLite(SQLiteOpenHelper),9 表 11 DAO |
| 偏好 | DataStore Preferences 1.1.1 |
| 网络 | Retrofit 2.11.0 + OkHttp 4.12.0 + Gson |
| 图片 | Coil Compose 2.7.0 |
| 后台 | WorkManager 2.9.1 |
| 小组件 | Glance AppWidget 1.1.1 |
| AI | 通义千问 DashScope(qwen3-omni-flash) |
| 天气 | 和风天气 QWeather API |
| DI | 手动依赖注入(PlantNetApp 单例) |
- JSON-Only 输出约束:所有 prompt 均要求"仅返回 JSON,不要其他文字",确保客户端可稳定解析
- 天气环境注入:浇水周期 prompt 动态拼接用户所在地天气数据,使 AI 输出个性化结果
- 知识库修正:AI 返回结果经本地
WateringPeriodSuggester修正,融合内置植物知识库的基准值 - 上下文增强:养护问答注入用户全部植物档案作为 system prompt 上下文
请识别照片中的植物并评估其当前健康状态,仅返回 JSON,不要其他文字:
{
"name":"植物中文名",
"species":"科属或品种",
"healthScore":85,
"healthAssessment":"30字内:叶片颜色、是否有黄叶/病斑/缺水迹象",
"wateringDays":5,
"wateringReason":"20字内:结合盆土干湿、盆器大小、当地天气给出周期理由",
"lightRequirement":"全日照/半阴/散射光/耐阴 之一",
"description":"50字以内简介",
"careTips":"浇水光照建议",
"confidence":"高/中/低"
}
healthScore 为 0-100 整数;wateringDays 为 1-30 的个性化浇水间隔天数,
必须结合天气独立计算,不要照抄示例数字。
识别时动态拼接天气环境块(城市、气温、湿度、降水概率),引导 AI 结合天气给出个性化浇水周期。
请评估照片中植物的健康状态,仅返回 JSON,不要其他文字:
{"healthScore":85,"healthAssessment":"30字内:叶片颜色、是否有黄叶/病斑/缺水迹象"}
healthScore 为 0-100 整数。
请对比两张同一植物在不同时间的照片(第一张为较早,第二张为较晚),评估生长变化。
仅返回 JSON,不要其他文字:
{
"summary":"50字内总体变化",
"growthTrend":"变好/持平/变差",
"changes":["叶色更绿","新芽2处"],
"healthDelta":5,
"suggestions":"30字内建议"
}
healthDelta 为 -100 到 100 的整数,表示健康度变化估计。
请根据照片中植物状态、盆土干湿、盆器大小,并结合用户所在地天气与环境,
评估个性化浇水周期,仅返回 JSON,不要其他文字:
{"wateringDays":5,"wateringReason":"20字内理由,需提及天气或环境因素影响",
"lightRequirement":"全日照/半阴/散射光/耐阴 之一"}
wateringDays 为 1-30 的整数;必须结合天气独立计算,不要照抄示例数字。
请作为植物病理专家分析照片中植物的健康状况,仅返回 JSON:
{"summary":"总体判断50字内","possibleIssues":"可能的问题",
"suggestions":"处理建议","severity":"轻/中/重"}
若看不出植物或无法判断,在 summary 中说明。
你是专业的植物养护助手。根据用户植物档案回答问题,给出简洁实用的建议
用户植物档案
{动态注入用户所有植物的名称、种类、健康评分、浇水周期}
回答控制200字以内,使用中文
- AI 作为结构化数据源:不把 AI 当聊天机器人,而是当作"多模态 JSON 生成器",prompt 精确约束输出格式
- 本地修正 > 纯 AI 依赖:AI 返回的浇水周期经
WateringPeriodSuggester修正,融合知识库基准值,避免 AI 幻觉导致极端值 - 天气感知闭环:天气 API → 环境上下文注入 prompt → AI 个性化输出 →
CareDecisionEngine天气感知决策 → 通知推送,形成完整闭环 - 图片压缩前置:AI 调用前将图片压缩至 768px 宽度并转 base64,控制 token 消耗
- 协议:OpenAI 兼容模式(DashScope
compatible-mode/v1/chat/completions) - 模型:
qwen3-omni-flash - 调用模式:非流式(同步等待完整响应)
- 认证:
Authorization: Bearer ${DASHSCOPE_API_KEY} - 超时:连接 30s / 读写 60s
// 多模态请求(图片 + 文本)
ChatRequest(
model = "qwen3-omni-flash",
messages = listOf(
Message(role = "user", content = listOf(
ContentPart(type = "image_url",
image_url = ImageUrl(url = "data:image/jpeg;base64,{base64}")),
ContentPart(type = "text", text = "prompt")
))
)
)
// 文本问答请求(system + user)
ChatRequest(
model = "qwen3-omni-flash",
messages = listOf(
Message(role = "system", content = listOf(
ContentPart(type = "text", text = systemPrompt))),
Message(role = "user", content = listOf(
ContentPart(type = "text", text = question)))
)
)AI Response (JSON string)
│
▼
extractJson() ── 从回复文本中提取 {...} 子串
│
▼
Gson JsonObject ── 按字段名手动解析
│
▼
结构化数据模型 ── IdentifyResult / PlantHealthAnalysis / GrowthCompareResult
│
▼
本地修正 ── WateringPeriodSuggester.refine() / PlantProfileMatcher
│
▼
持久化 ── 写入 SQLite / 更新 UI 状态
| 功能 | 入口 | 调用链 |
|---|---|---|
| 植物识别 | 识别 Tab / FAB | IdentifyViewModel → PlantPhotoAnalyzer.identifyPlant() → AiRepository.analyzeImage() → DashScope API → parseIdentifyResult() → enrichIdentifyResult() |
| 病害诊断 | 识别 Tab | IdentifyViewModel → AiRepository.analyzeImage() → DashScope API |
| 健康评估 | 生长记录拍照 | PlantPhotoAnalyzer.analyzeHealth() → AiRepository.analyzeImage() → DashScope API |
| 生长对比 | 双图对比页 | PlantPhotoAnalyzer.compareGrowth() → AiRepository.analyzeImages() → DashScope API |
| 浇水周期 | AI 识别添加 | PlantPhotoAnalyzer.calculateWatering() → AiRepository.analyzeImage() → WateringPeriodSuggester.refine() |
| 养护问答 | 我的 → 养护问答 | CareAskViewModel → AiRepository.askCareQuestion() → DashScope API |
- 图片压缩至 768px 宽度后再 base64 编码,减少图片 token 消耗
- 使用
qwen3-omni-flash而非更大模型,平衡效果与成本 - 养护问答限制 200 字回复,prompt 中明确约束输出长度
- 非流式调用,单次请求完整返回,避免长连接开销
- Android Studio(推荐最新稳定版,需支持 AGP 9)
- JDK 11+
- Android SDK(minSdk 24,targetSdk 36)
- 克隆项目
git clone https://github.com/你的用户名/Plantnet.git
cd Plantnet- 配置 API Key
cp local.properties.example local.properties编辑 local.properties:
sdk.dir=你的Android SDK路径
DASHSCOPE_API_KEY=你的通义千问Key
QWEATHER_API_KEY=你的和风天气Key
QWEATHER_API_HOST=你的专属域名.re.qweatherapi.com- 构建运行
./gradlew assembleDebug或直接在 Android Studio 中 Sync Gradle → Run。
| API | 获取地址 | 用途 |
|---|---|---|
| 通义千问 DashScope | https://dashscope.console.aliyun.com/ | 植物识别、病害诊断、养护问答 |
| 和风天气 QWeather | https://dev.qweather.com/ | 实时天气、天气预报、极端天气预警 |
Key 通过
local.properties注入到BuildConfig,不会提交到 Git。
和风天气 API 支持 HTTPS,需在控制台绑定专属域名:
- 登录和风天气开发控制台 → 项目管理 → 创建项目
- 绑定专属域名(格式:
xxx.re.qweatherapi.com),该域名自动配置 SSL 证书 - 将域名填入
QWEATHER_API_HOST,App 内所有请求自动走 HTTPS
# 生成签名 APK
./gradlew assembleRelease
# 输出路径
# app/build/outputs/apk/release/app-release.apk签名配置在 app/build.gradle 的 signingConfigs 中设置。
- 首页控制台:今日浇水、养护简报、统计卡片、和风天气;下拉刷新
- 植物档案:添加/编辑/删除、分组、浇水/施肥/换盆/换土打卡、养护画像、AI 健康评估
- 养护日历:浇水/施肥/换盆/换土日程,完成/忽略/推迟
- 识别 Tab:植物识别与病害诊断同一 Tab 切换;识别结果预填添加表单
- 生长记录:时间线拍照、AI 健康评分、双图生长对比
- 养护问答:单轮 AI 问答,结合本地植物档案上下文
- 知识库:常见植物养护指南,标签筛选
- 全局统计:全库汇总与近 30 天养护柱状图
- 桌面小组件:今日待浇水株数,点击跳转首页
- 分享卡片:植物详情页生成分享图
- 数据备份:ZIP v2 导出/导入(兼容旧版 JSON)
| 类型 | 时机 | 开关 |
|---|---|---|
| 每日养护简报 | 每天 7:00 合并推送 | 每日 7:00 养护简报 |
| 单株浇水提醒 | 浇水周期到期时独立推送 | 单株浇水提醒 |
| 极端天气预警 | 暴雨/高温等触发时即时推送 | 极端天气预警 |
| 日历待办摘要 | 当日有施肥/换盆/换土待办 | 随每日简报通道 |
| 文档 | 说明 |
|---|---|
| CHANGELOG.md | 版本变更 |
| docs/plantnet-development-plan.md | 完善方案与历史 Phase 进度 |
| docs/superpowers/specs/2026-06-09-weather-care-design.md | 天气感知养护设计 |
| docs/superpowers/specs/2026-06-05-plant-care-app-design.md | 初版设计(历史归档) |