diff --git a/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl index 26f3272c920..b3359741f38 100644 --- a/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl +++ b/packages/flutter_tools/templates/plugin/android-java.tmpl/build.gradle.tmpl @@ -22,6 +22,10 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { + if (project.android.hasProperty("namespace")) { + namespace '{{androidIdentifier}}' + } + compileSdkVersion {{compileSdkVersion}} compileOptions { diff --git a/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/build.gradle.tmpl index 9b35a39f389..b466c607eed 100644 --- a/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/build.gradle.tmpl +++ b/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/build.gradle.tmpl @@ -25,6 +25,10 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { + if (project.android.hasProperty("namespace")) { + namespace '{{androidIdentifier}}' + } + compileSdkVersion 31 compileOptions { diff --git a/packages/flutter_tools/templates/plugin_ffi/android.tmpl/build.gradle.tmpl b/packages/flutter_tools/templates/plugin_ffi/android.tmpl/build.gradle.tmpl index 0383cfd7374..74511b59ced 100644 --- a/packages/flutter_tools/templates/plugin_ffi/android.tmpl/build.gradle.tmpl +++ b/packages/flutter_tools/templates/plugin_ffi/android.tmpl/build.gradle.tmpl @@ -25,6 +25,10 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { + if (project.android.hasProperty("namespace")) { + namespace '{{androidIdentifier}}' + } + // Bumping the plugin compileSdkVersion requires all clients of this plugin // to bump the version in their app. compileSdkVersion {{compileSdkVersion}} 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 0249996e112..6d86f2a9535 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart @@ -2848,6 +2848,77 @@ void main() { expect(buildContent.contains('targetSdkVersion flutter.targetSdkVersion'), true); }); + testUsingContext('Android Java plugin contains namespace', () async { + Cache.flutterRoot = '../..'; + + final CreateCommand command = CreateCommand(); + final CommandRunner runner = createTestCommandRunner(command); + + await runner.run(['create', '--no-pub', + '-t', 'plugin', + '--org', 'com.bar.foo', + '-a', 'java', + '--platforms=android', + projectDir.path]); + + final File buildGradleFile = globals.fs.file('${projectDir.path}/android/build.gradle'); + + expect(buildGradleFile.existsSync(), true); + + final String buildGradleContent = await buildGradleFile.readAsString(); + + expect(buildGradleContent.contains("namespace 'com.bar.foo.flutter_project'"), true); + // The namespace should be conditionalized for AGP <4.2. + expect(buildGradleContent.contains('if (project.android.hasProperty("namespace")) {'), true); + }); + + testUsingContext('Android FFI plugin contains namespace', () async { + Cache.flutterRoot = '../..'; + + final CreateCommand command = CreateCommand(); + final CommandRunner runner = createTestCommandRunner(command); + + await runner.run(['create', '--no-pub', + '-t', 'plugin_ffi', + '--org', 'com.bar.foo', + '--platforms=android', + projectDir.path]); + + final File buildGradleFile = globals.fs.file('${projectDir.path}/android/build.gradle'); + + expect(buildGradleFile.existsSync(), true); + + final String buildGradleContent = await buildGradleFile.readAsString(); + + expect(buildGradleContent.contains("namespace 'com.bar.foo.flutter_project'"), true); + // The namespace should be conditionalized for AGP <4.2. + expect(buildGradleContent.contains('if (project.android.hasProperty("namespace")) {'), true); + }); + + testUsingContext('Android Kotlin plugin contains namespace', () async { + Cache.flutterRoot = '../..'; + + final CreateCommand command = CreateCommand(); + final CommandRunner runner = createTestCommandRunner(command); + + await runner.run(['create', '--no-pub', + '-t', 'plugin', + '--org', 'com.bar.foo', + '-a', 'kotlin', + '--platforms=android', + projectDir.path]); + + final File buildGradleFile = globals.fs.file('${projectDir.path}/android/build.gradle'); + + expect(buildGradleFile.existsSync(), true); + + final String buildGradleContent = await buildGradleFile.readAsString(); + + expect(buildGradleContent.contains("namespace 'com.bar.foo.flutter_project'"), true); + // The namespace should be conditionalized for AGP <4.2. + expect(buildGradleContent.contains('if (project.android.hasProperty("namespace")) {'), true); + }); + testUsingContext('Linux plugins handle partially camel-case project names correctly', () async { Cache.flutterRoot = '../..';