Files
Cable/android/app/build.gradle.kts
Stefan Lange-Hegermann 89ee36c1a4 Add in-app rating prompt (iOS + Android)
Request an App Store / Play Store review after a successful export
(Overview PDF, BOM PDF, or wiring diagram). A shared gate keeps prompts
rare: >=2 successful exports, >=3 days since install, >=120 days since the
last prompt, and at most once per app version. A one-time migration
backdates existing users so the prompt can fire on their first export
after updating. Logs a "Review Prompt Requested" analytics event.

iOS uses StoreKit's AppStore.requestReview(in:) with UserDefaults state;
Android uses the Play In-App Review API with DataStore state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 01:05:24 +02:00

121 lines
3.8 KiB
Kotlin

import java.io.FileInputStream
import java.util.Properties
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.ksp)
}
// Release signing credentials, loaded from android/keystore.properties (gitignored).
// Falls back to no release signing when the file/keystore is absent (e.g. CI without secrets).
val keystoreProps = Properties().apply {
val f = rootProject.file("keystore.properties")
if (f.exists()) load(FileInputStream(f))
}
val hasReleaseSigning = keystoreProps.getProperty("storeFile")?.let { file(it).exists() } == true
android {
namespace = "app.voltplan.cable"
compileSdk = 35
defaultConfig {
applicationId = "app.voltplan.cable"
minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "1.0"
// Aptabase analytics — mirrors the iOS configuration (the iPhone app's tracker).
buildConfigField("String", "APTABASE_APP_KEY", "\"A-SH-4260269603\"")
buildConfigField("String", "APTABASE_HOST", "\"https://apta.yuzuhub.com\"")
vectorDrawables { useSupportLibrary = true }
resourceConfigurations += listOf("en", "de", "es", "fr", "nl")
}
signingConfigs {
if (hasReleaseSigning) {
create("release") {
storeFile = file(keystoreProps.getProperty("storeFile"))
storePassword = keystoreProps.getProperty("storePassword")
keyAlias = keystoreProps.getProperty("keyAlias")
keyPassword = keystoreProps.getProperty("keyPassword")
}
}
}
buildTypes {
debug {
isMinifyEnabled = false
}
release {
if (hasReleaseSigning) {
signingConfig = signingConfigs.getByName("release")
}
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
// Bundle native debug symbols so Play can symbolicate native crashes/ANRs.
ndk {
debugSymbolLevel = "FULL"
}
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
buildConfig = true
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.material.icons.extended)
implementation(libs.androidx.navigation.compose)
debugImplementation(libs.androidx.ui.tooling)
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.datastore.preferences)
implementation(libs.retrofit)
implementation(libs.retrofit.serialization)
implementation(libs.okhttp)
implementation(libs.okhttp.logging)
implementation(libs.kotlinx.serialization.json)
implementation(libs.coil.compose)
implementation(libs.play.review.ktx)
}