Fix warnings in FGP (#166727)
Fixes/suppresses all warnings: 1. Fixes https://github.com/flutter/flutter/issues/162695 2. Suppresses warnings about the various `*Variant*` imports that we use being deprecated, with comments linking to https://github.com/flutter/flutter/issues/166550 to migrate to the variant api. 3. Fixes some unused elvis operators and unneeded types provided for declarations that AGP complains about, e.g. `val fooString: String = "a string"`, and use of deprecated string related methods. 4. Follows up on https://github.com/flutter/flutter/pull/166277, as we were getting a warning mentioned in this comment https://github.com/flutter/flutter/pull/166277#issuecomment-2780184486. 5. Suppresses some warnings about unused code where the analysis couldn't properly detect it being used (i.e., it isn't unused) (4) is more opinionated, let me know if you think it should be done in a follow up. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Gray Mackall <mackall@google.com>
This commit is contained in:
parent
a2cb910f83
commit
e2dea95082
@ -157,14 +157,7 @@ Future<void> main() async {
|
||||
|
||||
final String defaultPath = path.join(project.rootPath, 'android', 'app', '.cxx');
|
||||
|
||||
final String modifiedPath = path.join(
|
||||
project.rootPath,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'flutter',
|
||||
'.cxx',
|
||||
);
|
||||
final String modifiedPath = path.join(project.rootPath, 'build', '.cxx');
|
||||
if (Directory(defaultPath).existsSync()) {
|
||||
throw TaskResult.failure('Producing unexpected build artifacts in $defaultPath');
|
||||
}
|
||||
|
@ -19,16 +19,6 @@ tasks.validatePlugins {
|
||||
enableStricterValidation.set(true)
|
||||
}
|
||||
|
||||
// We need to compile Kotlin first so we can call it from Groovy. See https://stackoverflow.com/q/36214437/7009800
|
||||
tasks.withType<GroovyCompile> {
|
||||
dependsOn(tasks.compileKotlin)
|
||||
classpath += files(tasks.compileKotlin.get().destinationDirectory)
|
||||
}
|
||||
|
||||
tasks.classes {
|
||||
dependsOn(tasks.compileGroovy)
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
// The "flutterPlugin" name isn't used anywhere.
|
||||
|
@ -10,10 +10,10 @@ import kotlinx.serialization.json.put
|
||||
|
||||
// TODO(gmackall): Identify which of these can be val instead of var.
|
||||
class Deeplink(
|
||||
var scheme: String?,
|
||||
var host: String?,
|
||||
private var scheme: String?,
|
||||
private var host: String?,
|
||||
var path: String?,
|
||||
var intentFilterCheck: IntentFilterCheck
|
||||
private var intentFilterCheck: IntentFilterCheck
|
||||
) {
|
||||
// TODO(gmackall): This behavior was kept identical to the original Groovy behavior as part of
|
||||
// the Groovy->Kotlin conversion, but should be changed once the conversion is complete.
|
||||
|
@ -22,6 +22,7 @@ private const val FLUTTER_SDK_PATH = "flutterSdkPath"
|
||||
* This plugin applies the native plugin loader plugin (../scripts/native_plugin_loader.gradle.kts)
|
||||
* and then configures the main project to `include` each of the loaded flutter plugins.
|
||||
*/
|
||||
@Suppress("unused") // This class is used by packages/flutter_tools/gradle/build.gradle.kts.
|
||||
class FlutterAppPluginLoaderPlugin : Plugin<Settings> {
|
||||
override fun apply(settings: Settings) {
|
||||
val flutterProjectRoot: File = settings.settingsDir.parentFile
|
||||
|
@ -17,6 +17,7 @@ import org.gradle.api.GradleException
|
||||
* Learn more about extensions in Gradle:
|
||||
* * https://docs.gradle.org/8.0.2/userguide/custom_plugins.html#sec:getting_input_from_the_build
|
||||
*/
|
||||
@Suppress("unused") // The values in this class are used in Flutter developers app-level build.gradle file.
|
||||
open class FlutterExtension {
|
||||
/** Sets the compileSdkVersion used by default in Flutter app projects. */
|
||||
val compileSdkVersion: Int = 35
|
||||
|
@ -4,14 +4,10 @@
|
||||
|
||||
package com.flutter.gradle
|
||||
|
||||
import com.android.build.VariantOutput
|
||||
import com.android.build.api.dsl.ApplicationExtension
|
||||
import com.android.build.gradle.AbstractAppExtension
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
import com.android.build.gradle.api.ApkVariantOutput
|
||||
import com.android.build.gradle.api.BaseVariant
|
||||
import com.android.build.gradle.api.BaseVariantOutput
|
||||
import com.android.build.gradle.tasks.PackageAndroidArtifact
|
||||
import com.android.build.gradle.tasks.ProcessAndroidResources
|
||||
import com.flutter.gradle.FlutterPluginUtils.readPropertiesIfExist
|
||||
@ -27,6 +23,8 @@ import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
import org.gradle.process.ExecOperations
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Paths
|
||||
@ -54,7 +52,7 @@ class FlutterPlugin : Plugin<Project> {
|
||||
|
||||
val flutterRootSystemVal: String? = System.getenv("FLUTTER_ROOT")
|
||||
val flutterRootPath: String =
|
||||
resolveProperty("flutter.sdk", flutterRootSystemVal)
|
||||
resolveFlutterSdkProperty(flutterRootSystemVal)
|
||||
?: throw GradleException(
|
||||
"Flutter SDK not found. Define location with flutter.sdk in the " +
|
||||
"local.properties file or with a FLUTTER_ROOT environment variable."
|
||||
@ -145,7 +143,7 @@ class FlutterPlugin : Plugin<Project> {
|
||||
isUniversalApk = false
|
||||
}
|
||||
}
|
||||
val propDeferredComponentNames: String = "deferred-component-names"
|
||||
val propDeferredComponentNames = "deferred-component-names"
|
||||
val deferredComponentNamesValue: String? =
|
||||
project.findProperty(propDeferredComponentNames) as? String
|
||||
if (deferredComponentNamesValue != null) {
|
||||
@ -280,10 +278,8 @@ class FlutterPlugin : Plugin<Project> {
|
||||
private fun getExecutableNameForPlatform(baseExecutableName: String): String =
|
||||
if (OperatingSystem.current().isWindows) "$baseExecutableName.bat" else baseExecutableName
|
||||
|
||||
private fun resolveProperty(
|
||||
propertyName: String,
|
||||
defaultValue: String?
|
||||
): String? {
|
||||
private fun resolveFlutterSdkProperty(defaultValue: String?): String? {
|
||||
val propertyName = "flutter.sdk"
|
||||
if (localProperties == null) {
|
||||
localProperties =
|
||||
readPropertiesIfExist(File(project!!.projectDir.parentFile, "local.properties"))
|
||||
@ -300,7 +296,8 @@ class FlutterPlugin : Plugin<Project> {
|
||||
rootProject.subprojects.forEach { subproject ->
|
||||
val gradlew: String =
|
||||
getExecutableNameForPlatform("${rootProject.projectDir}/gradlew")
|
||||
rootProject.exec {
|
||||
val execOps = rootProject.serviceOf<ExecOperations>()
|
||||
execOps.exec {
|
||||
workingDir(rootProject.projectDir)
|
||||
executable(gradlew)
|
||||
args(":${subproject.name}:dependencies", "--write-locks")
|
||||
@ -342,11 +339,18 @@ class FlutterPlugin : Plugin<Project> {
|
||||
}
|
||||
val copyFlutterAssetsTask: Task =
|
||||
addFlutterDeps(variant, flutterPlugin, targetPlatforms)
|
||||
val variantOutput: BaseVariantOutput = variant.outputs.first()
|
||||
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
val variantOutput: com.android.build.gradle.api.BaseVariantOutput = variant.outputs.first()
|
||||
val processResources: ProcessAndroidResources =
|
||||
try {
|
||||
variantOutput.processResourcesProvider.get()
|
||||
} catch (e: UnknownTaskException) {
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
variantOutput.processResources
|
||||
}
|
||||
processResources.dependsOn(copyFlutterAssetsTask)
|
||||
@ -361,19 +365,26 @@ class FlutterPlugin : Plugin<Project> {
|
||||
// * `build-mode` can be `release|debug|profile`.
|
||||
variant.outputs.forEach { output ->
|
||||
assembleTask.doLast {
|
||||
output as ApkVariantOutput
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
output as com.android.build.gradle.api.ApkVariantOutput
|
||||
val packageApplicationProvider: PackageAndroidArtifact =
|
||||
variant.packageApplicationProvider.get()
|
||||
val outputDirectory: Directory =
|
||||
packageApplicationProvider.outputDirectory.get()
|
||||
val outputDirectoryStr: String = outputDirectory.toString()
|
||||
var filename = "app"
|
||||
val abi = output.getFilter(VariantOutput.FilterType.ABI)
|
||||
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
val abi = output.getFilter(com.android.build.VariantOutput.FilterType.ABI)
|
||||
if (abi != null && abi.isNotEmpty()) {
|
||||
filename += "-$abi"
|
||||
}
|
||||
if (variant.flavorName != null && variant.flavorName.isNotEmpty()) {
|
||||
filename += "-${variant.flavorName.toLowerCase()}"
|
||||
filename += "-${FlutterPluginUtils.lowercase(variant.flavorName)}"
|
||||
}
|
||||
filename += "-${FlutterPluginUtils.buildModeFor(variant.buildType)}"
|
||||
projectToAddTasksTo.copy {
|
||||
@ -395,13 +406,13 @@ class FlutterPlugin : Plugin<Project> {
|
||||
// This path is not flavor specific and must only be added once.
|
||||
// If support for flavors is added to native assets, then they must only be added
|
||||
// once per flavor; see https://github.com/dart-lang/native/issues/1359.
|
||||
val nativeAssetsDir: String =
|
||||
val nativeAssetsDir =
|
||||
"${projectToAddTasksTo.layout.buildDirectory.get()}/../native_assets/android/jniLibs/lib/"
|
||||
android.sourceSets
|
||||
.getByName("main")
|
||||
.jniLibs
|
||||
.srcDir(nativeAssetsDir)
|
||||
getPluginHandler(projectToAddTasksTo!!).configurePlugins(engineVersion!!)
|
||||
getPluginHandler(projectToAddTasksTo).configurePlugins(engineVersion!!)
|
||||
FlutterPluginUtils.detectLowCompileSdkVersionOrNdkVersion(
|
||||
projectToAddTasksTo,
|
||||
getPluginHandler(projectToAddTasksTo).getPluginList()
|
||||
@ -469,10 +480,12 @@ class FlutterPlugin : Plugin<Project> {
|
||||
flutterPlugin,
|
||||
targetPlatforms
|
||||
)
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
val mergeAssets =
|
||||
projectToAddTasksTo
|
||||
.tasks
|
||||
.findByPath(":$hostAppProjectName:merge${appProjectVariant.name.capitalize()}Assets")
|
||||
.findByPath(":$hostAppProjectName:merge${FlutterPluginUtils.capitalize(appProjectVariant.name)}Assets")
|
||||
check(mergeAssets != null)
|
||||
mergeAssets.dependsOn(copyFlutterAssetsTask)
|
||||
}
|
||||
@ -502,7 +515,7 @@ class FlutterPlugin : Plugin<Project> {
|
||||
* be sure to change any instances of this string in symbols in the code below
|
||||
* to match.
|
||||
*/
|
||||
const val FLUTTER_BUILD_PREFIX: String = "flutterBuild"
|
||||
private const val FLUTTER_BUILD_PREFIX: String = "flutterBuild"
|
||||
|
||||
/**
|
||||
* Finds a task by name, returning null if the task does not exist.
|
||||
@ -517,8 +530,10 @@ class FlutterPlugin : Plugin<Project> {
|
||||
null
|
||||
}
|
||||
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
private fun addFlutterDeps(
|
||||
variant: BaseVariant,
|
||||
@Suppress("DEPRECATION") variant: com.android.build.gradle.api.BaseVariant,
|
||||
flutterPlugin: FlutterPlugin,
|
||||
targetPlatforms: List<String>
|
||||
): Task {
|
||||
@ -559,9 +574,15 @@ class FlutterPlugin : Plugin<Project> {
|
||||
if (FlutterPluginUtils.shouldProjectSplitPerAbi(project)) {
|
||||
variant.outputs.forEach { output ->
|
||||
// need to force this as the API does not return the right thing for our use.
|
||||
output as ApkVariantOutput
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
output as com.android.build.gradle.api.ApkVariantOutput
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
val filterIdentifier: String =
|
||||
output.getFilter(VariantOutput.FilterType.ABI)
|
||||
output.getFilter(com.android.build.VariantOutput.FilterType.ABI)
|
||||
val abiVersionCode: Int? = FlutterPluginConstants.ABI_VERSION[filterIdentifier]
|
||||
if (abiVersionCode != null) {
|
||||
output.versionCodeOverride
|
||||
@ -647,8 +668,8 @@ class FlutterPlugin : Plugin<Project> {
|
||||
project.layout.buildDirectory.dir("${FlutterPluginConstants.INTERMEDIATES_DIR}/flutter/${variant.name}/libs.jar")
|
||||
)
|
||||
val packJniLibsTaskProvider: TaskProvider<Jar> =
|
||||
project.tasks.register<Jar>(
|
||||
"packJniLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}",
|
||||
project.tasks.register(
|
||||
"packJniLibs${FLUTTER_BUILD_PREFIX}${FlutterPluginUtils.capitalize(variant.name)}",
|
||||
Jar::class.java
|
||||
) {
|
||||
destinationDirectory.set(libJar.parentFile)
|
||||
@ -663,9 +684,9 @@ class FlutterPlugin : Plugin<Project> {
|
||||
}
|
||||
// Copy the native assets created by build.dart and placed in build/native_assets by flutter assemble.
|
||||
// The `$project.layout.buildDirectory` is '.android/Flutter/build/' instead of 'build/'.
|
||||
val buildDir: String =
|
||||
val buildDir =
|
||||
"${FlutterPluginUtils.getFlutterSourceDirectory(project)}/build"
|
||||
val nativeAssetsDir: String =
|
||||
val nativeAssetsDir =
|
||||
"$buildDir/native_assets/android/jniLibs/lib"
|
||||
from("$nativeAssetsDir/$abi") {
|
||||
include("*.so")
|
||||
@ -683,13 +704,14 @@ class FlutterPlugin : Plugin<Project> {
|
||||
)
|
||||
val copyFlutterAssetsTaskProvider: TaskProvider<Copy> =
|
||||
project.tasks.register(
|
||||
"copyFlutterAssets${variant.name.capitalize()}",
|
||||
"copyFlutterAssets${FlutterPluginUtils.capitalize(variant.name)}",
|
||||
Copy::class.java
|
||||
) {
|
||||
dependsOn(compileTask)
|
||||
with(compileTask.assets)
|
||||
// TODO(gmackall): Replace with filePermissions.user.read/write = true once
|
||||
// minimum supported Gradle version is 8.3.
|
||||
@Suppress("DEPRECATION")
|
||||
fileMode = 420 // corresponds to unix 0644 in base 8
|
||||
if (isUsedAsSubproject) {
|
||||
// TODO(gmackall): above is always false, can delete
|
||||
@ -701,20 +723,29 @@ class FlutterPlugin : Plugin<Project> {
|
||||
try {
|
||||
variant.mergeAssetsProvider.get()
|
||||
} catch (e: IllegalStateException) {
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
variant.mergeAssets
|
||||
}
|
||||
dependsOn(mergeAssets)
|
||||
dependsOn("clean${mergeAssets.name.capitalize()}")
|
||||
mergeAssets.mustRunAfter("clean${mergeAssets.name.capitalize()}")
|
||||
dependsOn("clean${FlutterPluginUtils.capitalize(mergeAssets.name)}")
|
||||
mergeAssets.mustRunAfter("clean${FlutterPluginUtils.capitalize(mergeAssets.name)}")
|
||||
into(mergeAssets.outputDir)
|
||||
}
|
||||
val copyFlutterAssetsTask: Task = copyFlutterAssetsTaskProvider.get()
|
||||
if (!isUsedAsSubproject) {
|
||||
val variantOutput: BaseVariantOutput = variant.outputs.first()
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
val variantOutput: com.android.build.gradle.api.BaseVariantOutput = variant.outputs.first()
|
||||
val processResources =
|
||||
try {
|
||||
variantOutput.processResourcesProvider.get()
|
||||
} catch (e: IllegalStateException) {
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
variantOutput.processResources
|
||||
}
|
||||
processResources.dependsOn(copyFlutterAssetsTask)
|
||||
@ -724,9 +755,9 @@ class FlutterPlugin : Plugin<Project> {
|
||||
// See https://docs.gradle.org/8.1/userguide/validation_problems.html#implicit_dependency.
|
||||
val tasksToCheck =
|
||||
listOf(
|
||||
"compress${variant.name.capitalize()}Assets",
|
||||
"bundle${variant.name.capitalize()}Aar",
|
||||
"bundle${variant.name.capitalize()}LocalLintAar"
|
||||
"compress${FlutterPluginUtils.capitalize(variant.name)}Assets",
|
||||
"bundle${FlutterPluginUtils.capitalize(variant.name)}Aar",
|
||||
"bundle${FlutterPluginUtils.capitalize(variant.name)}LocalLintAar"
|
||||
)
|
||||
tasksToCheck.forEach { taskTocheck ->
|
||||
try {
|
||||
|
@ -7,9 +7,6 @@ package com.flutter.gradle
|
||||
// TODO(gmackall): this should be collapsed back into the core FlutterPlugin once the Groovy to
|
||||
// kotlin conversion is complete.
|
||||
object FlutterPluginConstants {
|
||||
// Strings that define project properties
|
||||
const val PROP_PROCESS_RESOURCES_PROVIDER = "processResourcesProvider"
|
||||
|
||||
/** The platforms that can be passed to the `--Ptarget-platform` flag. */
|
||||
private const val PLATFORM_ARM32 = "android-arm"
|
||||
private const val PLATFORM_ARM64 = "android-arm64"
|
||||
@ -41,7 +38,7 @@ object FlutterPluginConstants {
|
||||
* Otherwise, the Play Store will complain that the APK variants have the same version.
|
||||
*/
|
||||
@JvmStatic val ABI_VERSION =
|
||||
mapOf<String, Int>(
|
||||
mapOf(
|
||||
ARCH_ARM32 to 1,
|
||||
ARCH_ARM64 to 2,
|
||||
ARCH_X86 to 3,
|
||||
|
@ -6,14 +6,11 @@ package com.flutter.gradle
|
||||
|
||||
import com.android.build.gradle.AbstractAppExtension
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import com.android.build.gradle.api.ApplicationVariant
|
||||
import com.android.build.gradle.api.BaseVariantOutput
|
||||
import com.android.build.gradle.tasks.ProcessAndroidResources
|
||||
import com.android.builder.model.BuildType
|
||||
import com.flutter.gradle.plugins.PluginHandler
|
||||
import groovy.lang.Closure
|
||||
import groovy.util.Node
|
||||
import groovy.util.XmlParser
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
@ -62,6 +59,13 @@ object FlutterPluginUtils {
|
||||
@Suppress("DEPRECATION")
|
||||
internal fun capitalize(string: String): String = string.capitalize()
|
||||
|
||||
// Kotlin's toLowerCase function is deprecated, but the suggested replacement is not supported
|
||||
// by the minimum version of Kotlin that we support. Centralize the use to one place, so that
|
||||
// when our minimum version does support the replacement we can replace by changing a single
|
||||
// line.
|
||||
@Suppress("DEPRECATION")
|
||||
internal fun lowercase(string: String): String = string.toLowerCase()
|
||||
|
||||
// compareTo implementation of version strings in the format of ints and periods
|
||||
// Will not crash on RC candidate strings but considers all RC candidates the same version.
|
||||
// Returns -1 if firstString < secondString, 0 if firstString == secondString, 1 if firstString > secondString
|
||||
@ -513,11 +517,8 @@ object FlutterPluginUtils {
|
||||
getCompileSdkFromProject(project).toIntOrNull() ?: Int.MAX_VALUE
|
||||
|
||||
var maxPluginCompileSdkVersion = projectCompileSdkVersion
|
||||
// TODO(gmackall): This should be updated to reflect newer templates.
|
||||
// The default for AGP 4.1.0 used in old templates.
|
||||
val ndkVersionIfUnspecified = "21.1.6352462"
|
||||
val projectNdkVersion =
|
||||
getAndroidExtension(project).ndkVersion ?: ndkVersionIfUnspecified
|
||||
getAndroidExtension(project).ndkVersion
|
||||
var maxPluginNdkVersion = projectNdkVersion
|
||||
var numProcessedPlugins = pluginList.size
|
||||
val pluginsWithHigherSdkVersion = mutableListOf<PluginVersionPair>()
|
||||
@ -543,14 +544,19 @@ object FlutterPluginUtils {
|
||||
)
|
||||
}
|
||||
val pluginNdkVersion: String =
|
||||
getAndroidExtension(pluginProject).ndkVersion ?: ndkVersionIfUnspecified
|
||||
getAndroidExtension(pluginProject).ndkVersion
|
||||
maxPluginNdkVersion =
|
||||
VersionUtils.mostRecentSemanticVersion(
|
||||
pluginNdkVersion,
|
||||
maxPluginNdkVersion
|
||||
)
|
||||
if (pluginNdkVersion != projectNdkVersion) {
|
||||
pluginsWithDifferentNdkVersion.add(PluginVersionPair(pluginName, pluginNdkVersion))
|
||||
pluginsWithDifferentNdkVersion.add(
|
||||
PluginVersionPair(
|
||||
pluginName,
|
||||
pluginNdkVersion
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
numProcessedPlugins--
|
||||
@ -614,7 +620,7 @@ object FlutterPluginUtils {
|
||||
// and rebuilt when running clean builds.
|
||||
gradleProjectAndroidExtension.externalNativeBuild.cmake.buildStagingDirectory(
|
||||
gradleProject.layout.buildDirectory
|
||||
.dir("${FlutterPluginConstants.INTERMEDIATES_DIR}/flutter/.cxx")
|
||||
.dir("../.cxx")
|
||||
.get()
|
||||
.asFile.path
|
||||
)
|
||||
@ -734,7 +740,10 @@ object FlutterPluginUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private fun findProcessResources(baseVariantOutput: BaseVariantOutput): ProcessAndroidResources =
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
private fun findProcessResources(baseVariantOutput: com.android.build.gradle.api.BaseVariantOutput): ProcessAndroidResources =
|
||||
baseVariantOutput.processResourcesProvider?.get() ?: baseVariantOutput.processResources
|
||||
|
||||
/**
|
||||
@ -769,12 +778,15 @@ object FlutterPluginUtils {
|
||||
}
|
||||
android.applicationVariants.configureEach {
|
||||
val variant = this
|
||||
project.tasks.register("output${FlutterPluginUtils.capitalize(variant.name)}AppLinkSettings") {
|
||||
project.tasks.register("output${capitalize(variant.name)}AppLinkSettings") {
|
||||
val task: Task = this
|
||||
task.description =
|
||||
"stores app links settings for the given build variant of this Android project into a json file."
|
||||
variant.outputs.configureEach {
|
||||
val baseVariantOutput: BaseVariantOutput = this
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
val baseVariantOutput: com.android.build.gradle.api.BaseVariantOutput = this
|
||||
// Deeplinks are defined in AndroidManifest.xml and is only available after
|
||||
// processResourcesProvider.
|
||||
dependsOn(findProcessResources(baseVariantOutput))
|
||||
@ -800,18 +812,21 @@ object FlutterPluginUtils {
|
||||
* @param BaseVariantOutput The output of a specific build variant (e.g., debug, release).
|
||||
* @param variant The application variant being processed.
|
||||
*/
|
||||
@Suppress("KDocUnresolvedReference")
|
||||
private fun createAppLinkSettings(
|
||||
variant: ApplicationVariant,
|
||||
baseVariantOutput: BaseVariantOutput
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION") variant: com.android.build.gradle.api.ApplicationVariant,
|
||||
@Suppress("DEPRECATION") baseVariantOutput: com.android.build.gradle.api.BaseVariantOutput
|
||||
): AppLinkSettings {
|
||||
val appLinkSettings = AppLinkSettings(variant.applicationId)
|
||||
// TODO https://github.com/flutter/flutter/issues/165881
|
||||
// Use import groovy.xml.XmlParser instead.
|
||||
|
||||
// XmlParser is not namespace aware because it makes querying nodes cumbersome.
|
||||
// TODO(gmackall): Migrate to AGPs variant api.
|
||||
// https://github.com/flutter/flutter/issues/166550
|
||||
@Suppress("DEPRECATION")
|
||||
val manifest: Node =
|
||||
XmlParser(false, false).parse(findProcessResources(baseVariantOutput).manifestFile)
|
||||
// The groovy.xml.XmlParser import would use getProperty like
|
||||
// manifest.getProperty("application").let { applicationNode -> ...
|
||||
groovy.xml.XmlParser(false, false).parse(findProcessResources(baseVariantOutput).manifestFile)
|
||||
val applicationNode: Node? =
|
||||
manifest.children().find { node ->
|
||||
node is Node && node.name() == "application"
|
||||
|
@ -26,7 +26,7 @@ object VersionUtils {
|
||||
val v2Parts = version2.split(".", "-")
|
||||
val maxSize = max(v1Parts.size, v2Parts.size)
|
||||
|
||||
for (i in 0..maxSize - 1) {
|
||||
for (i in 0 until maxSize) {
|
||||
val v1Part: String = v1Parts.getOrNull(i) ?: "0"
|
||||
val v2Part: String = v2Parts.getOrNull(i) ?: "0"
|
||||
|
||||
@ -42,7 +42,7 @@ object VersionUtils {
|
||||
return version1 // v1 is a number, v2 is not, so v1 is newer.
|
||||
v1Num == null && v2Num != null ->
|
||||
return version2 // v1 is not a number, v2 is, so v2 is newer.
|
||||
v1Num == null && v2Num == null -> { // Both are not numbers (pre-release identifiers)
|
||||
else -> { // Both are not numbers (pre-release identifiers)
|
||||
if (v1Part != v2Part) {
|
||||
return if (comparePreReleaseIdentifiers(v1Part, v2Part)) version1 else version2
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class PluginHandler(
|
||||
* This is only possible by taking all plugins into account, which
|
||||
* only appear on the `dependencyGraph` and in the `.flutter-plugins` file.
|
||||
* So in summary the plugins are currently selected from the `dependencyGraph`
|
||||
* and filtered then with the [doesSupportAndroidPlatform] method instead of
|
||||
* and filtered then with the [pluginSupportsAndroidPlatform] method instead of
|
||||
* just using the `plugins.android` list.
|
||||
*/
|
||||
private fun configureLegacyPluginEachProjects(engineVersionValue: String) {
|
||||
|
@ -132,7 +132,7 @@ open class BaseFlutterTask : DefaultTask() {
|
||||
var flavor: String? = null
|
||||
|
||||
/**
|
||||
* Gets the dependency file(s) by calling [com.flutter.gradle.BaseFlutterTaskHelper.getDependenciesFiles].
|
||||
* Gets the dependency file(s) by calling [com.flutter.gradle.tasks.BaseFlutterTaskHelper.getDependenciesFiles].
|
||||
*
|
||||
* @return the dependency file(s) based on the current intermediate directory path.
|
||||
*/
|
||||
|
@ -10,6 +10,8 @@ import org.gradle.api.GradleException
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.OutputFiles
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.process.ExecSpec
|
||||
import java.nio.file.Paths
|
||||
|
||||
@ -72,6 +74,7 @@ object BaseFlutterTaskHelper {
|
||||
.map {
|
||||
"android_aot_deferred_components_bundle_${baseFlutterTask.buildMode}_$it"
|
||||
}
|
||||
|
||||
else -> baseFlutterTask.targetPlatformValues!!.map { "android_aot_bundle_${baseFlutterTask.buildMode}_$it" }
|
||||
}
|
||||
return ruleNames
|
||||
@ -111,7 +114,17 @@ object BaseFlutterTaskHelper {
|
||||
if (!baseFlutterTask.fastStart!! || baseFlutterTask.buildMode != "debug") {
|
||||
args("-dTargetFile=${baseFlutterTask.targetPath}")
|
||||
} else {
|
||||
args("-dTargetFile=${Paths.get(baseFlutterTask.flutterRoot!!.absolutePath, "examples", "splash", "lib", "main.dart")}")
|
||||
args(
|
||||
"-dTargetFile=${
|
||||
Paths.get(
|
||||
baseFlutterTask.flutterRoot!!.absolutePath,
|
||||
"examples",
|
||||
"splash",
|
||||
"lib",
|
||||
"main.dart"
|
||||
)
|
||||
}"
|
||||
)
|
||||
}
|
||||
args("-dTargetPlatform=android")
|
||||
args("-dBuildMode=${baseFlutterTask.buildMode}")
|
||||
@ -157,6 +170,7 @@ object BaseFlutterTaskHelper {
|
||||
fun buildBundle(baseFlutterTask: BaseFlutterTask) {
|
||||
checkPreConditions(baseFlutterTask)
|
||||
baseFlutterTask.logging.captureStandardError(LogLevel.ERROR)
|
||||
baseFlutterTask.project.exec(createExecSpecActionFromTask(baseFlutterTask = baseFlutterTask))
|
||||
val execOps = baseFlutterTask.project.serviceOf<ExecOperations>()
|
||||
execOps.exec(createExecSpecActionFromTask(baseFlutterTask = baseFlutterTask))
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,10 @@ class NativePluginLoader {
|
||||
// of a federated plugin).
|
||||
val needsBuild = androidPlugin[NATIVE_BUILD_KEY] as? Boolean ?: true
|
||||
if (needsBuild) {
|
||||
nativePlugins.add(androidPlugin as Map<String, Any>) // Safe cast when adding, assuming type is now validated
|
||||
// Suppress the unchecked cast warning as we define the structure of the JSON in
|
||||
// the tool and we have already mostly validated the structure.
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
nativePlugins.add(androidPlugin as Map<String, Any>)
|
||||
}
|
||||
}
|
||||
return nativePlugins.toList() // Return immutable list
|
||||
@ -136,6 +139,9 @@ class NativePluginLoader {
|
||||
if (pluginsDependencyFile.exists()) {
|
||||
val slurper = JsonSlurper()
|
||||
val readText = slurper.parseText(pluginsDependencyFile.readText())
|
||||
|
||||
// Suppress the unchecked cast warning as we define the structure of the JSON in the tool.
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val parsedText =
|
||||
readText as? Map<String, Any>
|
||||
?: error("Parsed JSON is not a Map<String, Any>: $readText")
|
||||
|
@ -13,6 +13,8 @@ import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.logging.LoggingManager
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.process.ExecSpec
|
||||
import org.gradle.process.ProcessForkOptions
|
||||
import org.junit.jupiter.api.assertDoesNotThrow
|
||||
@ -544,7 +546,9 @@ class BaseFlutterTaskHelperTest {
|
||||
val baseFlutterTask = mockk<BaseFlutterTask>()
|
||||
val mockLoggingManager = mockk<LoggingManager>()
|
||||
val mockFile = mockk<File>()
|
||||
val mockProject = mockk<Project>()
|
||||
// Mocking the serviceOf() extension below requires us to specify this internal type
|
||||
// unfortunately.
|
||||
val mockProject = mockk<org.gradle.api.internal.project.ProjectInternal>()
|
||||
|
||||
// When baseFlutterTask.sourceDir is null, an exception is thrown. We mock its return value
|
||||
// before creating a BaseFlutterTaskHelper object.
|
||||
@ -554,7 +558,11 @@ class BaseFlutterTaskHelperTest {
|
||||
every { baseFlutterTask.logging } returns mockLoggingManager
|
||||
every { mockLoggingManager.captureStandardError(any()) } returns mockLoggingManager
|
||||
every { baseFlutterTask.project } returns mockProject
|
||||
every { mockProject.exec(any<Action<ExecSpec>>()) } returns mockk()
|
||||
val mockExecOperations = mockk<ExecOperations>()
|
||||
every {
|
||||
mockProject.serviceOf<ExecOperations>()
|
||||
} returns mockExecOperations
|
||||
every { mockExecOperations.exec(any<Action<ExecSpec>>()) } returns mockk()
|
||||
|
||||
BaseFlutterTaskHelper.buildBundle(baseFlutterTask)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user