Files
life-echo/app-android/README.md
penghanyuan 0030ea4a42 refactor: 更新应用名称与对话提示以增强用户体验
- 将应用名称从“岁月时书”更改为“岁月留书”,并在多个文件中更新相关文本。
- 在对话提示中将“回忆录助手”替换为“岁月知己”,以统一用户体验。
- 添加新的头像资源以匹配更新后的助手名称。
- 更新多个界面和文档中的文本,以反映新的品牌形象和功能。
2026-02-13 23:04:24 +01:00

441 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 岁月留书 Android 应用
> Life Echo Android 客户端 - 基于 Jetpack Compose 的现代化 Android 应用
## 📱 项目简介
**岁月留书 Android 应用**是 Life Echo 平台的移动端客户端,提供流畅的语音对话体验和回忆录管理功能。应用采用现代化的 Android 开发技术栈,实现优雅的用户界面和流畅的交互体验。
### 核心功能
- 🎙️ **实时语音对话** - 通过 WebSocket 实现实时语音交互
- 💬 **智能对话引导** - AI Agent 引导用户进行回忆录访谈
- 📚 **回忆录管理** - 查看和管理生成的回忆录章节
- 📄 **PDF 导出** - 导出回忆录为 PDF 文档
- 👤 **用户中心** - 账户管理、套餐升级、订单查询
- 💾 **离线存储** - 使用 Room 数据库实现本地数据存储
- 🌙 **深色模式** - 支持深色主题和浅色主题切换
## 🛠️ 技术栈
| 技术 | 版本/说明 | 用途 |
|------|-----------|------|
| **Kotlin** | 1.9+ | 编程语言 |
| **Jetpack Compose** | Latest | 声明式 UI 框架 |
| **Ktor** | Latest | HTTP 客户端和 WebSocket |
| **Room** | Latest | 本地数据库SQLite |
| **Coroutines + Flow** | Latest | 异步编程和响应式数据流 |
| **DataStore Preferences** | 1.0.0 | 键值对存储Token 管理) |
| **Coil** | Latest | 图片加载库 |
| **Navigation Compose** | Latest | 导航管理 |
| **ViewModel** | Latest | MVVM 架构支持 |
| **Material 3** | Latest | Material Design 3 组件 |
## 📁 项目结构
```
app-android/
├── app/
│ ├── build.gradle.kts # 应用级构建配置
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/com/huaga/life_echo/
│ │ ├── MainActivity.kt # 主 Activity
│ │ │
│ │ ├── config/
│ │ │ └── AppConfig.kt # 应用配置API 地址等)
│ │ │
│ │ ├── data/ # 数据层
│ │ │ ├── auth/
│ │ │ │ └── TokenManager.kt # Token 管理
│ │ │ ├── database/ # Room 数据库
│ │ │ │ ├── AppDatabase.kt
│ │ │ │ ├── Book.kt
│ │ │ │ ├── Chapter.kt
│ │ │ │ ├── Conversation.kt
│ │ │ │ └── ...
│ │ │ ├── preferences/
│ │ │ │ └── TokenPreferences.kt
│ │ │ └── repository/ # Repository 模式
│ │ │ ├── ChapterRepository.kt
│ │ │ ├── ConversationRepository.kt
│ │ │ └── ...
│ │ │
│ │ ├── network/ # 网络层
│ │ │ ├── ApiService.kt # REST API 服务
│ │ │ ├── AuthService.kt # 认证服务
│ │ │ ├── WebSocketClient.kt # WebSocket 客户端
│ │ │ ├── interceptors/
│ │ │ │ └── AuthInterceptor.kt
│ │ │ └── models/ # 数据模型
│ │ │ ├── AuthModels.kt
│ │ │ ├── ConversationModels.kt
│ │ │ └── ...
│ │ │
│ │ ├── ui/ # UI 层
│ │ │ ├── screens/ # 屏幕组件
│ │ │ │ ├── LoginScreen.kt
│ │ │ │ ├── RegisterScreen.kt
│ │ │ │ ├── CreateMemoryScreen.kt
│ │ │ │ ├── MyMemoirScreen.kt
│ │ │ │ ├── ProfileScreen.kt
│ │ │ │ └── ...
│ │ │ ├── components/ # 可复用组件
│ │ │ │ ├── chat/ # 聊天相关组件
│ │ │ │ ├── memoir/ # 回忆录相关组件
│ │ │ │ ├── payment/ # 支付相关组件
│ │ │ │ └── common/ # 通用组件
│ │ │ ├── theme/ # 主题配置
│ │ │ │ ├── Color.kt
│ │ │ │ ├── Theme.kt
│ │ │ │ └── Type.kt
│ │ │ └── viewmodel/ # ViewModel
│ │ │ ├── AuthViewModel.kt
│ │ │ ├── CreateMemoryViewModel.kt
│ │ │ └── ...
│ │ │
│ │ ├── navigation/ # 导航管理
│ │ │ ├── AppNavigation.kt
│ │ │ └── NavigationTransitions.kt
│ │ │
│ │ ├── feature/ # 功能模块
│ │ │ └── voice/
│ │ │ └── VoiceRecorder.kt # 语音录制
│ │ │
│ │ └── utils/ # 工具类
│ │ ├── AnimationUtils.kt
│ │ ├── PaymentUtils.kt
│ │ └── ...
│ │
│ └── res/ # 资源文件
│ ├── values/
│ │ ├── strings.xml # 字符串资源
│ │ ├── colors.xml # 颜色资源
│ │ └── themes.xml # 主题资源
│ └── xml/
│ └── network_security_config.xml
├── build.gradle.kts # 项目级构建配置
├── settings.gradle.kts # 项目设置
├── gradle.properties # Gradle 属性
└── README.md # 本文档
```
## 🚀 快速开始
### 前置要求
- **Android Studio** Hedgehog | 2023.1.1 或更高版本
- **JDK** 11 或更高版本
- **Android SDK** API 24 (Android 7.0) 或更高版本
- **Gradle** 8.0+(项目已包含 Gradle Wrapper
### 环境配置
1. **克隆项目**
```bash
git clone <repository-url>
cd life-echo/app-android
```
2. **使用 Android Studio 打开项目**
- 打开 Android Studio
- 选择 `File -> Open`
- 选择 `app-android` 目录
- 等待 Gradle 同步完成
3. **配置 API 地址**
编辑 `app/src/main/java/com/huaga/life_echo/config/AppConfig.kt`
```kotlin
object AppConfig {
// 开发环境配置
// 物理机测试使用实际的内网IP地址如 192.168.10.9
const val BASE_URL = "http://192.168.10.9:8000"
const val WS_BASE_URL = "ws://192.168.10.9:8000"
// Android模拟器测试使用 10.0.2.2 来访问主机
// const val BASE_URL = "http://10.0.2.2:8000"
// const val WS_BASE_URL = "ws://10.0.2.2:8000"
// 生产环境配置:公网地址
// const val BASE_URL = "https://api.lifeecho.com"
// const val WS_BASE_URL = "wss://api.lifeecho.com"
}
```
**注意事项**
- 从 Android 9 (API 28) 开始,默认禁止明文 HTTP 流量
- 开发环境已在 `network_security_config.xml` 中配置允许明文流量
- 生产环境应使用 HTTPS 并移除明文流量配置
4. **确保后端服务运行**
确保后端 API 服务已启动并可以访问(参考 [api/README.md](../api/README.md)
5. **运行应用**
- 连接 Android 设备或启动模拟器
- 点击 `Run` 按钮(或使用快捷键 `Shift+F10`
- 选择目标设备
- 等待应用安装和启动
## 📱 应用功能
### 认证功能
- **用户注册** - 手机号注册,支持昵称和邮箱
- **用户登录** - 手机号 + 密码登录
- **Token 管理** - 自动管理访问令牌和刷新令牌
- **自动登录** - 支持记住登录状态
### 对话功能
- **实时语音对话** - WebSocket 实时双向通信
- **语音录制** - 支持实时音频录制和发送
- **语音播放** - TTS 音频自动播放
- **对话历史** - 查看历史对话记录
- **对话管理** - 创建、查看、结束对话
### 回忆录功能
- **章节列表** - 查看所有回忆录章节
- **章节阅读** - 优雅的章节阅读界面
- **全文阅读** - 查看完整回忆录内容
- **PDF 导出** - 导出回忆录为 PDF 文档
- **章节整理** - 将对话内容整理为章节
### 用户中心
- **账户信息** - 查看和编辑用户信息
- **套餐管理** - 查看当前套餐,升级套餐
- **订单查询** - 查看历史订单
- **数据导出** - 导出所有用户数据
- **设置** - 语言、主题、通知等设置
- **常见问题** - FAQ 列表
- **反馈** - 提交反馈和联系客服
## 🏗️ 架构设计
### MVVM 架构
应用采用 **MVVMModel-View-ViewModel** 架构模式:
```
┌─────────────┐
│ View │ (Compose UI)
│ (Screen) │
└──────┬──────┘
│ observe
┌─────────────┐
│ ViewModel │ (状态管理、业务逻辑)
└──────┬──────┘
│ use
┌─────────────┐
│ Repository │ (数据访问抽象)
└──────┬──────┘
├─────────┐
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ Room │ │ Network │
│ Database │ │ API │
└──────────┘ └──────────┘
```
### 数据流
1. **UI 层Compose**:使用 `@Composable` 函数构建界面
2. **ViewModel**:管理 UI 状态,处理用户交互
3. **Repository**:统一数据访问接口,协调本地数据库和网络 API
4. **数据源**
- **Room Database**:本地 SQLite 数据库(离线数据)
- **Network API**REST API 和 WebSocket服务器数据
### 关键组件
#### TokenManager
管理用户认证令牌:
```kotlin
// 保存 Token
TokenManager.saveTokens(accessToken, refreshToken)
// 获取 Token
val accessToken = TokenManager.getAccessToken()
// 检查登录状态
val isLoggedIn = TokenManager.isLoggedIn
```
#### WebSocketClient
WebSocket 连接管理:
```kotlin
// 连接 WebSocket
webSocketClient.connect(conversationId, accessToken)
// 发送消息
webSocketClient.sendAudio(audioData)
// 接收消息
webSocketClient.onMessage { message ->
// 处理消息
}
```
#### Repository 模式
统一数据访问:
```kotlin
class ConversationRepository(
private val apiService: ApiService,
private val conversationDao: ConversationDao
) {
suspend fun getConversations(): Flow<List<Conversation>> {
// 先从本地数据库获取
// 然后从网络获取并更新本地数据库
}
}
```
## 🔧 开发指南
### 添加新的屏幕
1. 在 `ui/screens/` 目录创建新的 Screen Composable
2. 在 `navigation/AppNavigation.kt` 中添加路由
3. 创建对应的 ViewModel如需要
4. 在导航图中注册新屏幕
### 添加新的 API 接口
1. 在 `network/ApiService.kt` 中添加接口定义
2. 在 `network/models/` 中添加对应的数据模型
3. 在相应的 Repository 中调用新接口
### 添加新的数据库表
1. 在 `data/database/` 中创建 Entity 类
2. 创建对应的 DAO 接口
3. 在 `AppDatabase.kt` 中注册 Entity 和 DAO
4. 更新数据库版本号
### 添加新的 UI 组件
1. 在 `ui/components/` 目录创建组件
2. 使用 `@Composable` 注解
3. 遵循 Material Design 3 设计规范
## 🧪 测试
### 单元测试
```bash
./gradlew test
```
### 集成测试
```bash
./gradlew connectedAndroidTest
```
## 📦 构建发布
### Debug 构建
```bash
./gradlew assembleDebug
```
### Release 构建
1. 配置签名密钥(在 `app/build.gradle.kts` 中)
2. 构建 Release APK
```bash
./gradlew assembleRelease
```
3. 构建 Release AABGoogle Play
```bash
./gradlew bundleRelease
```
## 🔒 安全注意事项
1. **网络配置**
- 开发环境允许明文 HTTP仅用于开发
- 生产环境必须使用 HTTPS
- 配置 `network_security_config.xml` 限制允许的域名
2. **Token 存储**
- Token 存储在 DataStore Preferences 中
- 不要将 Token 存储在 SharedPreferences 或日志中
3. **API Key**
- 不要在代码中硬编码 API Key
- 使用 BuildConfig 或环境变量
4. **ProGuard/R8**
- 启用代码混淆Release 构建)
- 配置 ProGuard 规则保护敏感代码
## 🐛 常见问题
### WebSocket 连接失败
**问题**:无法连接到 WebSocket 服务器
**解决方案**
1. 检查 `AppConfig.kt` 中的 `WS_BASE_URL` 是否正确
2. 确认后端服务正在运行
3. 检查网络权限(`INTERNET`)是否已添加
4. 如果是模拟器,使用 `10.0.2.2` 代替 `localhost`
### 音频录制失败
**问题**:无法录制音频
**解决方案**
1. 检查 `RECORD_AUDIO` 权限是否已申请
2. 确认设备支持音频录制
3. 检查音频格式配置
### 数据库迁移失败
**问题**:应用更新后数据库迁移失败
**解决方案**
1. 检查数据库版本号是否正确递增
2. 确认 Migration 类已正确实现
3. 测试数据库迁移逻辑
## 📚 相关文档
- [项目根目录 README](../README.md) - 项目总览
- [API 文档](../api/README.md) - 后端 API 文档
- [WebSocket 测试文档](../api/docs/WebSocket快速测试指南.md) - WebSocket 测试指南
## 📄 许可证
MIT License
---
**岁月留书 Android** - 让每一段人生故事都被温柔记录 📱✨