diff --git a/dev/devicelab/bin/tasks/engine_dependency_proxy_test.dart b/dev/devicelab/bin/tasks/engine_dependency_proxy_test.dart index 9443a29bb2..49010dde83 100644 --- a/dev/devicelab/bin/tasks/engine_dependency_proxy_test.dart +++ b/dev/devicelab/bin/tasks/engine_dependency_proxy_test.dart @@ -29,14 +29,17 @@ Future main() async { await runProjectTest((FlutterProject flutterProject) async { await inDirectory(path.join(flutterProject.rootPath, 'android'), () async { section('Insert gradle testing script'); - final File build = File(path.join( - flutterProject.rootPath, 'android', 'app', 'build.gradle', - )); - build.writeAsStringSync( + final File buildFile = getAndroidBuildFile(path.join(flutterProject.rootPath, 'android')); + buildFile.writeAsStringSync( ''' -task printEngineMavenUrl() { +tasks.register("printEngineMavenUrl") { doLast { - println project.repositories.find { it.name == 'maven' }.url + project.repositories.forEach { repo -> + if (repo.name == "maven") { + repo as MavenArtifactRepository + logger.quiet(repo.url.toString()) + } + } } } ''', diff --git a/dev/devicelab/lib/framework/apk_utils.dart b/dev/devicelab/lib/framework/apk_utils.dart index a8f544ec59..e368d48a52 100644 --- a/dev/devicelab/lib/framework/apk_utils.dart +++ b/dev/devicelab/lib/framework/apk_utils.dart @@ -256,18 +256,17 @@ class FlutterProject { String get rootPath => path.join(parent.path, name); String get androidPath => path.join(rootPath, 'android'); String get iosPath => path.join(rootPath, 'ios'); + File get appBuildFile => getAndroidBuildFile(androidPath); Future addCustomBuildType(String name, {required String initWith}) async { - final File buildScript = File( - path.join(androidPath, 'app', 'build.gradle'), - ); + final File buildScript = appBuildFile; buildScript.openWrite(mode: FileMode.append).write(''' android { buildTypes { - $name { - initWith $initWith + create("$name") { + initWith(getByName("$initWith")) } } } @@ -288,14 +287,12 @@ android { } Future setMinSdkVersion(int sdkVersion) async { - final File buildScript = File( - path.join(androidPath, 'app', 'build.gradle'), - ); + final File buildScript = appBuildFile; buildScript.openWrite(mode: FileMode.append).write(''' android { defaultConfig { - minSdkVersion $sdkVersion + minSdk = $sdkVersion } } '''); @@ -308,22 +305,20 @@ android { } Future addProductFlavors(Iterable flavors) async { - final File buildScript = File( - path.join(androidPath, 'app', 'build.gradle'), - ); + final File buildScript = appBuildFile; final String flavorConfig = flavors.map((String name) { return ''' -$name { - applicationIdSuffix ".$name" - versionNameSuffix "-$name" +create("$name") { + applicationIdSuffix = ".$name" + versionNameSuffix = "-$name" } '''; }).join('\n'); buildScript.openWrite(mode: FileMode.append).write(''' android { - flavorDimensions "mode" + flavorDimensions.add("mode") productFlavors { $flavorConfig } @@ -332,9 +327,7 @@ android { } Future introduceError() async { - final File buildScript = File( - path.join(androidPath, 'app', 'build.gradle'), - ); + final File buildScript = appBuildFile; await buildScript.writeAsString((await buildScript.readAsString()).replaceAll('buildTypes', 'builTypes')); } @@ -477,3 +470,14 @@ String? validateSnapshotDependency(FlutterProject project, String expectedTarget return contentSnapshot.contains('$expectedTarget ') ? null : 'Dependency file should have $expectedTarget as target. Instead found $contentSnapshot'; } + +File getAndroidBuildFile(String androidPath) { + final File groovyFile = File(path.join(androidPath, 'app', 'build.gradle')); + final File kotlinFile = File(path.join(androidPath, 'app', 'build.gradle.kts')); + + if (groovyFile.existsSync()) { + return groovyFile; + } + + return kotlinFile; +} diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart index 1a7e2e5c2c..382e18b271 100644 --- a/packages/flutter_tools/lib/src/project.dart +++ b/packages/flutter_tools/lib/src/project.dart @@ -467,7 +467,19 @@ class AndroidProject extends FlutterProjectPlatform { static final RegExp _androidNamespacePattern = RegExp('android {[\\S\\s]+namespace\\s*=?\\s*[\'"](.+)[\'"]'); static final RegExp _applicationIdPattern = RegExp('^\\s*applicationId\\s*=?\\s*[\'"](.*)[\'"]\\s*\$'); static final RegExp _imperativeKotlinPluginPattern = RegExp('^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$'); - static final RegExp _declarativeKotlinPluginPattern = RegExp('^\\s*id\\s+[\'"]kotlin-android[\'"]\\s*\$'); + + /// Examples of strings that this regex matches: + /// - `id "kotlin-android"` + /// - `id("kotlin-android")` + /// - `id ( "kotlin-android" ) ` + /// - `id "org.jetbrains.kotlin.android"` + /// - `id("org.jetbrains.kotlin.android")` + /// - `id ( "org.jetbrains.kotlin.android" )` + static final List _declarativeKotlinPluginPatterns = [ + RegExp('^\\s*id\\s*\\(?\\s*[\'"]kotlin-android[\'"]\\s*\\)?\\s*\$'), + RegExp('^\\s*id\\s*\\(?\\s*[\'"]org.jetbrains.kotlin.android[\'"]\\s*\\)?\\s*\$'), + ]; + /// Pattern used to find the assignment of the "group" property in Gradle. /// Expected example: `group "dev.flutter.plugin"` @@ -563,7 +575,9 @@ class AndroidProject extends FlutterProjectPlatform { /// True, if the app project is using Kotlin. bool get isKotlin { final bool imperativeMatch = firstMatchInFile(appGradleFile, _imperativeKotlinPluginPattern) != null; - final bool declarativeMatch = firstMatchInFile(appGradleFile, _declarativeKotlinPluginPattern) != null; + final bool declarativeMatch = _declarativeKotlinPluginPatterns.any((RegExp pattern) { + return (firstMatchInFile(appGradleFile, pattern) != null); + }); return imperativeMatch || declarativeMatch; } diff --git a/packages/flutter_tools/templates/app_shared/android-java.tmpl/app/build.gradle.tmpl b/packages/flutter_tools/templates/app_shared/android-java.tmpl/app/build.gradle.kts.tmpl similarity index 84% rename from packages/flutter_tools/templates/app_shared/android-java.tmpl/app/build.gradle.tmpl rename to packages/flutter_tools/templates/app_shared/android-java.tmpl/app/build.gradle.kts.tmpl index 6d7ad78b1d..15700aaa43 100644 --- a/packages/flutter_tools/templates/app_shared/android-java.tmpl/app/build.gradle.tmpl +++ b/packages/flutter_tools/templates/app_shared/android-java.tmpl/app/build.gradle.kts.tmpl @@ -1,8 +1,8 @@ plugins { - id "com.android.application" - id "kotlin-android" + id("com.android.application") + id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" + id("dev.flutter.flutter-gradle-plugin") } android { @@ -16,7 +16,7 @@ android { } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 + jvmTarget = JavaVersion.VERSION_1_8.toString() } defaultConfig { @@ -34,7 +34,7 @@ android { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug + signingConfig = signingConfigs.getByName("debug") } } } diff --git a/packages/flutter_tools/templates/app_shared/android-java.tmpl/build.gradle.kts.tmpl b/packages/flutter_tools/templates/app_shared/android-java.tmpl/build.gradle.kts.tmpl new file mode 100644 index 0000000000..ffa69a07cf --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/android-java.tmpl/build.gradle.kts.tmpl @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = file("../build") +subprojects { + project.buildDir = file("${rootProject.buildDir}/${project.name}") +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.buildDir) +} diff --git a/packages/flutter_tools/templates/app_shared/android-java.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/app_shared/android-java.tmpl/build.gradle.tmpl deleted file mode 100644 index d2ffbffa4c..0000000000 --- a/packages/flutter_tools/templates/app_shared/android-java.tmpl/build.gradle.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/app/build.gradle.tmpl b/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/app/build.gradle.kts.tmpl similarity index 84% rename from packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/app/build.gradle.tmpl rename to packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/app/build.gradle.kts.tmpl index 6d7ad78b1d..15700aaa43 100644 --- a/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/app/build.gradle.tmpl +++ b/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/app/build.gradle.kts.tmpl @@ -1,8 +1,8 @@ plugins { - id "com.android.application" - id "kotlin-android" + id("com.android.application") + id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" + id("dev.flutter.flutter-gradle-plugin") } android { @@ -16,7 +16,7 @@ android { } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 + jvmTarget = JavaVersion.VERSION_1_8.toString() } defaultConfig { @@ -34,7 +34,7 @@ android { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug + signingConfig = signingConfigs.getByName("debug") } } } diff --git a/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/build.gradle.kts.tmpl b/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/build.gradle.kts.tmpl new file mode 100644 index 0000000000..ffa69a07cf --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/build.gradle.kts.tmpl @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = file("../build") +subprojects { + project.buildDir = file("${rootProject.buildDir}/${project.name}") +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.buildDir) +} diff --git a/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/build.gradle.tmpl deleted file mode 100644 index d2ffbffa4c..0000000000 --- a/packages/flutter_tools/templates/app_shared/android-kotlin.tmpl/build.gradle.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/packages/flutter_tools/templates/app_shared/android.tmpl/settings.gradle.kts.tmpl b/packages/flutter_tools/templates/app_shared/android.tmpl/settings.gradle.kts.tmpl new file mode 100644 index 0000000000..d0d44f3349 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/android.tmpl/settings.gradle.kts.tmpl @@ -0,0 +1,25 @@ +pluginManagement { + val flutterSdkPath = run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "{{agpVersion}}" apply false + id("org.jetbrains.kotlin.android") version "{{kotlinVersion}}" apply false +} + +include(":app") diff --git a/packages/flutter_tools/templates/app_shared/android.tmpl/settings.gradle.tmpl b/packages/flutter_tools/templates/app_shared/android.tmpl/settings.gradle.tmpl deleted file mode 100644 index f1272c957c..0000000000 --- a/packages/flutter_tools/templates/app_shared/android.tmpl/settings.gradle.tmpl +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "{{agpVersion}}" apply false - id "org.jetbrains.kotlin.android" version "{{kotlinVersion}}" apply false -} - -include ":app" diff --git a/packages/flutter_tools/templates/template_manifest.json b/packages/flutter_tools/templates/template_manifest.json index 98d9d70bc8..857c6dcc3e 100644 --- a/packages/flutter_tools/templates/template_manifest.json +++ b/packages/flutter_tools/templates/template_manifest.json @@ -14,13 +14,13 @@ "templates/app_shared/.idea/workspace.xml.tmpl", "templates/app_shared/.metadata.tmpl", "templates/app_shared/analysis_options.yaml.tmpl", - "templates/app_shared/android-java.tmpl/app/build.gradle.tmpl", + "templates/app_shared/android-java.tmpl/app/build.gradle.kts.tmpl", "templates/app_shared/android-java.tmpl/app/src/main/java/androidIdentifier/MainActivity.java.tmpl", - "templates/app_shared/android-java.tmpl/build.gradle.tmpl", + "templates/app_shared/android-java.tmpl/build.gradle.kts.tmpl", "templates/app_shared/android-java.tmpl/projectName_android.iml.tmpl", - "templates/app_shared/android-kotlin.tmpl/app/build.gradle.tmpl", + "templates/app_shared/android-kotlin.tmpl/app/build.gradle.kts.tmpl", "templates/app_shared/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/MainActivity.kt.tmpl", - "templates/app_shared/android-kotlin.tmpl/build.gradle.tmpl", + "templates/app_shared/android-kotlin.tmpl/build.gradle.kts.tmpl", "templates/app_shared/android-kotlin.tmpl/projectName_android.iml.tmpl", "templates/app_shared/android.tmpl/.gitignore", "templates/app_shared/android.tmpl/app/src/debug/AndroidManifest.xml.tmpl", @@ -36,7 +36,7 @@ "templates/app_shared/android.tmpl/app/src/main/res/values/styles.xml", "templates/app_shared/android.tmpl/app/src/profile/AndroidManifest.xml.tmpl", "templates/app_shared/android.tmpl/gradle.properties.tmpl", - "templates/app_shared/android.tmpl/settings.gradle.tmpl", + "templates/app_shared/android.tmpl/settings.gradle.kts.tmpl", "templates/app_shared/android.tmpl/gradle/wrapper/gradle-wrapper.properties.tmpl", "templates/app_shared/android.tmpl/settings.gradle", "templates/app_shared/ios-objc.tmpl/Runner.xcodeproj/project.pbxproj.tmpl", diff --git a/packages/flutter_tools/test/android_preview_integration.shard/flutter_build_preview_sdk_test.dart b/packages/flutter_tools/test/android_preview_integration.shard/flutter_build_preview_sdk_test.dart index 56b540b2f3..7e9c1723d9 100644 --- a/packages/flutter_tools/test/android_preview_integration.shard/flutter_build_preview_sdk_test.dart +++ b/packages/flutter_tools/test/android_preview_integration.shard/flutter_build_preview_sdk_test.dart @@ -44,7 +44,7 @@ void main() { test( 'build succeeds targeting string compileSdkVersion', () async { - final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle'); + final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle.kts'); // write a build.gradle with compileSdkVersion as `android-UpsideDownCake` which is a string preview version buildGradleFile.writeAsStringSync( buildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkVersion = "android-UpsideDownCake"'), @@ -72,7 +72,7 @@ void main() { test( 'build succeeds targeting string compileSdkPreview', () async { - final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle'); + final File buildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle.kts'); // write a build.gradle with compileSdkPreview as `UpsideDownCake` which is a string preview version buildGradleFile.writeAsStringSync( buildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkPreview = "UpsideDownCake"'), @@ -100,7 +100,7 @@ void main() { test( 'build succeeds when both example app and plugin target compileSdkPreview', () async { - final File appBuildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle'); + final File appBuildGradleFile = exampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle.kts'); // write a build.gradle with compileSdkPreview as `UpsideDownCake` which is a string preview version appBuildGradleFile.writeAsStringSync( appBuildGradleFile.readAsStringSync().replaceFirst(compileSdkVersionMatch, 'compileSdkPreview = "UpsideDownCake"'), diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart index acfb0e6ff1..a59303fadc 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart @@ -3126,9 +3126,9 @@ void main() { await runner.run(['create', '--no-pub', projectDir.path]); - expect(globals.fs.isFileSync('${projectDir.path}/android/app/build.gradle'), true); + expect(globals.fs.isFileSync('${projectDir.path}/android/app/build.gradle.kts'), true); - final String buildContent = await globals.fs.file('${projectDir.path}/android/app/build.gradle').readAsString(); + final String buildContent = await globals.fs.file('${projectDir.path}/android/app/build.gradle.kts').readAsString(); expect(buildContent.contains('compileSdk = flutter.compileSdkVersion'), true); expect(buildContent.contains('ndkVersion = flutter.ndkVersion'), true); diff --git a/packages/flutter_tools/test/integration.shard/android_plugin_compilesdkversion_mismatch_test.dart b/packages/flutter_tools/test/integration.shard/android_plugin_compilesdkversion_mismatch_test.dart index 9f753e6d27..301e851e71 100644 --- a/packages/flutter_tools/test/integration.shard/android_plugin_compilesdkversion_mismatch_test.dart +++ b/packages/flutter_tools/test/integration.shard/android_plugin_compilesdkversion_mismatch_test.dart @@ -54,7 +54,7 @@ void main() { final Directory pluginExampleAppDir = pluginAppDir.childDirectory('example'); - final File projectGradleFile = pluginExampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle'); + final File projectGradleFile = pluginExampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle.kts'); expect(projectGradleFile, exists); final String projectBuildGradle = projectGradleFile.readAsStringSync(); diff --git a/packages/flutter_tools/test/integration.shard/android_plugin_example_app_build_test.dart b/packages/flutter_tools/test/integration.shard/android_plugin_example_app_build_test.dart index 9412ba8c43..755ef2df44 100644 --- a/packages/flutter_tools/test/integration.shard/android_plugin_example_app_build_test.dart +++ b/packages/flutter_tools/test/integration.shard/android_plugin_example_app_build_test.dart @@ -51,7 +51,7 @@ void main() { final Directory exampleAppDir = tempDir.childDirectory(testName).childDirectory('example'); - final File buildGradleFile = exampleAppDir.childDirectory('android').childFile('build.gradle'); + final File buildGradleFile = exampleAppDir.childDirectory('android').childFile('build.gradle.kts'); expect(buildGradleFile, exists); final String buildGradle = buildGradleFile.readAsStringSync(); diff --git a/packages/flutter_tools/test/integration.shard/android_plugin_ndkversion_mismatch_test.dart b/packages/flutter_tools/test/integration.shard/android_plugin_ndkversion_mismatch_test.dart index 93e3cfd744..21784f1b5e 100644 --- a/packages/flutter_tools/test/integration.shard/android_plugin_ndkversion_mismatch_test.dart +++ b/packages/flutter_tools/test/integration.shard/android_plugin_ndkversion_mismatch_test.dart @@ -53,7 +53,7 @@ void main() { final Directory pluginExampleAppDir = pluginAppDir.childDirectory('example'); - final File projectGradleFile = pluginExampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle'); + final File projectGradleFile = pluginExampleAppDir.childDirectory('android').childDirectory('app').childFile('build.gradle.kts'); expect(projectGradleFile, exists); final String projectBuildGradle = projectGradleFile.readAsStringSync(); diff --git a/packages/flutter_tools/test/src/android_common.dart b/packages/flutter_tools/test/src/android_common.dart index 5f0832b3ce..ab2f82e900 100644 --- a/packages/flutter_tools/test/src/android_common.dart +++ b/packages/flutter_tools/test/src/android_common.dart @@ -160,7 +160,7 @@ Future buildFlutterApkWithSpecifiedDependencyVersions({ if (versions.compileSdkVersion != null) { final File appGradleBuild = File(fileSystem.path.join( - app.path, 'android', 'app', 'build.gradle')); + app.path, 'android', 'app', 'build.gradle.kts')); final String appBuildContent = appGradleBuild.readAsStringSync() .replaceFirst(flutterCompileSdkString, versions.compileSdkVersion!); appGradleBuild.writeAsStringSync(appBuildContent);