diff --git a/platform/android/MapLibreAndroid/build.gradle.kts b/platform/android/MapLibreAndroid/build.gradle.kts index 555194d1f..d5cb9b700 100644 --- a/platform/android/MapLibreAndroid/build.gradle.kts +++ b/platform/android/MapLibreAndroid/build.gradle.kts @@ -1,9 +1,7 @@ plugins { + id("com.android.library") alias(libs.plugins.kotlinter) alias(libs.plugins.dokka) - id("com.android.library") - id("com.jaredsburrows.license") - kotlin("android") id("maplibre.download-vulkan-validation") id("maplibre.gradle-checkstyle") id("maplibre.gradle-dependencies-graph") @@ -38,13 +36,15 @@ dependencies { dokka { moduleName.set("MapLibre Native Android") + val dokkaVariantName = "openglRelease" dokkaSourceSets { - main { + configureEach { + suppress.set(name != dokkaVariantName) includes.from("Module.md") sourceLink { - remoteUrl("https://github.com/maplibre/maplibre-native/tree/main/platform/android/") + remoteUrl.set(uri("https://github.com/maplibre/maplibre-native/tree/main/platform/android/")) localDirectory.set(rootDir) } @@ -61,7 +61,6 @@ android { defaultConfig { compileSdk = 34 minSdk = 23 - targetSdk = 33 buildConfigField("String", "GIT_REVISION_SHORT", "\"${getGitRevision()}\"") buildConfigField("String", "GIT_REVISION", "\"${getGitRevision(false)}\"") buildConfigField( @@ -134,7 +133,7 @@ android { nativeBuild(nativeTargets) // Avoid naming conflicts, force usage of prefix - resourcePrefix("maplibre_") + resourcePrefix = "maplibre_" sourceSets { getByName("main") { @@ -150,12 +149,14 @@ android { // http://robolectric.org/migrating/#migrating-to-40 isIncludeAndroidResources = true } + targetSdk = 33 } buildTypes { debug { - isTestCoverageEnabled = false isJniDebuggable = true + enableUnitTestCoverage = false + enableAndroidTestCoverage = false } } @@ -171,6 +172,7 @@ android { "WrongThreadInterprocedural" ) warningsAsErrors = false + targetSdk = 33 } buildFeatures { @@ -182,16 +184,6 @@ android { targetCompatibility = JavaVersion.VERSION_11 } - kotlinOptions { - jvmTarget = "11" - } -} - -licenseReport { - generateHtmlReport = false - generateJsonReport = true - copyHtmlReportToAssets = false - copyJsonReportToAssets = false } fun getGitRevision(shortRev: Boolean = true): String { diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/LocalRequestTask.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/LocalRequestTask.java index a3116c651..ab4cfdbd1 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/LocalRequestTask.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/LocalRequestTask.java @@ -7,7 +7,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.maplibre.android.MapStrictMode; -import org.maplibre.android.MapLibre; import org.maplibre.android.log.Logger; import java.io.IOException; @@ -17,16 +16,18 @@ class LocalRequestTask extends AsyncTask { private static final String TAG = "Mbgl-LocalRequestTask"; + private final AssetManager assets; private OnLocalRequestResponse requestResponse; - LocalRequestTask(OnLocalRequestResponse requestResponse) { + LocalRequestTask(@NonNull AssetManager assets, OnLocalRequestResponse requestResponse) { + this.assets = assets; this.requestResponse = requestResponse; } @Nullable @Override protected byte[] doInBackground(String... strings) { - return loadFile(MapLibre.getApplicationContext().getAssets(), + return loadFile(assets, "integration/" + strings[0] .substring(8) .replaceAll("%20", " ") diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/NativeHttpRequest.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/NativeHttpRequest.java index 0c4c43aab..fdb31ba29 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/NativeHttpRequest.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/http/NativeHttpRequest.java @@ -61,7 +61,7 @@ public class NativeHttpRequest implements HttpResponder { } private void executeLocalRequest(String resourceUrl) { - new LocalRequestTask(new LocalRequestTask.OnLocalRequestResponse() { + new LocalRequestTask(MapLibre.getApplicationContext().getAssets(), new LocalRequestTask.OnLocalRequestResponse() { @Override public void onResponse(@Nullable byte[] bytes) { if (bytes != null) { diff --git a/platform/android/MapLibreAndroidTestApp/build.gradle.kts b/platform/android/MapLibreAndroidTestApp/build.gradle.kts index 6b2cf1e45..fa2b7eee0 100644 --- a/platform/android/MapLibreAndroidTestApp/build.gradle.kts +++ b/platform/android/MapLibreAndroidTestApp/build.gradle.kts @@ -1,7 +1,6 @@ plugins { alias(libs.plugins.kotlinter) id("com.android.application") - alias(libs.plugins.kotlinAndroid) alias(libs.plugins.kotlinPluginSerialization) id("maplibre.gradle-make") id("maplibre.gradle-config") @@ -43,12 +42,12 @@ android { buildTypes { getByName("debug") { + manifestPlaceholders += mapOf() isJniDebuggable = true isDebuggable = true - isTestCoverageEnabled = true isMinifyEnabled = false isShrinkResources = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") packaging { jniLibs { @@ -57,13 +56,15 @@ android { } buildConfigField("String", "SENTRY_DSN", "\"" + (System.getenv("SENTRY_DSN") ?: "") + "\"") + enableUnitTestCoverage = true + enableAndroidTestCoverage = true manifestPlaceholders["SENTRY_DSN"] = System.getenv("SENTRY_DSN") ?: "" } getByName("release") { isMinifyEnabled = true isShrinkResources = true - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") testProguardFiles("test-proguard-rules.pro") signingConfig = signingConfigs.getByName("debug") @@ -144,6 +145,7 @@ dependencies { implementation(libs.maplibreJavaTurf) implementation(libs.supportRecyclerView) + implementation(libs.supportPrint) implementation(libs.supportDesign) implementation(libs.supportConstraintLayout) implementation(libs.kotlinxSerializationJson) diff --git a/platform/android/MapLibrePlugin/build.gradle.kts b/platform/android/MapLibrePlugin/build.gradle.kts index 6e264a118..cb3648dbc 100644 --- a/platform/android/MapLibrePlugin/build.gradle.kts +++ b/platform/android/MapLibrePlugin/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } dependencies { - implementation("com.android.tools.build:gradle:8.6.1") + implementation("com.android.tools.build:gradle:9.1.1") } group = "org.maplibre" diff --git a/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties b/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties index aaaabb3cb..37f78a6af 100644 --- a/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/platform/android/MapLibrePlugin/src/main/kotlin/org/maplibre/CcachePlugin.kt b/platform/android/MapLibrePlugin/src/main/kotlin/org/maplibre/CcachePlugin.kt index 486d71acf..2a104bad5 100644 --- a/platform/android/MapLibrePlugin/src/main/kotlin/org/maplibre/CcachePlugin.kt +++ b/platform/android/MapLibrePlugin/src/main/kotlin/org/maplibre/CcachePlugin.kt @@ -1,23 +1,40 @@ package org.maplibre -import com.android.build.gradle.BaseExtension +import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.dsl.LibraryExtension import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.getByType import java.io.File +private fun configureCcacheArguments(arguments: MutableList) { + val cacheToolPath = findCacheToolPath() + if (cacheToolPath != null) { + arguments.add("-DCMAKE_CXX_COMPILER_LAUNCHER=$cacheToolPath") + println("ccache enabled at: $cacheToolPath") + } else { + println("ccache not found on the system, continuing without it.") + } +} + fun configureCcache(project: Project) { - project.extensions.getByType().run { - defaultConfig { + val appExtension = project.extensions.findByType(ApplicationExtension::class.java) + if (appExtension != null) { + appExtension.defaultConfig { externalNativeBuild { cmake { - val cacheToolPath = findCacheToolPath() - if (cacheToolPath != null) { - arguments.add("-DCMAKE_CXX_COMPILER_LAUNCHER=$cacheToolPath") - println("ccache enabled at: $cacheToolPath") - } else { - println("ccache not found on the system, continuing without it.") - } + configureCcacheArguments(arguments) + } + } + } + return + } + + val libraryExtension = project.extensions.findByType(LibraryExtension::class.java) + if (libraryExtension != null) { + libraryExtension.defaultConfig { + externalNativeBuild { + cmake { + configureCcacheArguments(arguments) } } } diff --git a/platform/android/build.gradle.kts b/platform/android/build.gradle.kts index 0915ac305..3e4055168 100644 --- a/platform/android/build.gradle.kts +++ b/platform/android/build.gradle.kts @@ -1,6 +1,4 @@ plugins { alias(libs.plugins.kotlinter) apply false - alias(libs.plugins.kotlinAndroid) apply false - id("com.jaredsburrows.license") version "0.9.8" apply false id("maplibre.dependencies") } diff --git a/platform/android/buildSrc/build.gradle.kts b/platform/android/buildSrc/build.gradle.kts index 3bbc201d1..aa1fb136e 100644 --- a/platform/android/buildSrc/build.gradle.kts +++ b/platform/android/buildSrc/build.gradle.kts @@ -12,8 +12,7 @@ repositories { dependencies { implementation("com.vanniktech:gradle-dependency-graph-generator-plugin:0.3.0") implementation("com.vanniktech:gradle-maven-publish-plugin:0.34.0") - implementation("com.android.tools.build:gradle:8.6.0") - implementation("com.android.application:com.android.application.gradle.plugin:8.6.0") + implementation("com.android.application:com.android.application.gradle.plugin:9.1.1") implementation("commons-collections:commons-collections:3.2.2") implementation("io.sentry:sentry-android-gradle-plugin:5.9.0") } diff --git a/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt b/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt index ff34fe36c..0190fe84b 100644 --- a/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt +++ b/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt @@ -1,7 +1,7 @@ -import com.android.build.gradle.BaseExtension +import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.dsl.LibraryExtension import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.getByType open class DownloadVulkanValidationPlugin : Plugin { @@ -10,10 +10,23 @@ open class DownloadVulkanValidationPlugin : Plugin { } } -internal fun Project.configureVulkanJniLibs() = this.extensions.getByType().run { - sourceSets { - getByName("vulkan") { - jniLibs.srcDir(tasks.named("unzip").get().outputs.files.asFileTree) +internal fun Project.configureVulkanJniLibs() { + val appExtension = extensions.findByType(ApplicationExtension::class.java) + if (appExtension != null) { + appExtension.sourceSets { + getByName("vulkan") { + jniLibs.srcDir(tasks.named("unzip").get().outputs.files.asFileTree) + } + } + return + } + + val libraryExtension = extensions.findByType(LibraryExtension::class.java) + if (libraryExtension != null) { + libraryExtension.sourceSets { + getByName("vulkan") { + jniLibs.srcDir(tasks.named("unzip").get().outputs.files.asFileTree) + } } } } diff --git a/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt b/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt index ebf85d436..17ee754b6 100644 --- a/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt +++ b/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt @@ -1,8 +1,7 @@ -import com.android.build.gradle.BaseExtension +import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.dsl.LibraryExtension import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.getByType -import java.io.File open class NativeBuildPlugin : Plugin { override fun apply(project: Project) { @@ -19,8 +18,7 @@ open class NativeBuildExtension { } fun Project.nativeBuild(nativeTargets: List) = - this.extensions.getByType().run { - + run { // We sometimes want to invoke Gradle without building a native dependency, e.g. when we just want // to invoke the Java tests. When we explicitly specify an ABI of 'none', no native dependencies are // added. When another ABI is specified explicitly, we're just going to build that ABI. In all other @@ -32,65 +30,112 @@ fun Project.nativeBuild(nativeTargets: List) = // When building from Android Studio, gradle.properties sets `android.buildOnlyTargetAbi=true` so that // only the architecture for the device you're running on gets built. - var abi = "all" if (!project.hasProperty("android.injected.invoked.from.ide") && project.hasProperty("maplibre.abis")) { abi = project.property("maplibre.abis") as String } - if (abi != "none") { - externalNativeBuild { - cmake { - path = file("../MapLibreAndroid/src/cpp/CMakeLists.txt") - version = Versions.cmakeVersion - } - } - } - - // Determine the C++ STL being used. var stl = "c++_static" if (project.hasProperty("mapbox.stl")) { stl = project.property("mapbox.stl") as String } - defaultConfig { - if (abi != "none") { - externalNativeBuild { - cmake { - arguments.addAll( - listOf( - "-DANDROID_TOOLCHAIN=clang", - "-DANDROID_STL=$stl", - "-DANDROID_CPP_FEATURES=exceptions", - "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" - ) - ) + fun configureNativeBuildBlock(setup: () -> Unit) { + setup() + } - cFlags.add("-Qunused-arguments") - cppFlags.add("-Qunused-arguments") - - for (target in nativeTargets) { - targets(target) + val appExtension = extensions.findByType(ApplicationExtension::class.java) + if (appExtension != null) { + configureNativeBuildBlock { + if (abi != "none") { + appExtension.externalNativeBuild { + cmake { + path = file("../MapLibreAndroid/src/cpp/CMakeLists.txt") + version = Versions.cmakeVersion } + } + } - if (abi != "all") { - abiFilters.addAll(abi.split(" ")) - } else { - if (project.hasProperty("android.injected.invoked.from.ide") && project.hasProperty( - "android.injected.build.abi" - ) - ) { - abi = project.property("android.injected.build.abi") as String - abiFilters.add(abi.split(",").first()) - } else { - abiFilters.addAll( + appExtension.defaultConfig { + if (abi != "none") { + externalNativeBuild { + cmake { + arguments.addAll( listOf( - "armeabi-v7a", - "x86", - "arm64-v8a", - "x86_64" + "-DANDROID_TOOLCHAIN=clang", + "-DANDROID_STL=$stl", + "-DANDROID_CPP_FEATURES=exceptions", + "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ) ) + + cFlags.add("-Qunused-arguments") + cppFlags.add("-Qunused-arguments") + + for (target in nativeTargets) { + targets(target) + } + + if (abi != "all") { + abiFilters.addAll(abi.split(" ")) + } else { + if (project.hasProperty("android.injected.invoked.from.ide") && project.hasProperty("android.injected.build.abi")) { + abi = project.property("android.injected.build.abi") as String + abiFilters.add(abi.split(",").first()) + } else { + abiFilters.addAll(listOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64")) + } + } + } + } + } + } + } + return + } + + val libraryExtension = extensions.findByType(LibraryExtension::class.java) + if (libraryExtension != null) { + configureNativeBuildBlock { + if (abi != "none") { + libraryExtension.externalNativeBuild { + cmake { + path = file("../MapLibreAndroid/src/cpp/CMakeLists.txt") + version = Versions.cmakeVersion + } + } + } + + libraryExtension.defaultConfig { + if (abi != "none") { + externalNativeBuild { + cmake { + arguments.addAll( + listOf( + "-DANDROID_TOOLCHAIN=clang", + "-DANDROID_STL=$stl", + "-DANDROID_CPP_FEATURES=exceptions", + "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + ) + ) + + cFlags.add("-Qunused-arguments") + cppFlags.add("-Qunused-arguments") + + for (target in nativeTargets) { + targets(target) + } + + if (abi != "all") { + abiFilters.addAll(abi.split(" ")) + } else { + if (project.hasProperty("android.injected.invoked.from.ide") && project.hasProperty("android.injected.build.abi")) { + abi = project.property("android.injected.build.abi") as String + abiFilters.add(abi.split(",").first()) + } else { + abiFilters.addAll(listOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64")) + } + } } } } diff --git a/platform/android/buildSrc/src/main/kotlin/SentryConfigPlugin.kt b/platform/android/buildSrc/src/main/kotlin/SentryConfigPlugin.kt index e82fc708a..b5facbed5 100644 --- a/platform/android/buildSrc/src/main/kotlin/SentryConfigPlugin.kt +++ b/platform/android/buildSrc/src/main/kotlin/SentryConfigPlugin.kt @@ -1,9 +1,14 @@ import com.android.build.gradle.AppExtension -import java.io.ByteArrayOutputStream +import javax.inject.Inject import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.process.ExecOperations +import java.io.ByteArrayOutputStream + +abstract class SentryConditionalPlugin @Inject constructor( + private val execOperations: ExecOperations +) : Plugin { -class SentryConditionalPlugin : Plugin { override fun apply(project: Project) { val sentryProject = System.getenv("SENTRY_PROJECT") @@ -67,7 +72,7 @@ class SentryConditionalPlugin : Plugin { project.afterEvaluate { val commitHash = ByteArrayOutputStream() - project.exec { + execOperations.exec { commandLine("git", "rev-parse", "HEAD") standardOutput = commitHash workingDir = project.rootDir @@ -75,7 +80,8 @@ class SentryConditionalPlugin : Plugin { } androidExtension.applicationVariants.forEach { variant -> - variant.mergedFlavor.manifestPlaceholders["SENTRY_ENV"] = "${variant.name}-$commitHash" + variant.mergedFlavor.manifestPlaceholders["SENTRY_ENV"] = + "${variant.name}-${commitHash.toString().trim()}" } } } diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts index b1a8ca841..f5c329aab 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts @@ -1,18 +1,28 @@ +import org.gradle.process.ExecOperations +import javax.inject.Inject + plugins { id("maplibre.dependencies") } -tasks.register("androidNitpick") { - doLast { - println("Running android nitpick script") - verifyLicenseGeneration() +abstract class AndroidNitpickTask @Inject constructor( + private val execOperations: ExecOperations +) : DefaultTask() { + + @get:Internal + abstract val workingDirectory: DirectoryProperty + + @TaskAction + fun run() { + logger.lifecycle("Running android nitpick script") + logger.lifecycle("Verify license generation with git diff...") + execOperations.exec { + workingDir = workingDirectory.get().asFile + commandLine("python3", "scripts/validate-license.py") + } } } -fun verifyLicenseGeneration() { - println("Verify license generation with git diff...") - exec { - workingDir(rootDir) - commandLine("python3", "scripts/validate-license.py") - } +tasks.register("androidNitpick") { + workingDirectory.set(rootDir) } diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts index 86ed54454..3a72a111e 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts @@ -1,4 +1,8 @@ +import com.android.build.api.dsl.LibraryExtension +import com.android.build.api.variant.LibraryAndroidComponentsExtension import org.gradle.api.Task +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.external.javadoc.StandardJavadocDocletOptions import org.gradle.kotlin.dsl.get import java.util.Locale @@ -10,6 +14,15 @@ plugins { id("maplibre.artifact-settings") } +val androidComponents = extensions.getByType() +val androidLibrary = extensions.getByType() + +androidLibrary.publishing { + singleVariant("vulkanRelease") + singleVariant("vulkanDebug") + singleVariant("openglRelease") + singleVariant("openglDebug") +} afterEvaluate { mavenPublishing { @@ -32,22 +45,23 @@ gradle.projectsEvaluated { } tasks.register("androidJavadocs") { - source = fileTree(android.sourceSets.getByName("main").java.srcDirs) - classpath = files(android.bootClasspath) + source = fileTree("src/main/java") + classpath = files() isFailOnError = false } tasks.register("androidJavadocsJar") { archiveClassifier.set("javadoc") - from(tasks.named("androidJavadocs", Javadoc::class.java).get().destinationDir) + from(tasks.named("androidJavadocs", Javadoc::class.java).map { it.destinationDir!! }) + dependsOn(tasks.named("androidJavadocs")) } tasks.register("androidSourcesJar") { archiveClassifier.set("sources") - from(android.sourceSets.getByName("main").java.srcDirs) + from("src/main/java") } -tasks.withType { +tasks.withType().configureEach { options.encoding = "UTF-8" (options as StandardJavadocDocletOptions).apply { charSet = "UTF-8" @@ -55,7 +69,6 @@ tasks.withType { } } - artifacts { add("archives", tasks.named("androidSourcesJar")) add("archives", tasks.named("androidJavadocsJar")) @@ -80,7 +93,17 @@ fun configureMavenPublication( artifactId = "${project.extra["mapLibreArtifactId"]}$artifactIdPostfix" version = project.version.toString() - from(components["${renderer}${buildType}"]) + val componentName = "${renderer}${buildType}" + val component = components.findByName(componentName) + ?: components.find { it.name.equals(componentName, ignoreCase = true) } + if (component != null) { + from(component) + } else { + project.logger.warn( + "Skipping publication '$publicationName' because component '$componentName' was not found. " + + "Available components: ${components.map { it.name }.sorted()}" + ) + } pom { name.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") @@ -110,7 +133,6 @@ fun configureMavenPublication( } } - afterEvaluate { configureMavenPublication("vulkan", "defaultrelease", "", "") configureMavenPublication("vulkan", "defaultdebug", "-debug", " (Debug)", "Debug") @@ -123,13 +145,20 @@ afterEvaluate { configureMavenPublication("opengl", "opengldebug", "-opengl-debug", " (OpenGL ES, Debug)", "Debug") } +// Wire per-variant compile classpaths into the Javadoc task. +// Replaces the removed `android.libraryVariants` API with the new AndroidComponents API, +// looking up the generated JavaCompile task by its conventional name. +androidComponents.onVariants { variant -> + val capitalizedName = variant.name.replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() + } + val javaCompileTaskName = "compile${capitalizedName}JavaWithJavac" -afterEvaluate { - android.libraryVariants.forEach { variant -> - tasks.named("androidJavadocs", Javadoc::class.java).configure { - doFirst { - classpath = classpath.plus(files(variant.javaCompileProvider.get().classpath)) - } + tasks.named("androidJavadocs", Javadoc::class.java).configure { + val javaCompile = tasks.named(javaCompileTaskName, JavaCompile::class.java) + dependsOn(javaCompile) + doFirst { + classpath = classpath.plus(files(javaCompile.get().classpath)) } } } diff --git a/platform/android/gradle.properties b/platform/android/gradle.properties index 0eb9ba9bd..1b0794654 100644 --- a/platform/android/gradle.properties +++ b/platform/android/gradle.properties @@ -3,7 +3,7 @@ systemProp.org.gradle.internal.http.connectionTimeout=360000 systemProp.org.gradle.internal.http.socketTimeout=360000 org.gradle.jvmargs=-Xmx4096M android.nonTransitiveRClass=false -android.nonFinalResIds=false +android.nonFinalResIds=true android.injected.androidTest.leaveApksInstalledAfterRun=true org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true diff --git a/platform/android/gradle/libs.versions.toml b/platform/android/gradle/libs.versions.toml index 8f611f99e..cd508d682 100644 --- a/platform/android/gradle/libs.versions.toml +++ b/platform/android/gradle/libs.versions.toml @@ -1,33 +1,30 @@ [versions] mapLibreServices = "6.0.1" -constraintLayout = "2.1.4" +constraintLayout = "2.2.1" interpolator = "1.0.0" -recyclerView = "1.3.2" -material = "1.12.0" +recyclerView = "1.3.0" +material = "1.13.0" uiAutomator = "2.3.0" -espresso = "3.6.1" -testRunner = "1.2.1" -testRules = "1.6.1" -fragment = "1.8.2" +espresso = "3.7.0" +testRunner = "1.3.0" +testRules = "1.7.0" +fragment = "1.8.9" annotation = "1.8.2" +androidxPrint = "1.1.0" leakCanary = "2.14" junit = "4.13.2" -mockito = "5.13.0" -mockk = "1.13.12" -robolectric = "4.13" +mockito = "5.23.0" +mockk = "1.14.9" +robolectric = "4.16.1" timber = "5.0.1" okhttp = "4.12.0" -kotlin = "2.0.20" -licenses = "0.9.8" -lint = "31.6.0" +kotlin = "2.3.20" +lint = "32.1.1" appcenter = "1.5" -commonsIO = "2.16.1" -assertj = "3.26.3" -gradleNexus = "2.0.0" +commonsIO = "2.21.0" +assertj = "3.27.7" multidex = "2.0.1" -kotlinxCoroutines = { strictly = "[1.0, 2.0[" } - -androidGradlePlugin = "8.6.0" +kotlinxCoroutines = "1.10.2" [libraries] kotlinxCoroutinesCore = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } @@ -57,6 +54,7 @@ supportConstraintLayout = { group = "androidx.constraintlayout", name = "constra interpolator = { group = "androidx.interpolator", name = "interpolator", version.ref = "interpolator" } supportDesign = { group = "com.google.android.material", name = "material", version.ref = "material" } multidex = { group = "androidx.multidex", name = "multidex", version.ref = "multidex" } +supportPrint = { group = "androidx.print", name = "print", version.ref = "androidxPrint" } appCenter = { group = "com.microsoft.appcenter", name = "espresso-test-extension", version.ref = "appcenter" } commonsIO = { group = "commons-io", name = "commons-io", version.ref = "commonsIO" } @@ -64,28 +62,16 @@ timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "tim okhttp3 = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } leakCanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakCanary" } -kotlinPlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } -licensesPlugin = { group = "com.jaredsburrows", name = "gradle-license-plugin", version.ref = "licenses" } - lint = { group = "com.android.tools.lint", name = "lint", version.ref = "lint" } lintApi = { group = "com.android.tools.lint", name = "lint-api", version.ref = "lint" } lintChecks = { group = "com.android.tools.lint", name = "lint-checks", version.ref = "lint" } lintTests = { group = "com.android.tools.lint", name = "lint-tests", version.ref = "lint" } -gradleNexus = { group = "io.github.gradle-nexus", name = "publish-plugin", version.ref = "gradleNexus" } - -androidxTestExtJUnit = { group = "androidx.test.ext", name = "junit", version = "1.2.1" } -androidxTestCoreKtx = { group = "androidx.test", name = "core-ktx", version = "1.6.1" } -kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version = "1.7.2" } - -androidGradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } - +androidxTestExtJUnit = { group = "androidx.test.ext", name = "junit", version = "1.3.0" } +androidxTestCoreKtx = { group = "androidx.test", name = "core-ktx", version = "1.7.0" } +kotlinxSerializationJson = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version = "1.11.0" } [plugins] -nexusPublishPlugin = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" } -kotlinter = { id = "org.jmailen.kotlinter", version = "4.4.1" } -kotlinAndroid = { id = "org.jetbrains.kotlin.android", version = "2.0.20" } -dokka = { id = "org.jetbrains.dokka", version = "2.0.0-Beta" } -kotlinPluginSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "2.0.20" } -android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } -android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } +kotlinter = { id = "org.jmailen.kotlinter", version = "5.4.2" } +dokka = { id = "org.jetbrains.dokka", version = "2.2.0" } +kotlinPluginSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index aaaabb3cb..37f78a6af 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/platform/android/src/test/benchmark_runner.cpp b/platform/android/src/test/benchmark_runner.cpp index 8fbc94b20..5f9327f5e 100644 --- a/platform/android/src/test/benchmark_runner.cpp +++ b/platform/android/src/test/benchmark_runner.cpp @@ -59,7 +59,7 @@ void android_main(struct android_app* app) { struct android_poll_source* source = nullptr; while (true) { - ALooper_pollAll(-1, &outFd, &outEvents, reinterpret_cast(&source)); + ALooper_pollOnce(-1, &outFd, &outEvents, reinterpret_cast(&source)); if (source != nullptr) { source->process(app, source); } diff --git a/platform/android/src/test/test_runner.cpp b/platform/android/src/test/test_runner.cpp index c4ea490a5..aa0afc5c9 100644 --- a/platform/android/src/test/test_runner.cpp +++ b/platform/android/src/test/test_runner.cpp @@ -105,7 +105,7 @@ void android_main(struct android_app* app) { struct android_poll_source* source = nullptr; while (true) { - ALooper_pollAll(-1, &outFd, &outEvents, reinterpret_cast(&source)); + ALooper_pollOnce(-1, &outFd, &outEvents, reinterpret_cast(&source)); if (source != nullptr) { source->process(app, source); } diff --git a/render-test/android/build.gradle.kts b/render-test/android/build.gradle.kts index 34d6e8493..568d21129 100644 --- a/render-test/android/build.gradle.kts +++ b/render-test/android/build.gradle.kts @@ -1,3 +1,3 @@ plugins { - id("com.android.application") version "8.6.0" apply false + id("com.android.application") version "9.1.1" apply false } diff --git a/render-test/android/gradle/libs.versions.toml b/render-test/android/gradle/libs.versions.toml index ee2482d6c..b8fb86222 100644 --- a/render-test/android/gradle/libs.versions.toml +++ b/render-test/android/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -androidGradlePlugin = "8.6.0" +androidGradlePlugin = "8.13.2" espresso = "3.6.1" [libraries] diff --git a/render-test/android/gradle/wrapper/gradle-wrapper.properties b/render-test/android/gradle/wrapper/gradle-wrapper.properties index de413606b..5f38436fc 100644 --- a/render-test/android/gradle/wrapper/gradle-wrapper.properties +++ b/render-test/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/test/android/build.gradle.kts b/test/android/build.gradle.kts index 34d6e8493..568d21129 100644 --- a/test/android/build.gradle.kts +++ b/test/android/build.gradle.kts @@ -1,3 +1,3 @@ plugins { - id("com.android.application") version "8.6.0" apply false + id("com.android.application") version "9.1.1" apply false } diff --git a/test/android/gradle/wrapper/gradle-wrapper.properties b/test/android/gradle/wrapper/gradle-wrapper.properties index de413606b..5f38436fc 100644 --- a/test/android/gradle/wrapper/gradle-wrapper.properties +++ b/test/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME