# 岁月留书 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 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 架构 应用采用 **MVVM(Model-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> { // 先从本地数据库获取 // 然后从网络获取并更新本地数据库 } } ``` ## 🔧 开发指南 ### 添加新的屏幕 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 AAB(Google 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** - 让每一段人生故事都被温柔记录 📱✨