a6d930415c
Build APK / build (push) Successful in 2m18s
History chart: recordHistory() threw away the previous point whenever a new reading landed within the 2-min de-dup window, but the foreground loop refreshes every 30s — so history could never grow past one point while the app was open and the chart stayed stuck on 'Collecting history…'. Now it throttles by SKIPPING a too-soon reading instead of replacing the last one, so points accumulate during normal use. Security: - Remove hardcoded release keystore passwords from build.gradle.kts; read from env vars / gitignored keystore.properties; CI injects from Gitea secrets (KEYSTORE_PASSWORD/KEY_PASSWORD). Signing identity unchanged. - Make the cookie-never-plaintext invariant explicit on the read path. - Drop custom ACTION_REFRESH from the exported widget intent-filter so other apps can't trigger refreshes; internal explicit PendingIntent still works. - Gate an unguarded Log.w behind BuildConfig.DEBUG.
105 lines
3.6 KiB
Kotlin
105 lines
3.6 KiB
Kotlin
import java.util.Properties
|
|
|
|
plugins {
|
|
id("com.android.application")
|
|
id("org.jetbrains.kotlin.android")
|
|
}
|
|
|
|
// Signing credentials are NEVER committed. They are read from (in order):
|
|
// 1. environment variables (KEYSTORE_PASSWORD / KEY_PASSWORD / KEY_ALIAS) — used by CI
|
|
// 2. keystore.properties at the repo root (gitignored) — used locally
|
|
// See keystore.properties.example. Debug builds need none of this.
|
|
val keystoreProps = Properties().apply {
|
|
val f = rootProject.file("keystore.properties")
|
|
if (f.exists()) f.inputStream().use { load(it) }
|
|
}
|
|
fun signingCred(envName: String, propName: String): String? =
|
|
System.getenv(envName) ?: keystoreProps.getProperty(propName)
|
|
|
|
android {
|
|
namespace = "me.khodak.claudeusage"
|
|
compileSdk = 34
|
|
|
|
defaultConfig {
|
|
applicationId = "me.khodak.claudeusage"
|
|
minSdk = 26
|
|
targetSdk = 34
|
|
versionCode = 19
|
|
versionName = "1.18"
|
|
}
|
|
|
|
val releaseStorePassword = signingCred("KEYSTORE_PASSWORD", "storePassword")
|
|
val releaseKeyPassword = signingCred("KEY_PASSWORD", "keyPassword")
|
|
val releaseKeyAlias = signingCred("KEY_ALIAS", "keyAlias") ?: "claudewidget"
|
|
val hasSigningCreds = releaseStorePassword != null && releaseKeyPassword != null
|
|
|
|
signingConfigs {
|
|
create("release") {
|
|
// Only wire the keystore when credentials are present, so debug builds and
|
|
// credential-less checkouts configure cleanly. Same keystore file + alias as before —
|
|
// signing identity is unchanged; only the password source moved out of version control.
|
|
if (hasSigningCreds) {
|
|
storeFile = file("claude-widget-release.keystore")
|
|
storePassword = releaseStorePassword
|
|
keyAlias = releaseKeyAlias
|
|
keyPassword = releaseKeyPassword
|
|
}
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
isMinifyEnabled = true
|
|
isShrinkResources = true
|
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
|
// Sign only when creds were supplied; otherwise fail loudly at assembleRelease rather
|
|
// than silently shipping an unsigned APK. Tag builds in CI inject creds (see workflow).
|
|
if (hasSigningCreds) {
|
|
signingConfig = signingConfigs.getByName("release")
|
|
} else {
|
|
logger.warn("No signing credentials (KEYSTORE_PASSWORD/keystore.properties) — release APK will be unsigned.")
|
|
}
|
|
}
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
|
|
kotlinOptions {
|
|
jvmTarget = "17"
|
|
}
|
|
|
|
buildFeatures {
|
|
viewBinding = true
|
|
buildConfig = true
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
implementation("androidx.core:core-ktx:1.12.0")
|
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
|
implementation("com.google.android.material:material:1.11.0")
|
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
|
|
|
// HTTP
|
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
|
|
|
// JSON
|
|
implementation("com.google.code.gson:gson:2.10.1")
|
|
|
|
// Background work
|
|
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
|
|
|
// Secure storage
|
|
implementation("androidx.security:security-crypto:1.1.0-alpha06")
|
|
|
|
// Coroutines
|
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
|
|
|
// Lifecycle
|
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
|
|
}
|