mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-10 16:02:25 +01:00
Models download in Settings instead of shipping in the APK. Credits for the engine and models are in About.
141 lines
5.8 KiB
Kotlin
141 lines
5.8 KiB
Kotlin
import java.util.Properties
|
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
|
|
|
/**
|
|
* Gearslip: a phone-side Android Auto client built against the reverse-engineered AA wire
|
|
* protocol, so a non-Google app can authenticate to and project onto a real car head unit
|
|
* with no gearhead in the path. No third-party dependencies: the X.509 certificate is
|
|
* generated by hand (see `SelfSignedCert`) so there is no BouncyCastle version to track and
|
|
* no second crypto provider to collide with Conscrypt.
|
|
*/
|
|
plugins {
|
|
alias(libs.plugins.android.application)
|
|
alias(libs.plugins.kotlin.compose)
|
|
}
|
|
|
|
// The release signing key, read from an untracked keystore.properties beside this file or at the
|
|
// repository root. Third-party apps allowlist Gearslip by the SHA-256 of this certificate, so the
|
|
// key must stay the same for the life of the project - and must never be committed.
|
|
val keystoreProperties = Properties().apply {
|
|
listOf(
|
|
rootProject.file("keystore.properties"),
|
|
project.file("keystore.properties"),
|
|
).firstOrNull { it.exists() }?.inputStream()?.use { load(it) }
|
|
}
|
|
|
|
android {
|
|
namespace = "app.seb3thehacker.gearslip"
|
|
compileSdk = 37
|
|
|
|
defaultConfig {
|
|
applicationId = "app.seb3thehacker.gearslip"
|
|
minSdk = 31
|
|
targetSdk = 37
|
|
versionCode = 8
|
|
// -PgearslipVersionName=0.1.99-test makes a build that thinks it's older, to try the updater.
|
|
versionName = project.findProperty("gearslipVersionName")?.toString() ?: "0.2.00-alpha"
|
|
manifestPlaceholders["appLabel"] = "Gearslip"
|
|
// Where opted-in phones send their daily usage note: the stats-worker/ Worker's address,
|
|
// set as gearslipStatsUrl in gradle.properties. Left empty, nothing is ever sent.
|
|
buildConfigField("String", "STATS_URL", "\"${project.findProperty("gearslipStatsUrl") ?: ""}\"")
|
|
}
|
|
|
|
signingConfigs {
|
|
// Declared only when the properties file is present, so a clone without the key still
|
|
// builds debug; assembleRelease then falls back to unsigned rather than failing here.
|
|
if (keystoreProperties.getProperty("storeFile") != null) {
|
|
create("release") {
|
|
storeFile = rootProject.file(keystoreProperties.getProperty("storeFile"))
|
|
storePassword = keystoreProperties.getProperty("storePassword")
|
|
keyAlias = keystoreProperties.getProperty("keyAlias")
|
|
keyPassword = keystoreProperties.getProperty("keyPassword")
|
|
}
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
signingConfig = signingConfigs.findByName("release")
|
|
}
|
|
// Its own package, so a dev build installs beside the release one instead of over it.
|
|
// Signed with the release key when it's here: both builds declare the car template
|
|
// permission, and Android refuses a second app declaring it under a different key.
|
|
debug {
|
|
applicationIdSuffix = ".dev"
|
|
signingConfigs.findByName("release")?.let { signingConfig = it }
|
|
manifestPlaceholders["appLabel"] = "Gearslip Dev"
|
|
}
|
|
}
|
|
|
|
buildFeatures {
|
|
buildConfig = true
|
|
}
|
|
|
|
// Keeps build output out of the module folder: <root>/build/gearslip/... instead of
|
|
// <root>/gearslip/build/..., so everything this project produces lands under one
|
|
// root-level build/ directory.
|
|
layout.buildDirectory.set(rootProject.layout.buildDirectory.dir("gearslip"))
|
|
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_21
|
|
targetCompatibility = JavaVersion.VERSION_21
|
|
}
|
|
|
|
defaultConfig {
|
|
// Speech-to-text (sherpa-onnx, in jniLibs) ships for 64-bit ARM only: every phone
|
|
// Gearslip runs on, and one copy of the native library instead of four.
|
|
ndk { abiFilters += "arm64-v8a" }
|
|
}
|
|
|
|
testOptions {
|
|
// GearslipLog calls android.util.Log, which is a stub on the local JVM.
|
|
unitTests.isReturnDefaultValues = true
|
|
}
|
|
|
|
}
|
|
|
|
// Renames the produced APK and moves it to the root build/ folder (<root>/build/Gearslip-debug.apk)
|
|
// after the fact rather than fighting AGP's variant-output API across versions - simpler and
|
|
// doesn't break when that API moves again.
|
|
tasks.register("renameApk") {
|
|
doLast {
|
|
val rootBuildDir = rootProject.layout.buildDirectory.get().asFile
|
|
layout.buildDirectory.dir("outputs/apk").get().asFile.walkTopDown()
|
|
.filter { it.extension == "apk" }
|
|
.toList()
|
|
.forEach { apk ->
|
|
val renamed = File(rootBuildDir, "Gearslip-${apk.parentFile.name}.apk")
|
|
apk.copyTo(renamed, overwrite = true)
|
|
apk.delete()
|
|
}
|
|
}
|
|
}
|
|
tasks.matching { it.name.startsWith("assemble") }.configureEach { finalizedBy("renameApk") }
|
|
|
|
dependencies {
|
|
// Only for the XML window theme (Theme.Material3.DynamicColors); every screen is Compose.
|
|
implementation(libs.google.material)
|
|
implementation(platform(libs.androidx.compose.bom))
|
|
implementation(libs.androidx.compose.ui)
|
|
implementation(libs.androidx.compose.material3)
|
|
implementation(libs.commons.compress)
|
|
implementation(libs.androidx.compose.material.icons.core)
|
|
implementation(libs.androidx.activity.compose)
|
|
implementation(libs.androidx.lifecycle.runtime.compose)
|
|
// Used from the host side, not the app side: Gearslip renders other apps' templates rather
|
|
// than publishing its own, so this is here for the AIDL interfaces and the model classes
|
|
// their Bundleables deserialize into.
|
|
implementation(libs.androidx.car.app)
|
|
implementation(libs.androidx.car.app.projected)
|
|
implementation(libs.androidx.media)
|
|
testImplementation(libs.junit)
|
|
}
|
|
|
|
tasks.withType<KotlinJvmCompile>().configureEach {
|
|
compilerOptions {
|
|
jvmTarget.set(JvmTarget.JVM_21)
|
|
}
|
|
}
|
|
|