diff --git a/dev/devicelab/bin/tasks/plugin_test.dart b/dev/devicelab/bin/tasks/plugin_test.dart index e00d2586875..1d9359a4183 100644 --- a/dev/devicelab/bin/tasks/plugin_test.dart +++ b/dev/devicelab/bin/tasks/plugin_test.dart @@ -11,5 +11,12 @@ Future main() async { await task(combine([ PluginTest('apk', ['-a', 'java']), PluginTest('apk', ['-a', 'kotlin']), + // These create the plugins using the new v2 plugin templates but create the + // apps using the old v1 embedding app templates to make sure new plugins + // are by default backward compatible. + PluginTest('apk', ['-a', 'java'], pluginCreateEnvironment: + {'ENABLE_ANDROID_EMBEDDING_V2': 'true'}), + PluginTest('apk', ['-a', 'kotlin'], pluginCreateEnvironment: + {'ENABLE_ANDROID_EMBEDDING_V2': 'true'}), ])); } diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart index 8141ba748e9..32ca1bad94a 100644 --- a/dev/devicelab/lib/framework/utils.dart +++ b/dev/devicelab/lib/framework/utils.dart @@ -256,7 +256,8 @@ Future startProcess( assert(isBot != null); final String command = '$executable ${arguments?.join(" ") ?? ""}'; final String finalWorkingDirectory = workingDirectory ?? cwd; - print('\nExecuting: $command in $finalWorkingDirectory'); + print('\nExecuting: $command in $finalWorkingDirectory' + + (environment != null ? ' with environment $environment' : '')); environment ??= {}; environment['BOT'] = isBot ? 'true' : 'false'; final Process process = await _processManager.start( diff --git a/dev/devicelab/lib/tasks/plugin_tests.dart b/dev/devicelab/lib/tasks/plugin_tests.dart index bf6c64e3866..e574fb6377a 100644 --- a/dev/devicelab/lib/tasks/plugin_tests.dart +++ b/dev/devicelab/lib/tasks/plugin_tests.dart @@ -26,10 +26,12 @@ TaskFunction combine(List tasks) { /// Defines task that creates new Flutter project, adds a local and remote /// plugin, and then builds the specified [buildTarget]. class PluginTest { - PluginTest(this.buildTarget, this.options); + PluginTest(this.buildTarget, this.options, { this.pluginCreateEnvironment, this.appCreateEnvironment }); final String buildTarget; final List options; + final Map pluginCreateEnvironment; + final Map appCreateEnvironment; Future call() async { final Directory tempDir = @@ -38,12 +40,12 @@ class PluginTest { section('Create plugin'); final _FlutterProject plugin = await _FlutterProject.create( tempDir, options, - name: 'plugintest', template: 'plugin'); + name: 'plugintest', template: 'plugin', environment: pluginCreateEnvironment); section('Test plugin'); await plugin.test(); section('Create Flutter app'); final _FlutterProject app = await _FlutterProject.create(tempDir, options, - name: 'plugintestapp', template: 'app'); + name: 'plugintestapp', template: 'app', environment: appCreateEnvironment); try { if (buildTarget == 'ios') await prepareProvisioningCertificates(app.rootPath); @@ -95,8 +97,13 @@ class _FlutterProject { } static Future<_FlutterProject> create( - Directory directory, List options, - {String name, String template}) async { + Directory directory, + List options, + { + String name, + String template, + Map environment, + }) async { await inDirectory(directory, () async { await flutter( 'create', @@ -107,6 +114,7 @@ class _FlutterProject { ...options, name, ], + environment: environment, ); }); return _FlutterProject(directory, name); diff --git a/packages/flutter_tools/templates/plugin/android-java.tmpl/src/main/java/androidIdentifier/pluginClass.java.tmpl b/packages/flutter_tools/templates/plugin/android-java.tmpl/src/main/java/androidIdentifier/pluginClass.java.tmpl index b6a72976d44..c2bdb80e6c8 100644 --- a/packages/flutter_tools/templates/plugin/android-java.tmpl/src/main/java/androidIdentifier/pluginClass.java.tmpl +++ b/packages/flutter_tools/templates/plugin/android-java.tmpl/src/main/java/androidIdentifier/pluginClass.java.tmpl @@ -12,6 +12,7 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; /** {{pluginClass}} */ public class {{pluginClass}} implements FlutterPlugin, MethodCallHandler { @@ -21,6 +22,20 @@ public class {{pluginClass}} implements FlutterPlugin, MethodCallHandler { channel.setMethodCallHandler(new {{pluginClass}}()); } + // This static function is optional and equivalent to onAttachedToEngine. It supports the old + // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting + // plugin registration via this function while apps migrate to use the new Android APIs + // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. + // + // It is encouraged to share logic between onAttachedToEngine and registerWith to keep + // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called + // depending on the user's project. onAttachedToEngine or registerWith must both be defined + // in the same class. + public static void registerWith(Registrar registrar) { + final MethodChannel channel = new MethodChannel(registrar.messenger(), "{{projectName}}"); + channel.setMethodCallHandler(new {{pluginClass}}()); + } + @Override public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { if (call.method.equals("getPlatformVersion")) { diff --git a/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/src/main/kotlin/androidIdentifier/pluginClass.kt.tmpl b/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/src/main/kotlin/androidIdentifier/pluginClass.kt.tmpl index 1147f1cf6e7..2e7596aad4c 100644 --- a/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/src/main/kotlin/androidIdentifier/pluginClass.kt.tmpl +++ b/packages/flutter_tools/templates/plugin/android-kotlin.tmpl/src/main/kotlin/androidIdentifier/pluginClass.kt.tmpl @@ -12,6 +12,7 @@ import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result +import io.flutter.plugin.common.PluginRegistry.Registrar /** {{pluginClass}} */ public class {{pluginClass}}: FlutterPlugin, MethodCallHandler { @@ -20,6 +21,23 @@ public class {{pluginClass}}: FlutterPlugin, MethodCallHandler { channel.setMethodCallHandler({{pluginClass}}()); } + // This static function is optional and equivalent to onAttachedToEngine. It supports the old + // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting + // plugin registration via this function while apps migrate to use the new Android APIs + // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. + // + // It is encouraged to share logic between onAttachedToEngine and registerWith to keep + // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called + // depending on the user's project. onAttachedToEngine or registerWith must both be defined + // in the same class. + companion object { + @JvmStatic + fun registerWith(registrar: Registrar) { + val channel = MethodChannel(registrar.messenger(), "{{projectName}}") + channel.setMethodCallHandler({{pluginClass}}()) + } + } + override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { if (call.method == "getPlatformVersion") { result.success("Android ${android.os.Build.VERSION.RELEASE}")