Show a warning when a module uses a v1 only plugin (#44499)
diff --git a/packages/flutter_tools/test/general.shard/plugins_test.dart b/packages/flutter_tools/test/general.shard/plugins_test.dart
index ea41d4d..802d8034 100644
--- a/packages/flutter_tools/test/general.shard/plugins_test.dart
+++ b/packages/flutter_tools/test/general.shard/plugins_test.dart
@@ -55,7 +55,7 @@
dummyPackageDirectory = fs.directory('/pubcache/apackage/lib/');
packagesFile = fs.file(fs.path.join(flutterProject.directory.path, PackageMap.globalPackagesPath));
packagesFile..createSync(recursive: true)
- ..writeAsStringSync('apackage:file://${dummyPackageDirectory.path}');
+ ..writeAsStringSync('apackage:file://${dummyPackageDirectory.path}\n');
});
// Makes the dummy package pointed to by packagesFile look like a plugin.
@@ -69,6 +69,126 @@
''');
}
+
+ void createNewJavaPlugin1() {
+ final Directory pluginUsingJavaAndNewEmbeddingDir =
+ fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.');
+ pluginUsingJavaAndNewEmbeddingDir
+ .childFile('pubspec.yaml')
+ .writeAsStringSync('''
+flutter:
+ plugin:
+ androidPackage: plugin1
+ pluginClass: UseNewEmbedding
+ ''');
+ pluginUsingJavaAndNewEmbeddingDir
+ .childDirectory('android')
+ .childDirectory('src')
+ .childDirectory('main')
+ .childDirectory('java')
+ .childDirectory('plugin1')
+ .childFile('UseNewEmbedding.java')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin;');
+
+ flutterProject.directory
+ .childFile('.packages')
+ .writeAsStringSync(
+ 'plugin1:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()}\n',
+ mode: FileMode.append,
+ );
+ }
+
+ void createNewKotlinPlugin2() {
+ final Directory pluginUsingKotlinAndNewEmbeddingDir =
+ fs.systemTempDirectory.createTempSync('flutter_plugin_using_kotlin_and_new_embedding_dir.');
+ pluginUsingKotlinAndNewEmbeddingDir
+ .childFile('pubspec.yaml')
+ .writeAsStringSync('''
+flutter:
+ plugin:
+ androidPackage: plugin2
+ pluginClass: UseNewEmbedding
+ ''');
+ pluginUsingKotlinAndNewEmbeddingDir
+ .childDirectory('android')
+ .childDirectory('src')
+ .childDirectory('main')
+ .childDirectory('kotlin')
+ .childDirectory('plugin2')
+ .childFile('UseNewEmbedding.kt')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin');
+
+ flutterProject.directory
+ .childFile('.packages')
+ .writeAsStringSync(
+ 'plugin2:${pluginUsingKotlinAndNewEmbeddingDir.childDirectory('lib').uri.toString()}\n',
+ mode: FileMode.append,
+ );
+ }
+
+ void createOldJavaPlugin3() {
+ final Directory pluginUsingOldEmbeddingDir =
+ fs.systemTempDirectory.createTempSync('flutter_plugin_using_old_embedding_dir.');
+ pluginUsingOldEmbeddingDir
+ .childFile('pubspec.yaml')
+ .writeAsStringSync('''
+flutter:
+ plugin:
+ androidPackage: plugin3
+ pluginClass: UseOldEmbedding
+ ''');
+ pluginUsingOldEmbeddingDir
+ .childDirectory('android')
+ .childDirectory('src')
+ .childDirectory('main')
+ .childDirectory('java')
+ .childDirectory('plugin3')
+ .childFile('UseOldEmbedding.java')
+ ..createSync(recursive: true);
+
+ flutterProject.directory
+ .childFile('.packages')
+ .writeAsStringSync(
+ 'plugin3:${pluginUsingOldEmbeddingDir.childDirectory('lib').uri.toString()}\n',
+ mode: FileMode.append,
+ );
+ }
+
+ void createDualSupportJavaPlugin4() {
+ final Directory pluginUsingJavaAndNewEmbeddingDir =
+ fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.');
+ pluginUsingJavaAndNewEmbeddingDir
+ .childFile('pubspec.yaml')
+ .writeAsStringSync('''
+flutter:
+ plugin:
+ androidPackage: plugin4
+ pluginClass: UseBothEmbedding
+''');
+ pluginUsingJavaAndNewEmbeddingDir
+ .childDirectory('android')
+ .childDirectory('src')
+ .childDirectory('main')
+ .childDirectory('java')
+ .childDirectory('plugin4')
+ .childFile('UseBothEmbedding.java')
+ ..createSync(recursive: true)
+ ..writeAsStringSync(
+ 'import io.flutter.embedding.engine.plugins.FlutterPlugin;\n'
+ 'PluginRegistry\n'
+ 'registerWith(Irrelevant registrar)\n'
+ );
+
+ flutterProject.directory
+ .childFile('.packages')
+ .writeAsStringSync(
+ 'plugin4:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()}',
+ mode: FileMode.append,
+ );
+ }
+
// Creates the files that would indicate that pod install has run for the
// given project.
void simulatePodInstallRun(XcodeBasedProject project) {
@@ -149,6 +269,7 @@
expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
+ expect(registrant.readAsStringSync(), contains('public static void registerWith(PluginRegistry registry)'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
@@ -168,6 +289,7 @@
expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
+ expect(registrant.readAsStringSync(), contains('public static void registerWith(@NonNull FlutterEngine flutterEngine)'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
@@ -178,72 +300,9 @@
when(flutterProject.isModule).thenReturn(false);
when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v2);
- final Directory pluginUsingJavaAndNewEmbeddingDir =
- fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.');
- pluginUsingJavaAndNewEmbeddingDir
- .childFile('pubspec.yaml')
- .writeAsStringSync('''
- flutter:
- plugin:
- androidPackage: plugin1
- pluginClass: UseNewEmbedding
- ''');
- pluginUsingJavaAndNewEmbeddingDir
- .childDirectory('android')
- .childDirectory('src')
- .childDirectory('main')
- .childDirectory('java')
- .childDirectory('plugin1')
- .childFile('UseNewEmbedding.java')
- ..createSync(recursive: true)
- ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin;');
-
- final Directory pluginUsingKotlinAndNewEmbeddingDir =
- fs.systemTempDirectory.createTempSync('flutter_plugin_using_kotlin_and_new_embedding_dir.');
- pluginUsingKotlinAndNewEmbeddingDir
- .childFile('pubspec.yaml')
- .writeAsStringSync('''
- flutter:
- plugin:
- androidPackage: plugin2
- pluginClass: UseNewEmbedding
- ''');
- pluginUsingKotlinAndNewEmbeddingDir
- .childDirectory('android')
- .childDirectory('src')
- .childDirectory('main')
- .childDirectory('kotlin')
- .childDirectory('plugin2')
- .childFile('UseNewEmbedding.kt')
- ..createSync(recursive: true)
- ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin');
-
- final Directory pluginUsingOldEmbeddingDir =
- fs.systemTempDirectory.createTempSync('flutter_plugin_using_old_embedding_dir.');
- pluginUsingOldEmbeddingDir
- .childFile('pubspec.yaml')
- .writeAsStringSync('''
- flutter:
- plugin:
- androidPackage: plugin3
- pluginClass: UseOldEmbedding
- ''');
- pluginUsingOldEmbeddingDir
- .childDirectory('android')
- .childDirectory('src')
- .childDirectory('main')
- .childDirectory('java')
- .childDirectory('plugin3')
- .childFile('UseOldEmbedding.java')
- ..createSync(recursive: true);
-
- flutterProject.directory
- .childFile('.packages')
- .writeAsStringSync('''
-plugin1:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()}
-plugin2:${pluginUsingKotlinAndNewEmbeddingDir.childDirectory('lib').uri.toString()}
-plugin3:${pluginUsingOldEmbeddingDir.childDirectory('lib').uri.toString()}
-''');
+ createNewJavaPlugin1();
+ createNewKotlinPlugin2();
+ createOldJavaPlugin3();
await injectPlugins(flutterProject);
@@ -258,6 +317,8 @@
expect(registrant.readAsStringSync(),
contains('plugin3.UseOldEmbedding.registerWith(shimPluginRegistry.registrarFor("plugin3.UseOldEmbedding"));'));
+ // There should be no warning message
+ expect(testLogger.statusText, isNot(contains('go/android-plugin-migration')));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
@@ -269,31 +330,8 @@
when(flutterProject.isModule).thenReturn(false);
when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v1);
- final Directory pluginUsingJavaAndNewEmbeddingDir =
- fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.');
- pluginUsingJavaAndNewEmbeddingDir
- .childFile('pubspec.yaml')
- .writeAsStringSync('''
- flutter:
- plugin:
- androidPackage: plugin1
- pluginClass: UseNewEmbedding
- ''');
- pluginUsingJavaAndNewEmbeddingDir
- .childDirectory('android')
- .childDirectory('src')
- .childDirectory('main')
- .childDirectory('java')
- .childDirectory('plugin1')
- .childFile('UseNewEmbedding.java')
- ..createSync(recursive: true)
- ..writeAsStringSync('import io.flutter.embedding.engine.plugins.FlutterPlugin;');
+ createNewJavaPlugin1();
- flutterProject.directory
- .childFile('.packages')
- .writeAsStringSync('''
-plugin1:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()}
-''');
await expectLater(
() async {
await injectPlugins(flutterProject);
@@ -310,39 +348,12 @@
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
- testUsingContext('allows app use a plugin that supports v1 and v2 embedding', () async {
+ testUsingContext('old embedding app uses a plugin that supports v1 and v2 embedding', () async {
when(flutterProject.isModule).thenReturn(false);
when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v1);
- final Directory pluginUsingJavaAndNewEmbeddingDir =
- fs.systemTempDirectory.createTempSync('flutter_plugin_using_java_and_new_embedding_dir.');
- pluginUsingJavaAndNewEmbeddingDir
- .childFile('pubspec.yaml')
- .writeAsStringSync('''
- flutter:
- plugin:
- androidPackage: plugin1
- pluginClass: UseNewEmbedding
- ''');
- pluginUsingJavaAndNewEmbeddingDir
- .childDirectory('android')
- .childDirectory('src')
- .childDirectory('main')
- .childDirectory('java')
- .childDirectory('plugin1')
- .childFile('UseNewEmbedding.java')
- ..createSync(recursive: true)
- ..writeAsStringSync(
- 'import io.flutter.embedding.engine.plugins.FlutterPlugin;\n'
- 'PluginRegistry\n'
- 'registerWith(Irrelevant registrar)\n'
- );
+ createDualSupportJavaPlugin4();
- flutterProject.directory
- .childFile('.packages')
- .writeAsStringSync('''
-plugin1:${pluginUsingJavaAndNewEmbeddingDir.childDirectory('lib').uri.toString()}
-''');
await injectPlugins(flutterProject);
final File registrant = flutterProject.directory
@@ -352,6 +363,8 @@
expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
+ expect(registrant.readAsStringSync(),
+ contains('UseBothEmbedding.registerWith(registry.registrarFor("plugin4.UseBothEmbedding"));'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
@@ -359,9 +372,11 @@
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
- testUsingContext('Registrant doesn\'t use new embedding if app doesn\'t use new embedding', () async {
+ testUsingContext('new embedding app uses a plugin that supports v1 and v2 embedding', () async {
when(flutterProject.isModule).thenReturn(false);
- when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v1);
+ when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v2);
+
+ createDualSupportJavaPlugin4();
await injectPlugins(flutterProject);
@@ -372,32 +387,16 @@
expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
+ expect(registrant.readAsStringSync(),
+ contains('flutterEngine.getPlugins().add(new plugin4.UseBothEmbedding());'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags,
+ XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
- testUsingContext('Registrant uses old embedding in module project', () async {
- when(flutterProject.isModule).thenReturn(true);
- when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v1);
-
- await injectPlugins(flutterProject);
-
- final File registrant = flutterProject.directory
- .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
- .childFile('GeneratedPluginRegistrant.java');
-
- expect(registrant.existsSync(), isTrue);
- expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
- expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- ProcessManager: () => FakeProcessManager.any(),
- FeatureFlags: () => featureFlags,
- });
-
- testUsingContext('Registrant uses new embedding if module uses new embedding', () async {
+ testUsingContext('Modules use new embedding', () async {
when(flutterProject.isModule).thenReturn(true);
when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v2);
@@ -410,29 +409,76 @@
expect(registrant.existsSync(), isTrue);
expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
+ expect(registrant.readAsStringSync(), contains('public static void registerWith(@NonNull FlutterEngine flutterEngine)'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags,
});
- testUsingContext('Registrant doesn\'t use new embedding if module doesn\'t use new embedding', () async {
+ testUsingContext('Module using old plugin shows warning', () async {
when(flutterProject.isModule).thenReturn(true);
- when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v1);
+ when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v2);
+
+ createOldJavaPlugin3();
await injectPlugins(flutterProject);
final File registrant = flutterProject.directory
.childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
.childFile('GeneratedPluginRegistrant.java');
-
- expect(registrant.existsSync(), isTrue);
- expect(registrant.readAsStringSync(), contains('package io.flutter.plugins'));
- expect(registrant.readAsStringSync(), contains('class GeneratedPluginRegistrant'));
+ expect(registrant.readAsStringSync(),
+ contains('plugin3.UseOldEmbedding.registerWith(shimPluginRegistry.registrarFor("plugin3.UseOldEmbedding"));'));
+ expect(testLogger.statusText, contains('The plugin `plugin3` is built using an older version of the Android plugin API'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
FeatureFlags: () => featureFlags,
+ XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+ });
+
+ testUsingContext('Module using new plugin shows no warnings', () async {
+ when(flutterProject.isModule).thenReturn(true);
+ when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v2);
+
+ createNewJavaPlugin1();
+
+ await injectPlugins(flutterProject);
+
+ final File registrant = flutterProject.directory
+ .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
+ .childFile('GeneratedPluginRegistrant.java');
+ expect(registrant.readAsStringSync(),
+ contains('flutterEngine.getPlugins().add(new plugin1.UseNewEmbedding());'));
+
+ expect(testLogger.statusText, isNot(contains('go/android-plugin-migration')));
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => FakeProcessManager.any(),
+ FeatureFlags: () => featureFlags,
+ XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+ });
+
+ testUsingContext('Module using plugin with v1 and v2 support shows no warning', () async {
+ when(flutterProject.isModule).thenReturn(true);
+ when(androidProject.getEmbeddingVersion()).thenReturn(AndroidEmbeddingVersion.v2);
+
+ createDualSupportJavaPlugin4();
+
+ await injectPlugins(flutterProject);
+
+ final File registrant = flutterProject.directory
+ .childDirectory(fs.path.join('android', 'app', 'src', 'main', 'java', 'io', 'flutter', 'plugins'))
+ .childFile('GeneratedPluginRegistrant.java');
+ expect(registrant.readAsStringSync(),
+ contains('flutterEngine.getPlugins().add(new plugin4.UseBothEmbedding());'));
+
+ expect(testLogger.statusText, isNot(contains('go/android-plugin-migration')));
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => FakeProcessManager.any(),
+ FeatureFlags: () => featureFlags,
+ XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
testUsingContext('Does not throw when AndroidManifest.xml is not found', () async {