新增 docs/android/ 目录: - README.md 总入口(快速上手 + 决策摘要 + 数据流) - 01-architecture.md 模块划分 + 数据流 + 选型理由 - 02-api-contract.md 每个接口的请求/响应 + DTO 字段映射 - 03-build-run.md Gradle/SDK/网络安全白名单/真机调试 - 04-milestones.md 7 天里程碑 + DoD + E2E 测试场景 新增 assets/: - logo/: 主图标 master + adaptive icon + 5 DPI launcher (方/圆) - splash/: 启动屏 logo + 完整背景预览 + 5 DPI 资源 - android_resources/: 集成所需的 XML(adaptive icon/主题/颜色/字符串/drawable/layout) - INTEGRATION.md 集成指南 - logo.svg + _make_logo.py 设计源 设计风格:参考用户提供的木质方块字母积木图,米色木纹底 + 深棕色字母 D,代表 'Diary',温暖私人日记感。 服务器体检:所有容器/API/DB/翻译主链路正常,TMT 本月已用 0.37%。 MaaS 备用通道上次已验证可用。
230 lines
8.1 KiB
Markdown
230 lines
8.1 KiB
Markdown
# Logo + 启动屏集成指南
|
|
|
|
> 把 `assets/` 下所有产物拷到你的 Android Studio 工程目录里。
|
|
>
|
|
> 主要文件清单 + 拷贝目标位置。
|
|
|
|
---
|
|
|
|
## 1. 文件清单
|
|
|
|
### 1.1 应用图标
|
|
|
|
| 源文件 | 目标位置(Android Studio 项目)|
|
|
|---|---|
|
|
| `assets/logo/ic_launcher_foreground.png` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher_foreground.png`(覆盖)|
|
|
| `assets/logo/ic_launcher_background.png` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher_background.png`(覆盖)|
|
|
| `assets/logo/mipmap-mdpi/ic_launcher.png` | `app/src/main/res/mipmap-mdpi/ic_launcher.png`(覆盖)|
|
|
| `assets/logo/mipmap-mdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-mdpi/ic_launcher_round.png`(覆盖)|
|
|
| `assets/logo/mipmap-hdpi/ic_launcher.png` | `app/src/main/res/mipmap-hdpi/ic_launcher.png`(覆盖)|
|
|
| `assets/logo/mipmap-hdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-hdpi/ic_launcher_round.png`(覆盖)|
|
|
| `assets/logo/mipmap-xhdpi/ic_launcher.png` | `app/src/main/res/mipmap-xhdpi/ic_launcher.png`(覆盖)|
|
|
| `assets/logo/mipmap-xhdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-xhdpi/ic_launcher_round.png`(覆盖)|
|
|
| `assets/logo/mipmap-xxhdpi/ic_launcher.png` | `app/src/main/res/mipmap-xxhdpi/ic_launcher.png`(覆盖)|
|
|
| `assets/logo/mipmap-xxhdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png`(覆盖)|
|
|
| `assets/logo/mipmap-xxxhdpi/ic_launcher.png` | `app/src/main/res/mipmap-xxxhdpi/ic_launcher.png`(覆盖)|
|
|
| `assets/logo/mipmap-xxxhdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png`(覆盖)|
|
|
|
|
### 1.2 Adaptive icon XML
|
|
|
|
把 `assets/android_resources/mipmap-anydpi-v26/` 下的两个 XML 也拷到对应目录:
|
|
|
|
| 源文件 | 目标 |
|
|
|---|---|
|
|
| `ic_launcher.xml` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml` |
|
|
| `ic_launcher_round.xml` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml` |
|
|
|
|
> Android 8.0+ 会优先用 `<adaptive-icon>` XML。如果项目里已经有同名 XML,**整体覆盖**即可。
|
|
|
|
### 1.3 启动屏资源
|
|
|
|
| 源文件 | 目标 |
|
|
|---|---|
|
|
| `splash/drawable-mdpi/ic_splash_logo.png` | `app/src/main/res/drawable-mdpi/ic_splash_logo.png` |
|
|
| `splash/drawable-hdpi/ic_splash_logo.png` | `app/src/main/res/drawable-hdpi/ic_splash_logo.png` |
|
|
| `splash/drawable-xhdpi/ic_splash_logo.png` | `app/src/main/res/drawable-xhdpi/ic_splash_logo.png` |
|
|
| `splash/drawable-xxhdpi/ic_splash_logo.png` | `app/src/main/res/drawable-xxhdpi/ic_splash_logo.png` |
|
|
| `splash/drawable-xxxhdpi/ic_splash_logo.png` | `app/src/main/res/drawable-xxxhdpi/ic_splash_logo.png` |
|
|
|
|
### 1.4 XML 主题 / 颜色 / 字符串
|
|
|
|
| 源文件 | 目标 |
|
|
|---|---|
|
|
| `android_resources/values/colors_splash.xml` | `app/src/main/res/values/colors_splash.xml` |
|
|
| `android_resources/values/strings_splash.xml` | `app/src/main/res/values/strings_splash.xml` |
|
|
| `android_resources/values/themes_splash.xml` | `app/src/main/res/values/themes_splash.xml` |
|
|
| `android_resources/values/dimens_splash.xml` | `app/src/main/res/values/dimens_splash.xml` |
|
|
| `android_resources/drawable/splash_screen.xml` | `app/src/main/res/drawable/splash_screen.xml` |
|
|
| `android_resources/layout/activity_splash.xml` | `app/src/main/res/layout/activity_splash.xml` |
|
|
|
|
---
|
|
|
|
## 2. 集成步骤
|
|
|
|
### 2.1 加 SplashScreen 依赖
|
|
|
|
`gradle/libs.versions.toml`:
|
|
|
|
```toml
|
|
[versions]
|
|
core-splashscreen = "1.0.1"
|
|
|
|
[libraries]
|
|
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "core-splashscreen" }
|
|
```
|
|
|
|
`app/build.gradle.kts`:
|
|
|
|
```kotlin
|
|
dependencies {
|
|
// ...
|
|
implementation(libs.androidx.core.splashscreen)
|
|
}
|
|
```
|
|
|
|
### 2.2 `AndroidManifest.xml` 改启动主题
|
|
|
|
```xml
|
|
<application
|
|
android:name=".DiaryNewsApp"
|
|
android:theme="@style/Theme.App.Starting"
|
|
...>
|
|
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:theme="@style/Theme.App.Starting.Legacy" <!-- Android 11 及以下 -->
|
|
android:exported="true">
|
|
...
|
|
</activity>
|
|
</application>
|
|
```
|
|
|
|
或者用 v31 区分:
|
|
|
|
```xml
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:exported="true">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:exported="false"
|
|
android:theme="@style/Theme.App.Starting.Legacy" /> <!-- 用一个 launcher alias 兼容低版本 -->
|
|
```
|
|
|
|
**最简单做法**:在 `MainActivity` 里 **不** 用 `android:theme`,改在 `onCreate` 里用 SplashScreen API 处理。
|
|
|
|
### 2.3 `MainActivity.kt`(SplashScreen API 用法)
|
|
|
|
```kotlin
|
|
package com.diary.news
|
|
|
|
import android.os.Bundle
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.compose.setContent
|
|
import androidx.activity.enableEdgeToEdge
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
import androidx.compose.material3.Surface
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
|
import com.diary.news.ui.theme.DiaryNewsTheme
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
|
|
@AndroidEntryPoint
|
|
class MainActivity : ComponentActivity() {
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
// 1. 安装 SplashScreen(必须在 super.onCreate 之前)
|
|
val splashScreen = installSplashScreen()
|
|
// 可选:保持启动屏直到数据加载完成
|
|
// splashScreen.setKeepOnScreenCondition { !viewModel.isReady.value }
|
|
|
|
super.onCreate(savedInstanceState)
|
|
enableEdgeToEdge()
|
|
|
|
setContent {
|
|
DiaryNewsTheme {
|
|
Surface(modifier = Modifier.fillMaxSize()) {
|
|
AppNav()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2.4 应用名(`strings.xml`)
|
|
|
|
确保 `app/src/main/res/values/strings.xml` 有:
|
|
|
|
```xml
|
|
<resources>
|
|
<string name="app_name">Diary News</string>
|
|
</resources>
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 验证清单
|
|
|
|
装到真机后,逐项过:
|
|
|
|
- [ ] **桌面图标**:长按图标 → 看 launcher 上的视觉,是不是米色木质方块 D
|
|
- [ ] **不同 launcher 风格**:长按图标 → 改 "Edit" / "Themes",确认 adaptive icon 正常(Pixel Launcher / Nova / 系统自带都试一下)
|
|
- [ ] **启动屏**:点图标,启动时先看到木色启动屏 + Diary News 文字,然后进登录页 / Feed
|
|
- [ ] **启动屏过渡**:启动屏消失时是否平滑(无白闪 / 黑闪)
|
|
- [ ] **暗色模式**:系统切深色 → 启动屏颜色是否仍然温暖(用了固定木色,深色模式不变)
|
|
- [ ] **横竖屏切换**:旋转屏幕时启动屏不崩(虽然启动时不会切,但要看 activity 不因配置变更崩)
|
|
- [ ] **低版本兼容**:Android 7.0 / 8.0 真机测试启动屏是否正常显示
|
|
- [ ] **多 DPI**:在 Pixel 2 (xhdpi) / Pixel 7 Pro (xxxhdpi) 上看图标清晰度
|
|
|
|
---
|
|
|
|
## 4. 关于"以后用域名访问"
|
|
|
|
Android 这边改 IP 为域名,只需要两处:
|
|
|
|
1. `app/build.gradle.kts` 里 `buildConfigField` 的 `API_BASE_URL` 改成 `https://你的域名/api/v1/`
|
|
2. `app/src/main/res/xml/network_security_config.xml` 删掉 IP 白名单,改成默认 HTTPS 即可(或者保留 +加域名白名单)
|
|
|
|
代码不动,业务逻辑零变更。
|
|
|
|
---
|
|
|
|
## 5. 设计说明
|
|
|
|
### 颜色
|
|
|
|
| 角色 | HEX | 来源 |
|
|
|---|---|---|
|
|
| 木色底 | `#F5E9D0` | 参考图取色 |
|
|
| 中木色 | `#E8D4A8` | 渐变中间色 |
|
|
| 暗木色 | `#C9A876` | 阴影 / 渐变底部 |
|
|
| 字母深棕 | `#3E2A1E` | 字母主体 |
|
|
| 木纹线 | `#A8825A` | 半透明纹理 |
|
|
|
|
整套配色都是低饱和度暖色,**跟"私人日报 / 日记"的氛围匹配**,和 web 端 `#2080f0` 的蓝色主调形成"冷暖对比",反而有"早晚看新闻"的感觉。
|
|
|
|
### 字体
|
|
|
|
- 当前使用 Arial(Pillow 默认 fallback)
|
|
- 真机运行时,SplashScreen 的文字是 SVG/drawable 渲染的,字体以系统为准
|
|
- Compose 里的 `Text()` 可以用 `FontFamily.Serif`(衬线感更接近参考图)
|
|
|
|
### 安全区(Adaptive Icon)
|
|
|
|
- Android adaptive icon 要求 foreground 主体放中心 **66%**(108x108 中的 72x72 中心区)
|
|
- 我们的 `safe_zone=True` 参数自动留了 22% padding,符合规范
|
|
- **不要**给 foreground PNG 加背景色 —— 必须是透明 PNG
|
|
- **不要**让主体元素贴边
|
|
|
|
### 启动屏时长
|
|
|
|
- SplashScreen API 的默认时长 ≈ 200ms(很短,基本看不到)
|
|
- 我们做了 `setKeepOnScreenCondition` 注释,如果以后想"等数据加载完再消失",取消注释就行
|
|
- **不要**手动 sleep 假装启动屏,Google Play 政策明文禁止 |