CI / backend (push) Canceled after 0s
- 加 markwon ext-tables / ext-strikethrough:同一个 markdown 在 Web 里是表格, 在 app 里原来会把 | 管道符原样铺出来,现在按 Web 的纸面色画(1dp 浅线、表头浅底) - 「载入中…」原来挂在分类 chip 行末尾,chip 横向滚动时被挤出屏幕,等于没提示; 挪到「知识」标题右侧,任何滚动位置都看得见
118 lines
4.5 KiB
Kotlin
118 lines
4.5 KiB
Kotlin
import java.util.Properties
|
||
|
||
plugins {
|
||
id("com.android.application")
|
||
id("org.jetbrains.kotlin.android")
|
||
id("org.jetbrains.kotlin.plugin.compose")
|
||
id("org.jetbrains.kotlin.plugin.serialization")
|
||
}
|
||
|
||
/**
|
||
* 后端地址不走硬编码:优先读 local.properties 的 dadao.apiBase,
|
||
* 缺省指向模拟器访问宿主机的 10.0.2.2:8100。
|
||
*/
|
||
val apiBase: String = run {
|
||
val props = Properties()
|
||
val file = rootProject.file("local.properties")
|
||
if (file.exists()) file.inputStream().use { props.load(it) }
|
||
props.getProperty("dadao.apiBase") ?: "http://10.0.2.2:8100"
|
||
}
|
||
|
||
android {
|
||
namespace = "com.dadao.task"
|
||
compileSdk = 35
|
||
|
||
defaultConfig {
|
||
applicationId = "com.dadao.task"
|
||
minSdk = 26
|
||
targetSdk = 35
|
||
// 版本号是 OTA 的唯一判据:后端只比对 version_code,改这里才算"有新版本"
|
||
versionCode = 2
|
||
versionName = "0.2.0"
|
||
buildConfigField("String", "API_BASE", "\"$apiBase\"")
|
||
}
|
||
|
||
buildFeatures {
|
||
compose = true
|
||
buildConfig = true
|
||
}
|
||
|
||
/**
|
||
* 调试签名用仓库内的 keystore,而不是 ~/.android/debug.keystore。
|
||
*
|
||
* 原因:CI 与受限沙箱里 `~/.android` 常常不可写,AGP 会去建
|
||
* `debug.keystore.lock` 然后 AccessDenied,构建在 validateSigningDebug 这一步失败。
|
||
* 放在工程里就能在任何机器上直接 assembleDebug。
|
||
* 注意:这只是调试签名,release 必须换成真正的证书并走 secret 注入。
|
||
*/
|
||
signingConfigs {
|
||
getByName("debug") {
|
||
storeFile = rootProject.file("keystore/debug.keystore")
|
||
storePassword = "android"
|
||
keyAlias = "androiddebugkey"
|
||
keyPassword = "android"
|
||
}
|
||
/**
|
||
* 发布签名从 android/keystore.properties 读,证书本身不进仓库。
|
||
*
|
||
* 没有这个文件(别人 clone 下来、CI 没注入)时回落到调试签名:
|
||
* assembleRelease 依然能跑,只是装不上已经装了正式版的机器——
|
||
* 而这正是应该发生的:发布包的签名只能由发布者本人持有。
|
||
*/
|
||
create("release") {
|
||
val file = rootProject.file("keystore.properties")
|
||
if (file.exists()) {
|
||
val props = Properties()
|
||
file.inputStream().use { props.load(it) }
|
||
storeFile = rootProject.file(props.getProperty("storeFile"))
|
||
storePassword = props.getProperty("storePassword")
|
||
keyAlias = props.getProperty("keyAlias")
|
||
keyPassword = props.getProperty("keyPassword")
|
||
}
|
||
}
|
||
}
|
||
|
||
buildTypes {
|
||
release {
|
||
// 没有正式证书时回落调试签名,保证任何机器都能 assembleRelease
|
||
signingConfig = if (rootProject.file("keystore.properties").exists()) {
|
||
signingConfigs.getByName("release")
|
||
} else {
|
||
signingConfigs.getByName("debug")
|
||
}
|
||
isMinifyEnabled = false
|
||
isShrinkResources = false
|
||
}
|
||
}
|
||
|
||
compileOptions {
|
||
sourceCompatibility = JavaVersion.VERSION_17
|
||
targetCompatibility = JavaVersion.VERSION_17
|
||
}
|
||
|
||
kotlinOptions {
|
||
jvmTarget = "17"
|
||
}
|
||
}
|
||
|
||
dependencies {
|
||
implementation(platform("androidx.compose:compose-bom:2024.12.01"))
|
||
implementation("androidx.compose.ui:ui")
|
||
implementation("androidx.compose.ui:ui-tooling-preview")
|
||
implementation("androidx.compose.material3:material3")
|
||
implementation("androidx.activity:activity-compose:1.9.3")
|
||
// FileProvider(应用内升级把安装包交给系统安装器)就在 core 里,显式声明不靠传递依赖
|
||
implementation("androidx.core:core-ktx:1.13.1")
|
||
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
|
||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
|
||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
|
||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||
// Markdown 预览用成熟库渲染,不自己写解析器
|
||
implementation("io.noties.markwon:core:4.6.2")
|
||
// 表格与删除线:Web 端正文支持,安卓不能把 | 管道符原样吐给读者
|
||
implementation("io.noties.markwon:ext-tables:4.6.2")
|
||
implementation("io.noties.markwon:ext-strikethrough:4.6.2")
|
||
implementation("io.coil-kt:coil-compose:2.7.0")
|
||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||
}
|