-
Notifications
You must be signed in to change notification settings - Fork 8
TechStack
一句话 TL;DR:这页列出 Sleepy 用的语言、框架、依赖版本和构建配置,并说明 CI 在做什么,给想本地编译或参与贡献的开发者看。
| 组件 | 选型 | 版本 |
|---|---|---|
| 语言 | Kotlin | 2.1.10(随插件版本) |
| 构建工具 | Gradle Wrapper | 9.3.1 |
| Android Gradle Plugin | AGP | 9.1.0 |
| UI 框架 | Jetpack Compose | 由 BOM 2024.10.00 统一管理 |
| 数据库 | Room | 2.7.0 |
| 注解处理 | KSP | 2.1.10-1.0.29 |
| 序列化 | kotlinx.serialization | JSON 1.6.3 |
| Widget 层 | RemoteViews + Canvas bitmap | — |
插件版本声明在根 build.gradle.kts:2-5;Gradle 发行版来自腾讯镜像,固定 9.3.1(gradle/wrapper/gradle-wrapper.properties:3)。
仓库没有版本目录(gradle/libs.versions.toml 不存在),所有依赖版本直接写在 app/build.gradle.kts 的 dependencies 块里。模块只有一个::app(settings.gradle.kts:31)。
仓库源配置有两条优先级:
- 插件仓库(
pluginManagement)先走阿里云镜像(google/public/gradle-plugin 三个),再落到官方 google/mavenCentral/gradlePluginPortal;google 仓库还用includeGroupByRegex限定只接受com.android.*、com.google.*、androidx.*三个组(settings.gradle.kts:3-12)。 - 依赖仓库(
dependencyResolutionManagement)设为PREFER_SETTINGS,同样阿里云镜像在前,末尾保留jitpack.io——注释写明 compose-markdown(com.github.jeziellago)只在 JitPack 发布,当前app/build.gradle.kts里没有引用这个库(settings.gradle.kts:18-27)。
工程名是 WakeUpPure(settings.gradle.kts:30),根 gradle.properties 只有一行 android.disallowKotlinSourceSets=false。
核心参数全部在 app/build.gradle.kts:9-22:
-
namespace与applicationId均为com.lingion.sleepy -
compileSdk = 37,minSdk = 26,targetSdk = 37 -
versionCode = 58,versionName = "1.0.54" vectorDrawables.useSupportLibrary = true- 语言资源过滤(
localeFilters)只打包 5 种:zh-rCN、zh-rTW、en、ja、es
Compose 侧:buildFeatures 开启 compose 与 buildConfig(app/build.gradle.kts:46-49);Java 与 Kotlin 统一 17(app/build.gradle.kts:41-44、79-81)。编译器 opt-in 了 5 个实验 API:kotlin.RequiresOptIn、ExperimentalMaterial3Api、ExperimentalFoundationApi、ExperimentalAnimationApi、ExperimentalCoroutinesApi(app/build.gradle.kts:82-88)。
其余配置:打包时排除 META-INF 下的许可证类资源(app/build.gradle.kts:51-60);单元测试开启 isIncludeAndroidResources 与 isReturnDefaultValues(app/build.gradle.kts:62-67)。
buildTypes 只有两个(app/build.gradle.kts:24-39):
| 变体 | 行为 |
|---|---|
| debug | 不做 minify,versionName 追加 -debug 后缀 |
| release |
isMinifyEnabled = true,套 proguard-android-optimize.txt + proguard-rules.pro,签名用 debug keystore(signingConfig = signingConfigs.getByName("debug")) |
release 的 R8 策略是「只裁剪不改名」:app/proguard-rules.pro:5 一行 -dontobfuscate 关掉混淆,避免 Room 生成类和 serialization 反射因改名崩溃。keep 规则覆盖 kotlinx.serialization companion/serializer(app/proguard-rules.pro:12-21)、Room entity/DAO(app/proguard-rules.pro:23-27)、WorkManager(app/proguard-rules.pro:29-31)、Manifest 反射实例化的 AppWidgetProvider 与 BroadcastReceiver 子类(app/proguard-rules.pro:33-37)、WakeUp 课表兼容 schema 的 com.wakeup.pure.**(app/proguard-rules.pro:39-40)。
ABI 拆分已启用:产出 arm64-v8a、armeabi-v7a、x86_64 三个 ABI 的独立 APK,isUniversalApk = false 表示不生成通用包(app/build.gradle.kts:69-76)。
Compose 系列由 BOM 统一管理版本(app/build.gradle.kts:93-95),以下为主要依赖及版本:
| 依赖 | 版本 | 证据 |
|---|---|---|
| androidx.compose:compose-bom | 2024.10.00 | app/build.gradle.kts:93 |
| androidx.core:core-ktx | 1.17.0 | app/build.gradle.kts:107 |
| androidx.activity:activity-compose | 1.9.3 | app/build.gradle.kts:108 |
| androidx.lifecycle:* (runtime-ktx / viewmodel-compose / process) | 2.8.7 | app/build.gradle.kts:109-111 |
| androidx.navigation:navigation-compose | 2.8.3 | app/build.gradle.kts:114 |
| androidx.datastore:datastore-preferences | 1.1.1 | app/build.gradle.kts:117 |
| androidx.room (runtime / ktx / compiler) | 2.7.0,经 KSP 接入 | app/build.gradle.kts:120-123 |
| kotlinx-coroutines (core / android) | 1.8.1 | app/build.gradle.kts:126-127 |
| kotlinx-serialization-json | 1.6.3 | app/build.gradle.kts:130 |
| org.jsoup:jsoup | 1.18.1 | app/build.gradle.kts:133 |
| androidx.work:work-runtime-ktx | 2.9.1 | app/build.gradle.kts:137 |
| androidx.core:core-splashscreen | 1.0.1 | app/build.gradle.kts:140 |
| io.coil-kt:coil-compose | 2.7.0 | app/build.gradle.kts:143 |
Compose 子件含 ui、ui-graphics、ui-tooling-preview、material3、material-icons-extended、animation、foundation(app/build.gradle.kts:97-104),版本全部跟随 BOM。
测试依赖:junit 4.13.2、junit-jupiter-params 5.10.2、org.json 20231013、sqlite-jdbc 3.53.4.0(用于直接执行 Room 迁移语句,仓库没有 Robolectric/Instrumentation 测试依赖)(app/build.gradle.kts:146-151);androidTest 有 androidx.test.ext:junit 1.2.1、espresso-core 3.6.1 和 BOM 管理的 ui-test-junit4(app/build.gradle.kts:152-156)。
Glance 不在依赖列表里。构建文件里的注释写明:「Glance 依赖已随死代码删除移除……5 个生产 widget 全走 RemoteViews + Canvas bitmap」(app/build.gradle.kts:135-137)。widget 相关实现都在 app/src/main/java/com/lingion/sleepy/widget/ 目录,入口类如 WeekListWidget.kt、WeekGridWidgetProvider.kt、TodayWidget.kt。想看 widget 细节,转到 桌面组件。
.github/workflows/ 下只有两个文件,做的是同一件事:把 GitHub 的仓库与 Release 镜像到 Gitee。没有任何 workflow 执行编译、测试或打包。
- 触发条件:push 到任意分支、任意 tag、release published/edited,外加手动
workflow_dispatch(.github/workflows/sync-to-gitee.yml:3-9) - 两个 job 串行:
sync-git用git clone --mirror拉全量再git push --mirror到 Gitee,推之前会清掉refs/pull引用,失败按 15 秒间隔重试 3 次(.github/workflows/sync-to-gitee.yml:16-32);sync-release只在 release 事件或手动触发时跑,超时上限 180 分钟(.github/workflows/sync-to-gitee.yml:34-38) -
sync-release是一段内嵌 Python:对照 GitHub Release 全量清单,在 Gitee 1 GB 附件配额内维护一个 980 MB 的滚动保留窗口——新版本优先占位,窗口外的旧版本只同步元数据不上传附件(.github/workflows/sync-to-gitee.yml:180-203);源码压缩包(-source.zip/-source.tar.gz)直接跳过,Gitee 页面会自动生成(.github/workflows/sync-to-gitee.yml:249-252);配额满了先淘汰最旧的非保护版本附件再重试一次(.github/workflows/sync-to-gitee.yml:138-177)
- 触发条件:手动
workflow_dispatch+ 定时 cron23 */2 * * *,即每 2 小时一次(.github/workflows/healer-gitee.yml:3-5) - 职责:对比 GitHub 与 Gitee 双方的 release 附件清单,补传缺失文件;新版本排在队首优先补;同样遵守 980 MB 预算,配额满时淘汰已完整同步的最旧版本(
.github/workflows/healer-gitee.yml:126-143、90-124) - 自带时间护栏:30 分钟后不再启动新的下载/上传,50 分钟强制收尾退出,给 55 分钟的步骤超时留余量(
.github/workflows/healer-gitee.yml:22-23)
另外 .github/ 下还有 ISSUE_TEMPLATE/(bug_report、feature_request、school_adaptation 三个表单)和 PULL_REQUEST_TEMPLATE.md,供提 issue/PR 时使用。
# 组装 debug APK(三个 ABI 各出一个,见 splits 配置)
./gradlew assembleDebug
# 组装 release APK(走 R8 shrinking,debug keystore 签名)
./gradlew assembleRelease
# 只要某个 ABI,AGP 会生成按变体+ABI 拆分的任务
./gradlew assembleArm64Release
# 单元测试(本仓库的测试主力)
./gradlew testDebugUnitTest
# 全部单元测试变体
./gradlew test
# 连接真机/模拟器跑 androidTest
./gradlew connectedDebugAndroidTest
# 静态检查
./gradlew lint产物在 app/build/outputs/apk/<variant>/<abi>/ 下。仓库启用了 buildConfig(app/build.gradle.kts:46-49),所以首次构建会生成 BuildConfig 类;单元测试开了 isReturnDefaultValues(app/build.gradle.kts:62-67),android.jar 的方法在 JVM 测试里返回默认值而非抛异常。
Sleepy Wiki
入门
界面与视图
课程管理
导入导出
小组件与提醒
数据与设置
项目
社区