阶段6:Restic streaming 策略 - ConfigScreen 流式备份文案改为'实验性 Restic 临时目录备份' 并显示不完整备份警告 - ResticStreamBackup 写入 streaming_manifest.json 记录 excluded 项目 - RestoreViewModel 检测 streaming manifest 并在确认弹窗中显示警告 阶段7:发布与仓库治理 - .gitignore 排除 app/release/*.apk - build.gradle release 构建强制签名,启用 R8 + shrinkResources - proguard-rules.pro 修正 restic 类路径,启用 R8 keep 规则 - 新增 .github/workflows/android.yml (CI: lint/test/assembleDebug) - 新增 .github/workflows/release.yml (Release: tag触发,签名,sha256)
138 lines
5.0 KiB
Groovy
138 lines
5.0 KiB
Groovy
apply plugin: 'com.android.application'
|
|
apply plugin: 'kotlin-android'
|
|
apply plugin: 'kotlinx-serialization'
|
|
apply plugin: 'org.jetbrains.kotlinx.kover'
|
|
|
|
kover {
|
|
reports {
|
|
filters {
|
|
excludes {
|
|
classes(
|
|
"*.BuildConfig",
|
|
"*.R",
|
|
"*.R\$*"
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
android {
|
|
namespace "com.example.androidbackupgui"
|
|
compileSdk 34
|
|
defaultConfig {
|
|
applicationId "com.example.androidbackupgui"
|
|
minSdk 24
|
|
targetSdk 34
|
|
versionCode 16
|
|
versionName "1.16"
|
|
}
|
|
buildFeatures {
|
|
compose = true
|
|
}
|
|
composeOptions {
|
|
kotlinCompilerExtensionVersion = "1.5.1"
|
|
}
|
|
lint {
|
|
disable 'QueryAllPackagesPermission'
|
|
}
|
|
signingConfigs {
|
|
release {
|
|
storeFile rootProject.file("app/release.keystore")
|
|
storePassword System.getenv("KEYSTORE_PASSWORD")
|
|
keyAlias "release"
|
|
keyPassword System.getenv("KEY_PASSWORD")
|
|
v1SigningEnabled true
|
|
v2SigningEnabled true
|
|
}
|
|
}
|
|
buildTypes {
|
|
release {
|
|
minifyEnabled true
|
|
shrinkResources true
|
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
def ksFile = rootProject.file("app/release.keystore")
|
|
def ksPass = System.getenv("KEYSTORE_PASSWORD")
|
|
def kPass = System.getenv("KEY_PASSWORD")
|
|
def isReleaseTask = gradle.startParameter.taskNames.any { it.toLowerCase().contains("release") }
|
|
if (isReleaseTask) {
|
|
if (!ksFile.exists() || ksPass == null || ksPass.isEmpty() || kPass == null || kPass.isEmpty()) {
|
|
throw new GradleException("Release build requires signing config. Set KEYSTORE_PASSWORD and KEY_PASSWORD env vars and ensure app/release.keystore exists.")
|
|
}
|
|
signingConfig signingConfigs.release
|
|
} else if (ksFile.exists() && ksPass != null && !ksPass.isEmpty() && kPass != null && !kPass.isEmpty()) {
|
|
signingConfig signingConfigs.release
|
|
}
|
|
}
|
|
}
|
|
testOptions {
|
|
unitTests.all {
|
|
|
|
useJUnitPlatform()
|
|
}
|
|
}
|
|
compileOptions {
|
|
sourceCompatibility JavaVersion.VERSION_17
|
|
targetCompatibility JavaVersion.VERSION_17
|
|
}
|
|
kotlinOptions {
|
|
jvmTarget = '17'
|
|
}
|
|
packagingOptions {
|
|
jniLibs {
|
|
useLegacyPackaging true
|
|
}
|
|
resources {
|
|
excludes += [
|
|
'org/bouncycastle/pqc/crypto/picnic/lowmcL5.bin.properties',
|
|
'org/bouncycastle/pqc/crypto/picnic/lowmcL3.bin.properties',
|
|
'org/bouncycastle/pqc/crypto/picnic/lowmcL1.bin.properties',
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
// Compose BOM (manages all Compose library versions)
|
|
implementation platform('androidx.compose:compose-bom:2024.02.00')
|
|
implementation 'androidx.compose.material3:material3'
|
|
implementation 'androidx.compose.ui:ui'
|
|
implementation 'androidx.compose.ui:ui-tooling-preview'
|
|
implementation 'androidx.compose.foundation:foundation'
|
|
implementation 'androidx.compose.material:material-icons-extended'
|
|
implementation 'androidx.activity:activity-compose:1.8.2'
|
|
debugImplementation 'androidx.compose.ui:ui-tooling'
|
|
|
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
|
|
implementation 'androidx.core:core-ktx:1.12.0'
|
|
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
implementation 'com.google.android.material:material:1.11.0'
|
|
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
|
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
|
|
implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
|
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
|
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
|
|
|
|
// 方案A: jcifs-ng (SMB) + sardine-android (WebDAV) 替代 rclone serve
|
|
implementation("eu.agno3.jcifs:jcifs-ng:2.1.10") {
|
|
exclude group: 'org.bouncycastle'
|
|
}
|
|
implementation("com.github.thegrizzlylabs:sardine-android:v0.9") {
|
|
exclude group: 'xpp3'
|
|
exclude group: 'stax'
|
|
}
|
|
implementation "org.slf4j:slf4j-android:1.7.36"
|
|
|
|
// root shell via libsu (Magisk/KernelSU/APatch)
|
|
implementation 'com.github.topjohnwu:libsu:6.0.0'
|
|
// Full BouncyCastle provider (includes MD4 required by jcifs-ng SMB)
|
|
implementation 'org.bouncycastle:bcprov-jdk15to18:1.77'
|
|
implementation 'org.nanohttpd:nanohttpd:2.3.1'
|
|
testImplementation "io.kotest:kotest-runner-junit5:5.9.1"
|
|
testImplementation "io.kotest:kotest-assertions-core:5.9.1"
|
|
testImplementation "io.kotest:kotest-property:5.9.1"
|
|
testImplementation "io.mockk:mockk:1.13.12"
|
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3"
|
|
}
|