Files
dsh-pet-floating/app/build.gradle.kts
T
jkooe 43275ae7a0
Build APK / build (push) Canceled after 7m12s
feat(ci): Gitea Actions 构建完整版 APK 并发布 Release;App 内更新检查
- .gitea/workflows/build.yml:打 tag 触发构建。代码取当前 ref,素材目录单独从 full-assets 分支叠加
  (main 保持 ~8MB 不追踪 assets_hq/assets_small/assets_net,缺它们构建出来的包宠物是空白的)。
  用 secret 注入的固定 keystore 签 release 包,构建后发布 APK + version.json 到 Gitea Release。
- app/build.gradle.kts:签名改为从环境变量读取(KEYSTORE_PATH / KEYSTORE_PASSWORD / KEY_ALIAS /
  KEY_PASSWORD),本地无 keystore 时回退 debug 签名;versionCode 支持 CI 注入,保证单调递增
  (更新机制要求新包 versionCode 严格大于已装版本,否则系统拒绝覆盖安装)。
- UpdateChecker.kt:读 Gitea Release API 按 versionCode 判版本 → 下载并校验 SHA256 → 经自带
  ApkProvider(content://)拉起系统安装器。项目零第三方依赖,用不了 androidx FileProvider,
  故自带一个只读 ContentProvider(只暴露 cacheDir/update 下的 .apk,路径取 basename 防穿越)。
- MainActivity 设置页新增「关于 / 检查更新」入口,下载前先检查「安装未知来源应用」授权。
- AndroidManifest 新增 REQUEST_INSTALL_PACKAGES 与 ApkProvider 声明。
- .gitignore 增加 *.jks / *.keystore / keystore.properties,防止签名文件误入库。
2026-11-09 17:16:41 +08:00

87 lines
3.4 KiB
Kotlin
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.
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.dsh.petfloat"
compileSdk = 34
defaultConfig {
applicationId = "com.dsh.petfloat"
minSdk = 26
targetSdk = 34
// 版本号:CI 注入 VERSION_CODE(单调递增),本地缺省 1000。
// 更新机制要求新包 versionCode **严格大于**已装版本,否则系统会拒绝覆盖安装。
val injectedCode = System.getenv("VERSION_CODE")?.toIntOrNull()
versionCode = injectedCode ?: 1000
versionName = System.getenv("VERSION_NAME") ?: "1.0.$versionCode"
}
// 发布签名:CI 通过 secret 注入 keystore(见 .gitea/workflows/build.yml)。
// 本地没有 keystore 时不创建 release signingConfig,release 变体退回 debug 签名——
// 仅用于本地验证,**不可用于分发**(debug 签名每台机器不同,无法覆盖安装)。
val keystorePath = System.getenv("KEYSTORE_PATH")
val hasReleaseKeystore = !keystorePath.isNullOrBlank() && file(keystorePath).exists()
signingConfigs {
if (hasReleaseKeystore) {
create("release") {
storeFile = file(keystorePath!!)
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS") ?: "petfloat"
keyPassword = System.getenv("KEY_PASSWORD") ?: System.getenv("KEYSTORE_PASSWORD")
}
}
}
buildTypes {
release {
isMinifyEnabled = false
if (hasReleaseKeystore) {
signingConfig = signingConfigs.getByName("release")
}
}
}
// 生成 BuildConfig:QA-004 的 debug 故障注入必须靠 `BuildConfig.DEBUG` 做编译期闸门
//(release 里它是常量 false,注入开关整段不可达)。AGP 8 默认不生成,这里显式打开。
buildFeatures {
buildConfig = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
// 单测(纯 JVM,不需要设备):判定内核 ReconcileEngine 不碰 Context,可直接跑。
testOptions {
unitTests.isReturnDefaultValues = true // android.jar stub 方法返回默认值而不是抛异常
unitTests.all { it.testLogging { showStandardStreams = true } } // 让 benchmark 数字打到控制台
}
// 素材两套:默认小体积(pilot 128MB 上限内可装),-Phq 用 640×360 原画质
val hqBuild = project.hasProperty("hq")
sourceSets["main"].assets.setSrcDirs(
listOf(
file("src/main/assets_common"),
file("src/main/assets_net"),
file(if (hqBuild) "src/main/assets_hq" else "src/main/assets_small")
)
)
}
dependencies {
// 纯平台 API(android.* / java.* / 平台自带 org.json),无需第三方依赖。
// 以下**仅测试依赖,不进 APK**:
testImplementation("junit:junit:4.13.2")
// JVM 版 org.json:android.jar 里的 org.json 只是 stub,JVM 单测调用会抛异常;
// 加它才能在单测里实测「600 条全量 JSON 解析」的真实耗时(Android 平台的 org.json
// 与此实现同源,属同一量级,作为代理指标使用,见交付说明)。
testImplementation("org.json:json:20240303")
}