From 039e785a2d9b4b6799e02b7f78cbead317109ace Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:04:30 -0600 Subject: [PATCH] build: Lower JDK to 17 and minSdk to 21 (#4369) --- .github/copilot-instructions.md | 25 ++++++++++--------- .github/workflows/merge-queue.yml | 13 +++------- .github/workflows/pull-request.yml | 3 +-- .github/workflows/reusable-android-build.yml | 4 +-- .github/workflows/reusable-lint.yml | 8 ++++-- build-logic/convention/build.gradle.kts | 10 ++++---- .../meshtastic/buildlogic/KotlinAndroid.kt | 4 ++- core/api/build.gradle.kts | 6 +++++ core/model/build.gradle.kts | 6 +++++ core/proto/build.gradle.kts | 22 +++++----------- gradle/gradle-daemon-jvm.properties | 12 +-------- jitpack.yml | 2 +- 12 files changed, 53 insertions(+), 62 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c607fbbb0..b69f7c826 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -18,7 +18,7 @@ Meshtastic-Android is a native Android client application for the Meshtastic mes **ALWAYS run these commands in the exact order specified to avoid build failures:** ### Prerequisites Setup -1. **JDK Requirement:** JDK 21 is required (will fail with other versions) +1. **JDK Requirement:** JDK 17 is required (compatible with most developer environments) 2. **Secrets Configuration:** Copy `secrets.defaults.properties` to `local.properties` and update: ```properties MAPS_API_KEY=your_google_maps_api_key_here @@ -74,7 +74,7 @@ Meshtastic-Android is a native Android client application for the Meshtastic mes ### Environment Setup **Required Tools:** - Android SDK API 36 (compile target) -- JDK 21 (NOT JDK 17 or 11 - build will fail) +- JDK 17 (Preferred for consistency across project and plugins) - Gradle 9.0+ (downloaded automatically by wrapper) **Optional but Recommended:** @@ -90,16 +90,17 @@ Meshtastic-Android is a native Android client application for the Meshtastic mes │ ├── src/androidTest/ # Instrumented tests │ ├── src/fdroid/ # F-Droid specific code │ └── src/google/ # Google Play specific code +├── core/ # Core library modules ├── network/ # HTTP API networking library ├── mesh_service_example/ # AIDL service usage example -├── buildSrc/ # Build configuration (Configs.kt) +├── build-logic/ # Build configuration convention plugins └── config/ # Linting and formatting configs ├── detekt/ # Detekt static analysis rules └── spotless/ # Code formatting configuration ``` ### Key Configuration Files -- `buildSrc/src/main/kotlin/Configs.kt` - Version constants and build config +- `config.properties` - Version constants and build config - `app/build.gradle.kts` - Main app build configuration - `config/detekt/detekt.yml` - Static analysis rules - `config/spotless/.editorconfig` - Code formatting rules @@ -140,7 +141,7 @@ Meshtastic-Android is a native Android client application for the Meshtastic mes ## Common Issues & Solutions ### Build Failures -- **Gradle version error:** Ensure JDK 21 (NOT 17 or 11) +- **Gradle version error:** Ensure JDK 17 (Compatible version) - **Missing secrets:** Copy `secrets.defaults.properties` → `local.properties` - **Configuration cache:** Add `--no-configuration-cache` flag if issues persist - **Clean state:** Always run `./gradlew clean` before debugging build issues @@ -153,17 +154,17 @@ Meshtastic-Android is a native Android client application for the Meshtastic mes ### Code Style Issues - **Formatting:** Run `./gradlew spotlessApply` to auto-fix - **Detekt warnings:** Check `config/detekt/detekt.yml` for rules -- **Localization:** Use `stringResource(R.string.key)` instead of hardcoded strings +- **Localization:** Use `stringResource(Res.string.key)` instead of hardcoded strings ## File Organization ### Source Code Locations -- **Main Activity:** `app/src/main/java/com/geeksville/mesh/ui/MainActivity.kt` -- **Service Interface:** `app/src/main/aidl/com/geeksville/mesh/IMeshService.aidl` -- **UI Screens:** `app/src/main/java/com/geeksville/mesh/ui/` -- **Data Layer:** `app/src/main/java/com/geeksville/mesh/repository/` -- **Database:** `app/src/main/java/com/geeksville/mesh/database/` -- **Models:** `app/src/main/java/com/geeksville/mesh/model/` +- **Main Activity:** `app/src/main/java/com/geeksville/mesh/MainActivity.kt` +- **Service Interface:** `core/api/src/main/aidl/org/meshtastic/core/service/IMeshService.aidl` +- **UI Screens:** `feature/*/src/main/kotlin/org/meshtastic/feature/*/` +- **Data Layer:** `core/data/src/main/kotlin/org/meshtastic/core/data/` +- **Database:** `core/database/src/main/kotlin/org/meshtastic/core/database/` +- **Models:** `core/model/src/main/kotlin/org/meshtastic/core/model/` ### Dependencies - **Non-obvious deps:** Protobuf for device communication, DataDog for analytics (Google flavor) diff --git a/.github/workflows/merge-queue.yml b/.github/workflows/merge-queue.yml index 96e3350f6..9f4f77d70 100644 --- a/.github/workflows/merge-queue.yml +++ b/.github/workflows/merge-queue.yml @@ -12,8 +12,7 @@ jobs: lint: if: github.repository == 'meshtastic/Meshtastic-Android' uses: ./.github/workflows/reusable-lint.yml - secrets: - GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + secrets: inherit build: needs: lint @@ -21,11 +20,7 @@ jobs: uses: ./.github/workflows/reusable-android-build.yml with: upload_artifacts: false - secrets: - GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }} - DATADOG_APPLICATION_ID: ${{ secrets.DATADOG_APPLICATION_ID }} - DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }} - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + secrets: inherit androidTest: needs: lint @@ -35,9 +30,7 @@ jobs: api_levels: '[26, 35]' # Run on both API 26 and 35 for merge queue test_flavors: 'both' # Run both flavors for merge queue (comprehensive) upload_artifacts: false - secrets: - GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }} - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + secrets: inherit check-workflow-status: name: Check Workflow Status # Matches another in pull-request, and is required for merge to main. diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index d6e60d563..cae01a885 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -38,8 +38,7 @@ jobs: needs: check-changes if: needs.check-changes.outputs.code_changed == 'true' uses: ./.github/workflows/reusable-lint.yml - secrets: - GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + secrets: inherit build: needs: lint diff --git a/.github/workflows/reusable-android-build.yml b/.github/workflows/reusable-android-build.yml index 4e20a93b5..9607c8ad6 100644 --- a/.github/workflows/reusable-android-build.yml +++ b/.github/workflows/reusable-android-build.yml @@ -42,10 +42,10 @@ jobs: fetch-depth: 0 submodules: 'recursive' - - name: Set up JDK 21 + - name: Set up JDK 17 uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '17' distribution: 'jetbrains' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reusable-lint.yml b/.github/workflows/reusable-lint.yml index 541e0eea2..14b029aa6 100644 --- a/.github/workflows/reusable-lint.yml +++ b/.github/workflows/reusable-lint.yml @@ -5,21 +5,25 @@ on: secrets: GRADLE_ENCRYPTION_KEY: required: false + GRADLE_CACHE_URL: + required: false jobs: lint: runs-on: ubuntu-latest # Lint is fast, doesn't need large runner timeout-minutes: 10 + env: + GRADLE_CACHE_URL: ${{ secrets.GRADLE_CACHE_URL }} steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 - - name: Set up JDK 21 + - name: Set up JDK 17 uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '17' distribution: 'jetbrains' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index dc80cbf42..ec49dfda7 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -25,16 +25,16 @@ plugins { group = "org.meshtastic.buildlogic" -// Configure the build-logic plugins to target JDK 21 -// This matches the JDK used to build the project, and is not related to what is running on device. +// Configure the build-logic plugins to target JDK 17 +// This improves compatibility for developers building the project or consuming its libraries. java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlin { compilerOptions { - jvmTarget = JvmTarget.JVM_21 + jvmTarget = JvmTarget.JVM_17 } } diff --git a/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt index dc8f9f055..8e9ba05f7 100644 --- a/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt @@ -86,7 +86,9 @@ internal fun Project.configureKotlinJvm() { */ private inline fun Project.configureKotlin() { extensions.configure { - jvmToolchain(21) + // Using Java 17 for better compatibility with consumers (e.g. plugins, older environments) + // while still supporting modern Kotlin features. + jvmToolchain(17) } tasks.withType().configureEach { diff --git a/core/api/build.gradle.kts b/core/api/build.gradle.kts index 65a88a57e..7433e452f 100644 --- a/core/api/build.gradle.kts +++ b/core/api/build.gradle.kts @@ -35,6 +35,12 @@ afterEvaluate { configure { namespace = "org.meshtastic.core.api" buildFeatures { aidl = true } + + defaultConfig { + // Lowering minSdk to 21 for better compatibility with ATAK and other plugins + minSdk = 21 + } + publishing { singleVariant("googleRelease") { withSourcesJar() } } } diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index 74ea92458..ec19faf5a 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -42,6 +42,12 @@ configure { aidl = true } namespace = "org.meshtastic.core.model" + + defaultConfig { + // Lowering minSdk to 21 for better compatibility with ATAK and other plugins + minSdk = 21 + } + publishing { singleVariant("googleRelease") { withSourcesJar() } } } diff --git a/core/proto/build.gradle.kts b/core/proto/build.gradle.kts index e904a9ea4..2ddab69c3 100644 --- a/core/proto/build.gradle.kts +++ b/core/proto/build.gradle.kts @@ -16,22 +16,6 @@ */ import com.android.build.api.dsl.LibraryExtension -/* - * Copyright (c) 2025 Meshtastic LLC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ plugins { alias(libs.plugins.meshtastic.android.library) alias(libs.plugins.protobuf) @@ -53,6 +37,12 @@ afterEvaluate { configure { namespace = "org.meshtastic.core.proto" + + defaultConfig { + // Lowering minSdk to 21 for better compatibility with ATAK and other plugins + minSdk = 21 + } + publishing { singleVariant("googleRelease") { withSourcesJar() } } } diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties index 72c107f93..858feb7e3 100644 --- a/gradle/gradle-daemon-jvm.properties +++ b/gradle/gradle-daemon-jvm.properties @@ -1,12 +1,2 @@ #This file is generated by updateDaemonJvm -toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ff1d4fc92bcfc9d3799beabb4e70cfa3/redirect -toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/08ce182188ada0b93565cd9ca4a4ab32/redirect -toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c5760d82d08e6c26884debb23736ea57/redirect -toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/879378f84c64b2c76003b97a32968399/redirect -toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/70ee42f1b0395356c016dbcb3e88f71d/redirect -toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/6141bf023dcc7a96c47cad75c59b054e/redirect -toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ff1d4fc92bcfc9d3799beabb4e70cfa3/redirect -toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/08ce182188ada0b93565cd9ca4a4ab32/redirect -toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/3dc48436acf46a9c2958682158988183/redirect -toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d935bdb25150f4573137eb8176e8b4ec/redirect -toolchainVersion=21 +toolchainVersion=17 diff --git a/jitpack.yml b/jitpack.yml index 6ed1a28d4..e1b0fc233 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,5 +1,5 @@ jdk: - - openjdk21 + - openjdk17 before_install: - ./gradlew :core:proto:generateGoogleReleaseProto install: