Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/renovate_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ jobs:

- uses: actions/checkout@v6

- name: set up JDK 17
- name: set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'corretto'
java-version: '17'
java-version: '21'
cache: gradle

- name: Grant execute permission for gradlew
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tag_create_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ jobs:

- uses: actions/checkout@v6

- name: set up JDK 17
- name: set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'corretto'
java-version: '17'
java-version: '21'
cache: gradle

- name: Grant execute permission for gradlew
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ production apps it is not likely that we have a need to use both sources interch

## Let's download and run it!

This project was configured to build using Android Studio Iguana | 2023.2.1. You will need to have
Java 17 to build the project.
This project was configured to build using Android Studio Otter 3 Feature Drop | 2025.2.3. You will need to have
Java 21 to build the project.

Alternatively, you can find the ready-to-install APKs and App Bundles under
the [release section](https://github.com/ryanw-mobile/FusedUserPreferences/releases).
Expand Down
52 changes: 23 additions & 29 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Copyright (c) 2024. Ryan Wong (hello@ryanwebmail.com)
*/

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.ManagedVirtualDevice
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import java.io.FileInputStream
import java.io.InputStreamReader
import java.text.SimpleDateFormat
Expand All @@ -12,7 +12,6 @@ import java.util.Properties

plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
alias(libs.plugins.hilt.android.plugin)
alias(libs.plugins.devtools.ksp)
alias(libs.plugins.compose.compiler)
Expand Down Expand Up @@ -64,16 +63,16 @@ android {
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
}

kotlin {
compilerOptions {
freeCompilerArgs.add("-Xannotation-default-target=param-property")
}
jvmToolchain(17)
jvmToolchain(21)
}

dependencies {
Expand Down Expand Up @@ -125,8 +124,8 @@ tasks {

detekt { parallel = true }

// Gradle Build Utilities
private fun BaseAppModuleExtension.setupSdkVersionsFromVersionCatalog() {
// Gradle Build Utilities - Revision 2026.01.22.01
private fun ApplicationExtension.setupSdkVersionsFromVersionCatalog() {
compileSdk = libs.versions.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
Expand All @@ -136,7 +135,7 @@ private fun BaseAppModuleExtension.setupSdkVersionsFromVersionCatalog() {
}
}

private fun BaseAppModuleExtension.setupPackagingResourcesDeduplication() {
private fun ApplicationExtension.setupPackagingResourcesDeduplication() {
packaging.resources {
excludes.addAll(
listOf(
Expand All @@ -158,25 +157,31 @@ private fun BaseAppModuleExtension.setupPackagingResourcesDeduplication() {
}
}

private fun BaseAppModuleExtension.setupSigningAndBuildTypes() {
private fun ApplicationExtension.setupSigningAndBuildTypes() {
val isReleaseSigningEnabled =
providers.gradleProperty("releaseSigning")
.map { it.toBoolean() }
.orElse(false)
.get()

val releaseSigningConfigName = "releaseSigningConfig"
val timestamp = SimpleDateFormat("yyyyMMdd-HHmmss").format(Date())
val baseName = "$productApkName-${libs.versions.versionName.get()}-$timestamp"
val isReleaseBuild = gradle.startParameter.taskNames.any {
it.contains("Release", ignoreCase = true)
|| it.contains("Bundle", ignoreCase = true)
|| it.equals("build", ignoreCase = true)
it.contains("Release", ignoreCase = true) ||
it.contains("Bundle", ignoreCase = true)
}

extensions.configure<BasePluginExtension> { archivesName.set(baseName) }
project.extensions.configure<BasePluginExtension> { archivesName.set(baseName) }

signingConfigs.create(releaseSigningConfigName) {
// Only initialise the signing config when a Release or Bundle task is being executed.
// This prevents Gradle sync or debug builds from attempting to load the keystore,
// which could fail if the keystore or environment variables are not available.
// SigningConfig itself is only wired to the 'release' build type, so this guard avoids unnecessary setup.
if (isReleaseBuild) {
if (isReleaseBuild && isReleaseSigningEnabled) {
val keystorePropertiesFile = file("../../keystore.properties")
println("🔑 Searching for keystore at ${keystorePropertiesFile.absolutePath}: exist? ${keystorePropertiesFile.exists()}")

if (isRunningOnCI || !keystorePropertiesFile.exists()) {
println("⚠\uFE0F Signing Config: using environment variables")
Expand All @@ -200,27 +205,15 @@ private fun BaseAppModuleExtension.setupSigningAndBuildTypes() {
storePassword = properties.getProperty("storePass")
}
} else {
println("⚠\uFE0F Signing Config: not created for non-release builds.")
println("⚠ Signing Config: skipped (no release signing intent)")
}
}

buildTypes {
fun setOutputFileName() {
applicationVariants.all {
outputs
.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
.forEach { output ->
val outputFileName = "$productApkName-$name-$versionName-$timestamp.apk"
output.outputFileName = outputFileName
}
}
}

getByName("debug") {
applicationIdSuffix = ".debug"
isMinifyEnabled = false
isDebuggable = true
setOutputFileName()
}

getByName("release") {
Expand All @@ -233,8 +226,9 @@ private fun BaseAppModuleExtension.setupSigningAndBuildTypes() {
"proguard-rules.pro",
),
)
signingConfig = signingConfigs.getByName(name = releaseSigningConfigName)
setOutputFileName()
if (isReleaseSigningEnabled) {
signingConfig = signingConfigs.getByName(name = releaseSigningConfigName)
}
}
}
}
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
alias(libs.plugins.hilt.android.plugin) apply false
alias(libs.plugins.devtools.ksp) apply false
alias(libs.plugins.compose.compiler) apply false
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonFinalResIds=false
android.nonFinalResIds=true
org.gradle.parallel=true
org.gradle.caching=true
# Not useful at the moment but later will revisit
Expand Down
5 changes: 2 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
agp = "8.13.2"
agp = "9.0.0"
kotlin = "2.3.0"
kotlinMetadataJvm = "2.3.0"
coreKtx = "1.17.0"
Expand All @@ -15,7 +15,7 @@ datastorePreferences = "1.2.0"
mockk = "1.14.7"
junitKtx = "1.3.0"
robolectric = "4.16.1"
hilt = "2.58"
hilt = "2.59"
hilt-navigation-compose = "1.3.0"
# ksp is linked to Kotlin version https://github.com/google/ksp/releases
devtoolsksp = "2.3.4"
Expand Down Expand Up @@ -67,7 +67,6 @@ hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-com

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
hilt-android-plugin = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "devtoolsksp" }
Expand Down