Files
claude-usage-widget/app/build.gradle.kts
T
amir a6d930415c
Build APK / build (push) Successful in 2m18s
Fix empty usage-history chart + externalize signing secrets
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.
2026-06-10 10:28:37 +00:00

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")
}