From bc1168feaa8f6b56d313713962d0d0c7fd92aacd Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 10 Apr 2024 09:41:32 -0700 Subject: [PATCH 1/4] Revert "Reverts "Delete engine v1 android embedding (#51229)" (#51996)" This reverts commit 5dca50d3e268c16f3d4297d84d078b3dba7e62b0. --- ci/licenses_golden/licenses_flutter | 24 - shell/platform/android/AndroidManifest.xml | 17 +- shell/platform/android/BUILD.gn | 12 - .../io/flutter/app/FlutterActivity.java | 181 ---- .../flutter/app/FlutterActivityDelegate.java | 495 --------- .../io/flutter/app/FlutterActivityEvents.java | 73 -- .../io/flutter/app/FlutterApplication.java | 36 - .../flutter/app/FlutterFragmentActivity.java | 181 ---- .../app/FlutterPlayStoreSplitApplication.java | 53 - .../io/flutter/app/FlutterPluginRegistry.java | 259 ----- .../flutter/embedding/engine/FlutterJNI.java | 3 +- .../plugins/shim/ShimPluginRegistry.java | 153 --- .../engine/plugins/shim/ShimRegistrar.java | 234 ----- .../flutter/plugin/common/PluginRegistry.java | 367 +------ .../editing/ListenableEditingState.java | 2 +- .../platform/PlatformViewsController.java | 5 +- .../android/io/flutter/view/FlutterMain.java | 132 --- .../io/flutter/view/FlutterNativeView.java | 204 ---- .../android/io/flutter/view/FlutterView.java | 992 ------------------ .../io/flutter/view/TextureRegistry.java | 4 +- .../plugins/shim/ShimPluginRegistryTest.java | 157 --- .../android/app/src/main/AndroidManifest.xml | 1 - tools/javadoc/gen_javadoc.py | 2 - 23 files changed, 8 insertions(+), 3579 deletions(-) delete mode 100644 shell/platform/android/io/flutter/app/FlutterActivity.java delete mode 100644 shell/platform/android/io/flutter/app/FlutterActivityDelegate.java delete mode 100644 shell/platform/android/io/flutter/app/FlutterActivityEvents.java delete mode 100644 shell/platform/android/io/flutter/app/FlutterApplication.java delete mode 100644 shell/platform/android/io/flutter/app/FlutterFragmentActivity.java delete mode 100644 shell/platform/android/io/flutter/app/FlutterPlayStoreSplitApplication.java delete mode 100644 shell/platform/android/io/flutter/app/FlutterPluginRegistry.java delete mode 100644 shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java delete mode 100644 shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java delete mode 100644 shell/platform/android/io/flutter/view/FlutterMain.java delete mode 100644 shell/platform/android/io/flutter/view/FlutterNativeView.java delete mode 100644 shell/platform/android/io/flutter/view/FlutterView.java delete mode 100644 shell/platform/android/test/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistryTest.java diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 90af1ef2d726a..4dae834ae8aeb 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -44020,13 +44020,6 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/Build.java + ../../.. ORIGIN: ../../../flutter/shell/platform/android/io/flutter/BuildConfig.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/Log.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivity.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityEvents.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterApplication.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterPlayStoreSplitApplication.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/android/ExclusiveAppComponent.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java + ../../../flutter/LICENSE @@ -44083,8 +44076,6 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plug ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceControlSurface.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/util/GeneratedPluginRegister.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterUiDisplayListener.java + ../../../flutter/LICENSE @@ -44156,10 +44147,7 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/util/ViewUtils.java + ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/FlutterCallbackInformation.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/FlutterMain.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/FlutterNativeView.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/FlutterRunArguments.java + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/FlutterView.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/TextureRegistry.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/jni/jni_mock.h + ../../../flutter/LICENSE @@ -46891,13 +46879,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/Build.java FILE: ../../../flutter/shell/platform/android/io/flutter/BuildConfig.java FILE: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java FILE: ../../../flutter/shell/platform/android/io/flutter/Log.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivity.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityEvents.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterApplication.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterPlayStoreSplitApplication.java -FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/ExclusiveAppComponent.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -46957,8 +46938,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugin FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceControlSurface.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java -FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java -FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/util/GeneratedPluginRegister.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterUiDisplayListener.java @@ -47038,10 +47017,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/util/ViewUtils.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterCallbackInformation.java -FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterMain.java -FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterNativeView.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterRunArguments.java -FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterView.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/TextureRegistry.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java FILE: ../../../flutter/shell/platform/android/jni/jni_mock.h diff --git a/shell/platform/android/AndroidManifest.xml b/shell/platform/android/AndroidManifest.xml index cbc2aa2e8cde7..1f8e23631865b 100644 --- a/shell/platform/android/AndroidManifest.xml +++ b/shell/platform/android/AndroidManifest.xml @@ -3,28 +3,13 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - + - - - - - - - - - diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 6f062431cf747..bab2f5cb78f32 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -207,13 +207,6 @@ android_java_sources = [ "io/flutter/Build.java", "io/flutter/FlutterInjector.java", "io/flutter/Log.java", - "io/flutter/app/FlutterActivity.java", - "io/flutter/app/FlutterActivityDelegate.java", - "io/flutter/app/FlutterActivityEvents.java", - "io/flutter/app/FlutterApplication.java", - "io/flutter/app/FlutterFragmentActivity.java", - "io/flutter/app/FlutterPlayStoreSplitApplication.java", - "io/flutter/app/FlutterPluginRegistry.java", "io/flutter/embedding/android/AndroidTouchProcessor.java", "io/flutter/embedding/android/ExclusiveAppComponent.java", "io/flutter/embedding/android/FlutterActivity.java", @@ -273,8 +266,6 @@ android_java_sources = [ "io/flutter/embedding/engine/plugins/service/ServiceAware.java", "io/flutter/embedding/engine/plugins/service/ServiceControlSurface.java", "io/flutter/embedding/engine/plugins/service/ServicePluginBinding.java", - "io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java", - "io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java", "io/flutter/embedding/engine/plugins/util/GeneratedPluginRegister.java", "io/flutter/embedding/engine/renderer/FlutterRenderer.java", "io/flutter/embedding/engine/renderer/FlutterUiDisplayListener.java", @@ -354,10 +345,7 @@ android_java_sources = [ "io/flutter/view/AccessibilityBridge.java", "io/flutter/view/AccessibilityViewEmbedder.java", "io/flutter/view/FlutterCallbackInformation.java", - "io/flutter/view/FlutterMain.java", - "io/flutter/view/FlutterNativeView.java", "io/flutter/view/FlutterRunArguments.java", - "io/flutter/view/FlutterView.java", "io/flutter/view/TextureRegistry.java", "io/flutter/view/VsyncWaiter.java", ] diff --git a/shell/platform/android/io/flutter/app/FlutterActivity.java b/shell/platform/android/io/flutter/app/FlutterActivity.java deleted file mode 100644 index 932ad2c5ada57..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterActivity.java +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Bundle; -import androidx.annotation.NonNull; -import io.flutter.app.FlutterActivityDelegate.ViewFactory; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.view.FlutterNativeView; -import io.flutter.view.FlutterView; - -/** - * Deprecated base class for activities that use Flutter. - * - * @deprecated {@link io.flutter.embedding.android.FlutterActivity} is the new API that now replaces - * this class. See https://flutter.dev/go/android-project-migration for more migration details. - */ -@Deprecated -public class FlutterActivity extends Activity - implements FlutterView.Provider, PluginRegistry, ViewFactory { - private static final String TAG = "FlutterActivity"; - - private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this); - - // These aliases ensure that the methods we forward to the delegate adhere - // to relevant interfaces versus just existing in FlutterActivityDelegate. - private final FlutterActivityEvents eventDelegate = delegate; - private final FlutterView.Provider viewProvider = delegate; - private final PluginRegistry pluginRegistry = delegate; - - /** - * Returns the Flutter view used by this activity; will be null before {@link #onCreate(Bundle)} - * is called. - */ - @Override - public FlutterView getFlutterView() { - return viewProvider.getFlutterView(); - } - - /** - * Hook for subclasses to customize the creation of the {@code FlutterView}. - * - *

The default implementation returns {@code null}, which will cause the activity to use a - * newly instantiated full-screen view. - */ - @Override - public FlutterView createFlutterView(Context context) { - return null; - } - - /** - * Hook for subclasses to customize the creation of the {@code FlutterNativeView}. - * - *

The default implementation returns {@code null}, which will cause the activity to use a - * newly instantiated native view object. - */ - @Override - public FlutterNativeView createFlutterNativeView() { - return null; - } - - @Override - public boolean retainFlutterNativeView() { - return false; - } - - @Override - public final boolean hasPlugin(String key) { - return pluginRegistry.hasPlugin(key); - } - - @Override - public final T valuePublishedByPlugin(String pluginKey) { - return pluginRegistry.valuePublishedByPlugin(pluginKey); - } - - @Override - public final Registrar registrarFor(String pluginKey) { - return pluginRegistry.registrarFor(pluginKey); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - eventDelegate.onCreate(savedInstanceState); - } - - @Override - protected void onStart() { - super.onStart(); - eventDelegate.onStart(); - } - - @Override - protected void onResume() { - super.onResume(); - eventDelegate.onResume(); - } - - @Override - protected void onDestroy() { - eventDelegate.onDestroy(); - super.onDestroy(); - } - - @Override - public void onBackPressed() { - if (!eventDelegate.onBackPressed()) { - super.onBackPressed(); - } - } - - @Override - protected void onStop() { - eventDelegate.onStop(); - super.onStop(); - } - - @Override - protected void onPause() { - super.onPause(); - eventDelegate.onPause(); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - eventDelegate.onPostResume(); - } - - // @Override - added in API level 23 - public void onRequestPermissionsResult( - int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - eventDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (!eventDelegate.onActivityResult(requestCode, resultCode, data)) { - super.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - protected void onNewIntent(Intent intent) { - eventDelegate.onNewIntent(intent); - } - - @Override - public void onUserLeaveHint() { - eventDelegate.onUserLeaveHint(); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - eventDelegate.onWindowFocusChanged(hasFocus); - } - - @Override - public void onTrimMemory(int level) { - eventDelegate.onTrimMemory(level); - } - - @Override - public void onLowMemory() { - eventDelegate.onLowMemory(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - eventDelegate.onConfigurationChanged(newConfig); - } -} diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java deleted file mode 100644 index fcb553bbe8a2f..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ /dev/null @@ -1,495 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.app.Activity; -import android.app.Application; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Configuration; -import android.content.res.Resources.NotFoundException; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.TypedValue; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager.LayoutParams; -import io.flutter.Log; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.plugin.platform.PlatformPlugin; -import io.flutter.util.Preconditions; -import io.flutter.view.FlutterMain; -import io.flutter.view.FlutterNativeView; -import io.flutter.view.FlutterRunArguments; -import io.flutter.view.FlutterView; -import java.util.ArrayList; - -/** - * Deprecated class that performs the actual work of tying Android {@link android.app.Activity} - * instances to Flutter. - * - *

This exists as a dedicated class (as opposed to being integrated directly into {@link - * FlutterActivity}) to facilitate applications that don't wish to subclass {@code FlutterActivity}. - * The most obvious example of when this may come in handy is if an application wishes to subclass - * the Android v4 support library's {@code FragmentActivity}. - * - *

Usage: - * - *

To wire this class up to your activity, simply forward the events defined in {@link - * FlutterActivityEvents} from your activity to an instance of this class. Optionally, you can make - * your activity implement {@link PluginRegistry} and/or {@link - * io.flutter.view.FlutterView.Provider} and forward those methods to this class as well. - * - * @deprecated {@link io.flutter.embedding.android.FlutterActivity} is the new API that now replaces - * this class and {@link io.flutter.app.FlutterActivity}. See - * https://flutter.dev/go/android-project-migration for more migration details. - */ -@Deprecated -public final class FlutterActivityDelegate - implements FlutterActivityEvents, FlutterView.Provider, PluginRegistry { - private static final String SPLASH_SCREEN_META_DATA_KEY = - "io.flutter.app.android.SplashScreenUntilFirstFrame"; - private static final String TAG = "FlutterActivityDelegate"; - private static final LayoutParams matchParent = - new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - - /** - * Specifies the mechanism by which Flutter views are created during the operation of a {@code - * FlutterActivityDelegate}. - * - *

A delegate's view factory will be consulted during {@link #onCreate(Bundle)}. If it returns - * {@code null}, then the delegate will fall back to instantiating a new full-screen {@code - * FlutterView}. - * - *

A delegate's native view factory will be consulted during {@link #onCreate(Bundle)}. If it - * returns {@code null}, then the delegate will fall back to instantiating a new {@code - * FlutterNativeView}. This is useful for applications to override to reuse the FlutterNativeView - * held e.g. by a pre-existing background service. - */ - public interface ViewFactory { - FlutterView createFlutterView(Context context); - - FlutterNativeView createFlutterNativeView(); - - /** - * Hook for subclasses to indicate that the {@code FlutterNativeView} returned by {@link - * #createFlutterNativeView()} should not be destroyed when this activity is destroyed. - * - * @return Whether the FlutterNativeView is retained. - */ - boolean retainFlutterNativeView(); - } - - private final Activity activity; - private final ViewFactory viewFactory; - private FlutterView flutterView; - private View launchView; - - public FlutterActivityDelegate(Activity activity, ViewFactory viewFactory) { - this.activity = Preconditions.checkNotNull(activity); - this.viewFactory = Preconditions.checkNotNull(viewFactory); - } - - @Override - public FlutterView getFlutterView() { - return flutterView; - } - - // The implementation of PluginRegistry forwards to flutterView. - @Override - public boolean hasPlugin(String key) { - return flutterView.getPluginRegistry().hasPlugin(key); - } - - @Override - @SuppressWarnings("unchecked") - public T valuePublishedByPlugin(String pluginKey) { - return (T) flutterView.getPluginRegistry().valuePublishedByPlugin(pluginKey); - } - - @Override - public Registrar registrarFor(String pluginKey) { - return flutterView.getPluginRegistry().registrarFor(pluginKey); - } - - @Override - public boolean onRequestPermissionsResult( - int requestCode, String[] permissions, int[] grantResults) { - return flutterView - .getPluginRegistry() - .onRequestPermissionsResult(requestCode, permissions, grantResults); - } - - @Override - public boolean onActivityResult(int requestCode, int resultCode, Intent data) { - return flutterView.getPluginRegistry().onActivityResult(requestCode, resultCode, data); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - Window window = activity.getWindow(); - window.addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - window.setStatusBarColor(0x40000000); - window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI); - - String[] args = getArgsFromIntent(activity.getIntent()); - FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), args); - - flutterView = viewFactory.createFlutterView(activity); - if (flutterView == null) { - FlutterNativeView nativeView = viewFactory.createFlutterNativeView(); - flutterView = new FlutterView(activity, null, nativeView); - flutterView.setLayoutParams(matchParent); - activity.setContentView(flutterView); - launchView = createLaunchView(); - if (launchView != null) { - addLaunchView(); - } - } - - if (loadIntent(activity.getIntent())) { - return; - } - - String appBundlePath = FlutterMain.findAppBundlePath(); - if (appBundlePath != null) { - runBundle(appBundlePath); - } - } - - @Override - public void onNewIntent(Intent intent) { - // Only attempt to reload the Flutter Dart code during development. Use - // the debuggable flag as an indicator that we are in development mode. - if (!isDebuggable() || !loadIntent(intent)) { - flutterView.getPluginRegistry().onNewIntent(intent); - } - } - - private boolean isDebuggable() { - return (activity.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; - } - - @Override - public void onPause() { - Application app = (Application) activity.getApplicationContext(); - if (app instanceof FlutterApplication) { - FlutterApplication flutterApp = (FlutterApplication) app; - if (activity.equals(flutterApp.getCurrentActivity())) { - flutterApp.setCurrentActivity(null); - } - } - if (flutterView != null) { - flutterView.onPause(); - } - } - - @Override - public void onStart() { - if (flutterView != null) { - flutterView.onStart(); - } - } - - @Override - public void onResume() { - Application app = (Application) activity.getApplicationContext(); - if (app instanceof FlutterApplication) { - FlutterApplication flutterApp = (FlutterApplication) app; - flutterApp.setCurrentActivity(activity); - } - } - - @Override - public void onStop() { - flutterView.onStop(); - } - - @Override - public void onPostResume() { - if (flutterView != null) { - flutterView.onPostResume(); - } - } - - @Override - public void onDestroy() { - Application app = (Application) activity.getApplicationContext(); - if (app instanceof FlutterApplication) { - FlutterApplication flutterApp = (FlutterApplication) app; - if (activity.equals(flutterApp.getCurrentActivity())) { - flutterApp.setCurrentActivity(null); - } - } - if (flutterView != null) { - final boolean detach = - flutterView.getPluginRegistry().onViewDestroy(flutterView.getFlutterNativeView()); - if (detach || viewFactory.retainFlutterNativeView()) { - // Detach, but do not destroy the FlutterView if a plugin - // expressed interest in its FlutterNativeView. - flutterView.detach(); - } else { - flutterView.destroy(); - } - } - } - - @Override - public boolean onBackPressed() { - if (flutterView != null) { - flutterView.popRoute(); - return true; - } - return false; - } - - @Override - public void onUserLeaveHint() { - flutterView.getPluginRegistry().onUserLeaveHint(); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - flutterView.getPluginRegistry().onWindowFocusChanged(hasFocus); - } - - @Override - public void onTrimMemory(int level) { - // Use a trim level delivered while the application is running so the - // framework has a chance to react to the notification. - if (level == TRIM_MEMORY_RUNNING_LOW) { - flutterView.onMemoryPressure(); - } - } - - @Override - public void onLowMemory() { - flutterView.onMemoryPressure(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) {} - - private static String[] getArgsFromIntent(Intent intent) { - // Before adding more entries to this list, consider that arbitrary - // Android applications can generate intents with extra data and that - // there are many security-sensitive args in the binary. - ArrayList args = new ArrayList<>(); - if (intent.getBooleanExtra("trace-startup", false)) { - args.add("--trace-startup"); - } - if (intent.getBooleanExtra("start-paused", false)) { - args.add("--start-paused"); - } - if (intent.getBooleanExtra("disable-service-auth-codes", false)) { - args.add("--disable-service-auth-codes"); - } - if (intent.getBooleanExtra("use-test-fonts", false)) { - args.add("--use-test-fonts"); - } - if (intent.getBooleanExtra("enable-dart-profiling", false)) { - args.add("--enable-dart-profiling"); - } - if (intent.getBooleanExtra("enable-software-rendering", false)) { - args.add("--enable-software-rendering"); - } - if (intent.getBooleanExtra("skia-deterministic-rendering", false)) { - args.add("--skia-deterministic-rendering"); - } - if (intent.getBooleanExtra("trace-skia", false)) { - args.add("--trace-skia"); - } - if (intent.getBooleanExtra("trace-systrace", false)) { - args.add("--trace-systrace"); - } - if (intent.hasExtra("trace-to-file")) { - args.add("--trace-to-file=" + intent.getStringExtra("trace-to-file")); - } - if (intent.getBooleanExtra("dump-skp-on-shader-compilation", false)) { - args.add("--dump-skp-on-shader-compilation"); - } - if (intent.getBooleanExtra("cache-sksl", false)) { - args.add("--cache-sksl"); - } - if (intent.getBooleanExtra("purge-persistent-cache", false)) { - args.add("--purge-persistent-cache"); - } - if (intent.getBooleanExtra("verbose-logging", false)) { - args.add("--verbose-logging"); - } - int vmServicePort = intent.getIntExtra("vm-service-port", 0); - if (vmServicePort > 0) { - args.add("--vm-service-port=" + Integer.toString(vmServicePort)); - } else { - // TODO(bkonyi): remove once flutter_tools no longer uses this option. - // See https://github.com/dart-lang/sdk/issues/50233 - vmServicePort = intent.getIntExtra("observatory-port", 0); - if (vmServicePort > 0) { - args.add("--vm-service-port=" + Integer.toString(vmServicePort)); - } - } - if (intent.getBooleanExtra("endless-trace-buffer", false)) { - args.add("--endless-trace-buffer"); - } - // NOTE: all flags provided with this argument are subject to filtering - // based on a list of allowed flags in shell/common/switches.cc. If any - // flag provided is not allowed, the process will immediately terminate. - if (intent.hasExtra("dart-flags")) { - args.add("--dart-flags=" + intent.getStringExtra("dart-flags")); - } - if (!args.isEmpty()) { - String[] argsArray = new String[args.size()]; - return args.toArray(argsArray); - } - return null; - } - - private boolean loadIntent(Intent intent) { - String action = intent.getAction(); - if (Intent.ACTION_RUN.equals(action)) { - String route = intent.getStringExtra("route"); - String appBundlePath = intent.getDataString(); - if (appBundlePath == null) { - // Fall back to the installation path if no bundle path was specified. - appBundlePath = FlutterMain.findAppBundlePath(); - } - if (route != null) { - flutterView.setInitialRoute(route); - } - - runBundle(appBundlePath); - return true; - } - - return false; - } - - private void runBundle(String appBundlePath) { - if (!flutterView.getFlutterNativeView().isApplicationRunning()) { - FlutterRunArguments args = new FlutterRunArguments(); - args.bundlePath = appBundlePath; - args.entrypoint = "main"; - flutterView.runFromBundle(args); - } - } - - /** - * Creates a {@link View} containing the same {@link Drawable} as the one set as the {@code - * windowBackground} of the parent activity for use as a launch splash view. - * - *

Returns null if no {@code windowBackground} is set for the activity. - */ - private View createLaunchView() { - if (!showSplashScreenUntilFirstFrame()) { - return null; - } - final Drawable launchScreenDrawable = getLaunchScreenDrawableFromActivityTheme(); - if (launchScreenDrawable == null) { - return null; - } - final View view = new View(activity); - view.setLayoutParams(matchParent); - view.setBackground(launchScreenDrawable); - return view; - } - - /** - * Extracts a {@link Drawable} from the parent activity's {@code windowBackground}. - * - *

{@code android:windowBackground} is specifically reused instead of a other attributes - * because the Android framework can display it fast enough when launching the app as opposed to - * anything defined in the Activity subclass. - * - *

Returns null if no {@code windowBackground} is set for the activity. - */ - @SuppressWarnings("deprecation") - private Drawable getLaunchScreenDrawableFromActivityTheme() { - TypedValue typedValue = new TypedValue(); - if (!activity.getTheme().resolveAttribute(android.R.attr.windowBackground, typedValue, true)) { - return null; - } - if (typedValue.resourceId == 0) { - return null; - } - try { - return activity.getResources().getDrawable(typedValue.resourceId); - } catch (NotFoundException e) { - Log.e(TAG, "Referenced launch screen windowBackground resource does not exist"); - return null; - } - } - - /** - * Let the user specify whether the activity's {@code windowBackground} is a launch screen and - * should be shown until the first frame via a tag in the activity. - */ - private Boolean showSplashScreenUntilFirstFrame() { - try { - ActivityInfo activityInfo = - activity - .getPackageManager() - .getActivityInfo(activity.getComponentName(), PackageManager.GET_META_DATA); - Bundle metadata = activityInfo.metaData; - return metadata != null && metadata.getBoolean(SPLASH_SCREEN_META_DATA_KEY); - } catch (NameNotFoundException e) { - return false; - } - } - - /** - * Show and then automatically animate out the launch view. - * - *

If a launch screen is defined in the user application's AndroidManifest.xml as the - * activity's {@code windowBackground}, display it on top of the {@link FlutterView} and remove - * the activity's {@code windowBackground}. - * - *

Fade it out and remove it when the {@link FlutterView} renders its first frame. - */ - private void addLaunchView() { - if (launchView == null) { - return; - } - - activity.addContentView(launchView, matchParent); - flutterView.addFirstFrameListener( - new FlutterView.FirstFrameListener() { - @Override - public void onFirstFrame() { - FlutterActivityDelegate.this - .launchView - .animate() - .alpha(0f) - // Use Android's default animation duration. - .setListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // Views added to an Activity's addContentView is always added to its - // root FrameLayout. - ((ViewGroup) FlutterActivityDelegate.this.launchView.getParent()) - .removeView(FlutterActivityDelegate.this.launchView); - FlutterActivityDelegate.this.launchView = null; - } - }); - - FlutterActivityDelegate.this.flutterView.removeFirstFrameListener(this); - } - }); - - // Resets the activity theme from the one containing the launch screen in the window - // background to a blank one since the launch screen is now in a view in front of the - // FlutterView. - // - // We can make this configurable if users want it. - activity.setTheme(android.R.style.Theme_Black_NoTitleBar); - } -} diff --git a/shell/platform/android/io/flutter/app/FlutterActivityEvents.java b/shell/platform/android/io/flutter/app/FlutterActivityEvents.java deleted file mode 100644 index abbdec4fe6afa..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterActivityEvents.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import android.content.ComponentCallbacks2; -import android.content.Intent; -import android.os.Bundle; -import io.flutter.plugin.common.PluginRegistry.ActivityResultListener; -import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener; - -/** - * A collection of Android {@code Activity} methods that are relevant to the core operation of - * Flutter applications. - * - *

Application authors that use an activity other than {@link FlutterActivity} should forward all - * events herein from their activity to an instance of {@link FlutterActivityDelegate} in order to - * wire the activity up to the Flutter framework. This forwarding is already provided in {@code - * FlutterActivity}. - */ -public interface FlutterActivityEvents - extends ComponentCallbacks2, ActivityResultListener, RequestPermissionsResultListener { - /** - * @param savedInstanceState If the activity is being re-initialized after previously being shut - * down then this Bundle contains the data it most recently supplied in {@code - * onSaveInstanceState(Bundle)}. - * @see android.app.Activity#onCreate(android.os.Bundle) - */ - void onCreate(Bundle savedInstanceState); - - /** - * @param intent The new intent that was started for the activity. - * @see android.app.Activity#onNewIntent(Intent) - */ - void onNewIntent(Intent intent); - - /** @see android.app.Activity#onPause() */ - void onPause(); - - /** @see android.app.Activity#onStart() */ - void onStart(); - - /** @see android.app.Activity#onResume() */ - void onResume(); - - /** @see android.app.Activity#onPostResume() */ - void onPostResume(); - - /** @see android.app.Activity#onDestroy() */ - void onDestroy(); - - /** @see android.app.Activity#onStop() */ - void onStop(); - - /** - * Invoked when the activity has detected the user's press of the back key. - * - * @return {@code true} if the listener handled the event; {@code false} to let the activity - * continue with its default back button handling. - * @see android.app.Activity#onBackPressed() - */ - boolean onBackPressed(); - - /** @see android.app.Activity#onUserLeaveHint() */ - void onUserLeaveHint(); - - /** - * @param hasFocus True if the current activity window has focus. - * @see android.app.Activity#onWindowFocusChanged(boolean) - */ - void onWindowFocusChanged(boolean hasFocus); -} diff --git a/shell/platform/android/io/flutter/app/FlutterApplication.java b/shell/platform/android/io/flutter/app/FlutterApplication.java deleted file mode 100644 index a211c268548cd..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterApplication.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import android.app.Activity; -import android.app.Application; -import androidx.annotation.CallSuper; -import io.flutter.FlutterInjector; - -/** - * Flutter implementation of {@link android.app.Application}, managing application-level global - * initializations. - * - *

Using this {@link android.app.Application} is not required when using APIs in the package - * {@code io.flutter.embedding.android} since they self-initialize on first use. - */ -public class FlutterApplication extends Application { - @Override - @CallSuper - public void onCreate() { - super.onCreate(); - FlutterInjector.instance().flutterLoader().startInitialization(this); - } - - private Activity mCurrentActivity = null; - - public Activity getCurrentActivity() { - return mCurrentActivity; - } - - public void setCurrentActivity(Activity mCurrentActivity) { - this.mCurrentActivity = mCurrentActivity; - } -} diff --git a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java deleted file mode 100644 index 778bab65bcf00..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Bundle; -import androidx.fragment.app.FragmentActivity; -import io.flutter.app.FlutterActivityDelegate.ViewFactory; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.view.FlutterNativeView; -import io.flutter.view.FlutterView; - -/** - * Deprecated class for activities that use Flutter who also require the use of the Android v4 - * Support library's {@link FragmentActivity}. - * - *

Applications that don't have this need will likely want to use {@link FlutterActivity} - * instead. - * - *

Important! Flutter does not bundle the necessary Android v4 Support library - * classes for this class to work at runtime. It is the responsibility of the app developer using - * this class to ensure that they link against the v4 support library .jar file when creating their - * app to ensure that {@link FragmentActivity} is available at runtime. - * - * @see https://developer.android.com/training/testing/set-up-project - * @deprecated this class is replaced by {@link - * io.flutter.embedding.android.FlutterFragmentActivity}. - */ -@Deprecated -public class FlutterFragmentActivity extends FragmentActivity - implements FlutterView.Provider, PluginRegistry, ViewFactory { - private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this); - - // These aliases ensure that the methods we forward to the delegate adhere - // to relevant interfaces versus just existing in FlutterActivityDelegate. - private final FlutterActivityEvents eventDelegate = delegate; - private final FlutterView.Provider viewProvider = delegate; - private final PluginRegistry pluginRegistry = delegate; - - /** - * Returns the Flutter view used by this activity; will be null before {@link #onCreate(Bundle)} - * is called. - */ - @Override - public FlutterView getFlutterView() { - return viewProvider.getFlutterView(); - } - - /** - * Hook for subclasses to customize the creation of the {@code FlutterView}. - * - *

The default implementation returns {@code null}, which will cause the activity to use a - * newly instantiated full-screen view. - */ - @Override - public FlutterView createFlutterView(Context context) { - return null; - } - - @Override - public FlutterNativeView createFlutterNativeView() { - return null; - } - - @Override - public boolean retainFlutterNativeView() { - return false; - } - - @Override - public final boolean hasPlugin(String key) { - return pluginRegistry.hasPlugin(key); - } - - @Override - public final T valuePublishedByPlugin(String pluginKey) { - return pluginRegistry.valuePublishedByPlugin(pluginKey); - } - - @Override - public final Registrar registrarFor(String pluginKey) { - return pluginRegistry.registrarFor(pluginKey); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - eventDelegate.onCreate(savedInstanceState); - } - - @Override - protected void onDestroy() { - eventDelegate.onDestroy(); - super.onDestroy(); - } - - @Override - public void onBackPressed() { - if (!eventDelegate.onBackPressed()) { - super.onBackPressed(); - } - } - - @Override - protected void onStart() { - super.onStart(); - eventDelegate.onStart(); - } - - @Override - protected void onStop() { - eventDelegate.onStop(); - super.onStop(); - } - - @Override - protected void onPause() { - super.onPause(); - eventDelegate.onPause(); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - eventDelegate.onPostResume(); - } - - @Override - public void onRequestPermissionsResult( - int requestCode, String[] permissions, int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - eventDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (!eventDelegate.onActivityResult(requestCode, resultCode, data)) { - super.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - eventDelegate.onNewIntent(intent); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void onUserLeaveHint() { - eventDelegate.onUserLeaveHint(); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - eventDelegate.onWindowFocusChanged(hasFocus); - } - - @Override - public void onTrimMemory(int level) { - super.onTrimMemory(level); - eventDelegate.onTrimMemory(level); - } - - @Override - public void onLowMemory() { - eventDelegate.onLowMemory(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - eventDelegate.onConfigurationChanged(newConfig); - } -} diff --git a/shell/platform/android/io/flutter/app/FlutterPlayStoreSplitApplication.java b/shell/platform/android/io/flutter/app/FlutterPlayStoreSplitApplication.java deleted file mode 100644 index 7a415d71ff5e6..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterPlayStoreSplitApplication.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import androidx.annotation.CallSuper; -import com.google.android.play.core.splitcompat.SplitCompatApplication; -import io.flutter.FlutterInjector; -import io.flutter.embedding.engine.deferredcomponents.PlayStoreDeferredComponentManager; - -/** - * Flutter's extension of {@link SplitCompatApplication} that injects a {@link - * PlayStoreDeferredComponentManager} with {@link FlutterInjector} to enable Split AOT Flutter apps. - * - *

To use this class, either have your custom application class extend - * FlutterPlayStoreSplitApplication or use it directly in the app's AndroidManifest.xml by adding - * the following line: - * - *

{@code
- * 
- *    
- *  
- * }
- * - * This class is meant to be used with the Google Play store. Custom non-play store applications do - * not need to extend SplitCompatApplication and should inject a custom {@link - * io.flutter.embedding.engine.deferredcomponents.DeferredComponentManager} implementation like so: - * - *
{@code
- * FlutterInjector.setInstance(
- *      new FlutterInjector.Builder().setDeferredComponentManager(yourCustomManager).build());
- * }
- */ -public class FlutterPlayStoreSplitApplication extends SplitCompatApplication { - @Override - @CallSuper - public void onCreate() { - super.onCreate(); - // Create and inject a PlayStoreDeferredComponentManager, which is the default manager for - // interacting with the Google Play Store. - PlayStoreDeferredComponentManager deferredComponentManager = - new PlayStoreDeferredComponentManager(this, null); - FlutterInjector.setInstance( - new FlutterInjector.Builder() - .setDeferredComponentManager(deferredComponentManager) - .build()); - } -} diff --git a/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java b/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java deleted file mode 100644 index 887a9118979cd..0000000000000 --- a/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import io.flutter.embedding.engine.FlutterEngine; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.plugin.platform.PlatformViewRegistry; -import io.flutter.plugin.platform.PlatformViewsController; -import io.flutter.view.FlutterMain; -import io.flutter.view.FlutterNativeView; -import io.flutter.view.FlutterView; -import io.flutter.view.TextureRegistry; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** @deprecated See https://flutter.dev/go/android-project-migration for migration instructions. */ -@Deprecated -public class FlutterPluginRegistry - implements PluginRegistry, - PluginRegistry.RequestPermissionsResultListener, - PluginRegistry.ActivityResultListener, - PluginRegistry.NewIntentListener, - PluginRegistry.WindowFocusChangedListener, - PluginRegistry.UserLeaveHintListener, - PluginRegistry.ViewDestroyListener { - private static final String TAG = "FlutterPluginRegistry"; - - private Activity mActivity; - private Context mAppContext; - private FlutterNativeView mNativeView; - private FlutterView mFlutterView; - - private final PlatformViewsController mPlatformViewsController; - private final Map mPluginMap = new LinkedHashMap<>(0); - private final List mRequestPermissionsResultListeners = - new ArrayList<>(0); - private final List mActivityResultListeners = new ArrayList<>(0); - private final List mNewIntentListeners = new ArrayList<>(0); - private final List mUserLeaveHintListeners = new ArrayList<>(0); - private final List mWindowFocusChangedListeners = new ArrayList<>(0); - private final List mViewDestroyListeners = new ArrayList<>(0); - - public FlutterPluginRegistry(FlutterNativeView nativeView, Context context) { - mNativeView = nativeView; - mAppContext = context; - mPlatformViewsController = new PlatformViewsController(); - } - - public FlutterPluginRegistry(FlutterEngine engine, Context context) { - // TODO(mattcarroll): implement use of engine instead of nativeView. - mAppContext = context; - mPlatformViewsController = new PlatformViewsController(); - } - - @Override - public boolean hasPlugin(String key) { - return mPluginMap.containsKey(key); - } - - @Override - @SuppressWarnings("unchecked") - public T valuePublishedByPlugin(String pluginKey) { - return (T) mPluginMap.get(pluginKey); - } - - @Override - public Registrar registrarFor(String pluginKey) { - if (mPluginMap.containsKey(pluginKey)) { - throw new IllegalStateException("Plugin key " + pluginKey + " is already in use"); - } - mPluginMap.put(pluginKey, null); - return new FlutterRegistrar(pluginKey); - } - - public void attach(FlutterView flutterView, Activity activity) { - mFlutterView = flutterView; - mActivity = activity; - mPlatformViewsController.attach(activity, flutterView, flutterView.getDartExecutor()); - } - - public void detach() { - mPlatformViewsController.detach(); - mPlatformViewsController.onDetachedFromJNI(); - mFlutterView = null; - mActivity = null; - } - - public void onPreEngineRestart() { - mPlatformViewsController.onPreEngineRestart(); - } - - public PlatformViewsController getPlatformViewsController() { - return mPlatformViewsController; - } - - private class FlutterRegistrar implements Registrar { - private final String pluginKey; - - FlutterRegistrar(String pluginKey) { - this.pluginKey = pluginKey; - } - - @Override - public Activity activity() { - return mActivity; - } - - @Override - public Context context() { - return mAppContext; - } - - @Override - public Context activeContext() { - return (mActivity != null) ? mActivity : mAppContext; - } - - @Override - public BinaryMessenger messenger() { - return mNativeView; - } - - @Override - public TextureRegistry textures() { - return mFlutterView; - } - - @Override - public PlatformViewRegistry platformViewRegistry() { - return mPlatformViewsController.getRegistry(); - } - - @Override - public FlutterView view() { - return mFlutterView; - } - - @Override - public String lookupKeyForAsset(String asset) { - return FlutterMain.getLookupKeyForAsset(asset); - } - - @Override - public String lookupKeyForAsset(String asset, String packageName) { - return FlutterMain.getLookupKeyForAsset(asset, packageName); - } - - @Override - public Registrar publish(Object value) { - mPluginMap.put(pluginKey, value); - return this; - } - - @Override - public Registrar addRequestPermissionsResultListener( - RequestPermissionsResultListener listener) { - mRequestPermissionsResultListeners.add(listener); - return this; - } - - @Override - public Registrar addActivityResultListener(ActivityResultListener listener) { - mActivityResultListeners.add(listener); - return this; - } - - @Override - public Registrar addNewIntentListener(NewIntentListener listener) { - mNewIntentListeners.add(listener); - return this; - } - - @Override - public Registrar addUserLeaveHintListener(UserLeaveHintListener listener) { - mUserLeaveHintListeners.add(listener); - return this; - } - - @Override - public Registrar addWindowFocusChangedListener(WindowFocusChangedListener listener) { - mWindowFocusChangedListeners.add(listener); - return this; - } - - @Override - public Registrar addViewDestroyListener(ViewDestroyListener listener) { - mViewDestroyListeners.add(listener); - return this; - } - } - - @Override - public boolean onRequestPermissionsResult( - int requestCode, String[] permissions, int[] grantResults) { - for (RequestPermissionsResultListener listener : mRequestPermissionsResultListeners) { - if (listener.onRequestPermissionsResult(requestCode, permissions, grantResults)) { - return true; - } - } - return false; - } - - @Override - public boolean onActivityResult(int requestCode, int resultCode, Intent data) { - for (ActivityResultListener listener : mActivityResultListeners) { - if (listener.onActivityResult(requestCode, resultCode, data)) { - return true; - } - } - return false; - } - - @Override - public boolean onNewIntent(Intent intent) { - for (NewIntentListener listener : mNewIntentListeners) { - if (listener.onNewIntent(intent)) { - return true; - } - } - return false; - } - - @Override - public void onUserLeaveHint() { - for (UserLeaveHintListener listener : mUserLeaveHintListeners) { - listener.onUserLeaveHint(); - } - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - for (WindowFocusChangedListener listener : mWindowFocusChangedListeners) { - listener.onWindowFocusChanged(hasFocus); - } - } - - @Override - public boolean onViewDestroy(FlutterNativeView view) { - boolean handled = false; - for (ViewDestroyListener listener : mViewDestroyListeners) { - if (listener.onViewDestroy(view)) { - handled = true; - } - } - return handled; - } - - public void destroy() { - mPlatformViewsController.onDetachedFromJNI(); - } -} diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 389e866829f09..4747abac87ecc 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -1039,8 +1039,7 @@ private native void nativeRunBundleAndSnapshotFromLibrary( * will be dropped (ignored). Therefore, when using {@code FlutterJNI} to integrate a Flutter * context in an app, a {@link PlatformMessageHandler} must be registered for 2-way Java/Dart * communication to operate correctly. Moreover, the handler must be implemented such that - * fundamental platform messages are handled as expected. See {@link - * io.flutter.view.FlutterNativeView} for an example implementation. + * fundamental platform messages are handled as expected. */ @UiThread public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler) { diff --git a/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java b/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java deleted file mode 100644 index ed41d1d65f307..0000000000000 --- a/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.embedding.engine.plugins.shim; - -import androidx.annotation.NonNull; -import io.flutter.Log; -import io.flutter.embedding.engine.FlutterEngine; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.embedding.engine.plugins.activity.ActivityAware; -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import io.flutter.plugin.common.PluginRegistry; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * A {@link PluginRegistry} that is shimmed to let old plugins use the new Android embedding and - * plugin API behind the scenes. - * - *

The following is an example usage of {@code ShimPluginRegistry} within a {@code - * FlutterActivity}: - * - *

- * // Create the FlutterEngine that will back the Flutter UI.
- * FlutterEngineGroup group = new FlutterEngineGroup(context);
- * FlutterEngine flutterEngine = group.createAndRunDefaultEngine(context);
- *
- * // Create a ShimPluginRegistry and wrap the FlutterEngine with the shim.
- * ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine, platformViewsController);
- *
- * // Use the GeneratedPluginRegistrant to add every plugin that's in the pubspec.
- * GeneratedPluginRegistrant.registerWith(shimPluginRegistry);
- * 
- */ -public class ShimPluginRegistry implements PluginRegistry { - private static final String TAG = "ShimPluginRegistry"; - - private final FlutterEngine flutterEngine; - private final Map pluginMap = new HashMap<>(); - private final ShimRegistrarAggregate shimRegistrarAggregate; - - public ShimPluginRegistry(@NonNull FlutterEngine flutterEngine) { - this.flutterEngine = flutterEngine; - this.shimRegistrarAggregate = new ShimRegistrarAggregate(); - this.flutterEngine.getPlugins().add(shimRegistrarAggregate); - } - - @Override - @NonNull - public Registrar registrarFor(@NonNull String pluginKey) { - Log.v(TAG, "Creating plugin Registrar for '" + pluginKey + "'"); - if (pluginMap.containsKey(pluginKey)) { - throw new IllegalStateException("Plugin key " + pluginKey + " is already in use"); - } - pluginMap.put(pluginKey, null); - ShimRegistrar registrar = new ShimRegistrar(pluginKey, pluginMap); - shimRegistrarAggregate.addPlugin(registrar); - return registrar; - } - - @Override - public boolean hasPlugin(@NonNull String pluginKey) { - return pluginMap.containsKey(pluginKey); - } - - @Override - @SuppressWarnings("unchecked") - public T valuePublishedByPlugin(@NonNull String pluginKey) { - return (T) pluginMap.get(pluginKey); - } - - /** - * Aggregates all {@link ShimRegistrar}s within one single {@link FlutterPlugin}. - * - *

The reason we need this aggregate is because the new embedding uniquely identifies plugins - * by their plugin class, but the plugin shim system represents every plugin with a {@link - * ShimRegistrar}. Therefore, every plugin we would register after the first plugin, would - * overwrite the previous plugin, because they're all {@link ShimRegistrar} instances. - * - *

{@code ShimRegistrarAggregate} multiplexes {@link FlutterPlugin} and {@link ActivityAware} - * calls so that we can register just one {@code ShimRegistrarAggregate} with a {@link - * FlutterEngine}, while forwarding the relevant plugin resources to any number of {@link - * ShimRegistrar}s within this {@code ShimRegistrarAggregate}. - */ - private static class ShimRegistrarAggregate implements FlutterPlugin, ActivityAware { - private final Set shimRegistrars = new HashSet<>(); - private FlutterPluginBinding flutterPluginBinding; - private ActivityPluginBinding activityPluginBinding; - - public void addPlugin(@NonNull ShimRegistrar shimRegistrar) { - shimRegistrars.add(shimRegistrar); - - if (flutterPluginBinding != null) { - shimRegistrar.onAttachedToEngine(flutterPluginBinding); - } - if (activityPluginBinding != null) { - shimRegistrar.onAttachedToActivity(activityPluginBinding); - } - } - - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - flutterPluginBinding = binding; - for (ShimRegistrar shimRegistrar : shimRegistrars) { - shimRegistrar.onAttachedToEngine(binding); - } - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - for (ShimRegistrar shimRegistrar : shimRegistrars) { - shimRegistrar.onDetachedFromEngine(binding); - } - flutterPluginBinding = null; - activityPluginBinding = null; - } - - @Override - public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - activityPluginBinding = binding; - for (ShimRegistrar shimRegistrar : shimRegistrars) { - shimRegistrar.onAttachedToActivity(binding); - } - } - - @Override - public void onDetachedFromActivityForConfigChanges() { - for (ShimRegistrar shimRegistrar : shimRegistrars) { - shimRegistrar.onDetachedFromActivity(); - } - activityPluginBinding = null; - } - - @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { - activityPluginBinding = binding; - for (ShimRegistrar shimRegistrar : shimRegistrars) { - shimRegistrar.onReattachedToActivityForConfigChanges(binding); - } - } - - @Override - public void onDetachedFromActivity() { - for (ShimRegistrar shimRegistrar : shimRegistrars) { - shimRegistrar.onDetachedFromActivity(); - } - activityPluginBinding = null; - } - } -} diff --git a/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java b/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java deleted file mode 100644 index d27da01dae04b..0000000000000 --- a/shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimRegistrar.java +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.embedding.engine.plugins.shim; - -import android.app.Activity; -import android.content.Context; -import androidx.annotation.NonNull; -import io.flutter.FlutterInjector; -import io.flutter.Log; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.embedding.engine.plugins.activity.ActivityAware; -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.plugin.platform.PlatformViewRegistry; -import io.flutter.view.FlutterView; -import io.flutter.view.TextureRegistry; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * A {@link PluginRegistry.Registrar} that is shimmed let old plugins use the new Android embedding - * and plugin API behind the scenes. - * - *

Instances of {@code ShimRegistrar}s are vended internally by a {@link ShimPluginRegistry}. - */ -class ShimRegistrar implements PluginRegistry.Registrar, FlutterPlugin, ActivityAware { - private static final String TAG = "ShimRegistrar"; - - private final Map globalRegistrarMap; - private final String pluginId; - private final Set viewDestroyListeners = new HashSet<>(); - private final Set - requestPermissionsResultListeners = new HashSet<>(); - private final Set activityResultListeners = - new HashSet<>(); - private final Set newIntentListeners = new HashSet<>(); - private final Set userLeaveHintListeners = new HashSet<>(); - private final Set WindowFocusChangedListeners = - new HashSet<>(); - private FlutterPlugin.FlutterPluginBinding pluginBinding; - private ActivityPluginBinding activityPluginBinding; - - public ShimRegistrar(@NonNull String pluginId, @NonNull Map globalRegistrarMap) { - this.pluginId = pluginId; - this.globalRegistrarMap = globalRegistrarMap; - } - - @Override - public Activity activity() { - return activityPluginBinding != null ? activityPluginBinding.getActivity() : null; - } - - @Override - public Context context() { - return pluginBinding != null ? pluginBinding.getApplicationContext() : null; - } - - @Override - public Context activeContext() { - return activityPluginBinding == null ? context() : activity(); - } - - @Override - public BinaryMessenger messenger() { - return pluginBinding != null ? pluginBinding.getBinaryMessenger() : null; - } - - @Override - public TextureRegistry textures() { - return pluginBinding != null ? pluginBinding.getTextureRegistry() : null; - } - - @Override - public PlatformViewRegistry platformViewRegistry() { - return pluginBinding != null ? pluginBinding.getPlatformViewRegistry() : null; - } - - @Override - public FlutterView view() { - throw new UnsupportedOperationException( - "The new embedding does not support the old FlutterView."); - } - - @Override - public String lookupKeyForAsset(String asset) { - return FlutterInjector.instance().flutterLoader().getLookupKeyForAsset(asset); - } - - @Override - public String lookupKeyForAsset(String asset, String packageName) { - return FlutterInjector.instance().flutterLoader().getLookupKeyForAsset(asset, packageName); - } - - @Override - public PluginRegistry.Registrar publish(Object value) { - globalRegistrarMap.put(pluginId, value); - return this; - } - - @Override - public PluginRegistry.Registrar addRequestPermissionsResultListener( - PluginRegistry.RequestPermissionsResultListener listener) { - requestPermissionsResultListeners.add(listener); - - if (activityPluginBinding != null) { - activityPluginBinding.addRequestPermissionsResultListener(listener); - } - - return this; - } - - @Override - public PluginRegistry.Registrar addActivityResultListener( - PluginRegistry.ActivityResultListener listener) { - activityResultListeners.add(listener); - - if (activityPluginBinding != null) { - activityPluginBinding.addActivityResultListener(listener); - } - - return this; - } - - @Override - public PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener listener) { - newIntentListeners.add(listener); - - if (activityPluginBinding != null) { - activityPluginBinding.addOnNewIntentListener(listener); - } - - return this; - } - - @Override - public PluginRegistry.Registrar addUserLeaveHintListener( - PluginRegistry.UserLeaveHintListener listener) { - userLeaveHintListeners.add(listener); - - if (activityPluginBinding != null) { - activityPluginBinding.addOnUserLeaveHintListener(listener); - } - - return this; - } - - @Override - public PluginRegistry.Registrar addWindowFocusChangedListener( - PluginRegistry.WindowFocusChangedListener listener) { - WindowFocusChangedListeners.add(listener); - - if (activityPluginBinding != null) { - activityPluginBinding.addOnWindowFocusChangedListener(listener); - } - - return this; - } - - @Override - @NonNull - public PluginRegistry.Registrar addViewDestroyListener( - @NonNull PluginRegistry.ViewDestroyListener listener) { - viewDestroyListeners.add(listener); - return this; - } - - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - Log.v(TAG, "Attached to FlutterEngine."); - pluginBinding = binding; - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - Log.v(TAG, "Detached from FlutterEngine."); - for (PluginRegistry.ViewDestroyListener listener : viewDestroyListeners) { - // The following invocation might produce unexpected behavior in old plugins because - // we have no FlutterNativeView to pass to onViewDestroy(). This is a limitation of this shim. - listener.onViewDestroy(null); - } - - pluginBinding = null; - activityPluginBinding = null; - } - - @Override - public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - Log.v(TAG, "Attached to an Activity."); - activityPluginBinding = binding; - addExistingListenersToActivityPluginBinding(); - } - - @Override - public void onDetachedFromActivityForConfigChanges() { - Log.v(TAG, "Detached from an Activity for config changes."); - activityPluginBinding = null; - } - - @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { - Log.v(TAG, "Reconnected to an Activity after config changes."); - activityPluginBinding = binding; - addExistingListenersToActivityPluginBinding(); - } - - @Override - public void onDetachedFromActivity() { - Log.v(TAG, "Detached from an Activity."); - activityPluginBinding = null; - } - - private void addExistingListenersToActivityPluginBinding() { - for (PluginRegistry.RequestPermissionsResultListener listener : - requestPermissionsResultListeners) { - activityPluginBinding.addRequestPermissionsResultListener(listener); - } - for (PluginRegistry.ActivityResultListener listener : activityResultListeners) { - activityPluginBinding.addActivityResultListener(listener); - } - for (PluginRegistry.NewIntentListener listener : newIntentListeners) { - activityPluginBinding.addOnNewIntentListener(listener); - } - for (PluginRegistry.UserLeaveHintListener listener : userLeaveHintListeners) { - activityPluginBinding.addOnUserLeaveHintListener(listener); - } - for (PluginRegistry.WindowFocusChangedListener listener : WindowFocusChangedListeners) { - activityPluginBinding.addOnWindowFocusChangedListener(listener); - } - } -} diff --git a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java index 4859617d93b29..977b995ecf63a 100644 --- a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java +++ b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java @@ -5,353 +5,13 @@ package io.flutter.plugin.common; import android.app.Activity; -import android.content.Context; import android.content.Intent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import io.flutter.plugin.platform.PlatformViewRegistry; -import io.flutter.view.FlutterNativeView; -import io.flutter.view.FlutterView; -import io.flutter.view.TextureRegistry; -/** - * Container class for Android API listeners used by {@link ActivityPluginBinding}. - * - *

This class also contains deprecated v1 embedding APIs used for plugin registration. - * - *

In v1 Android applications, an auto-generated and auto-updated plugin registrant class - * (GeneratedPluginRegistrant) makes use of a {@link PluginRegistry} to register contributions from - * each plugin mentioned in the application's pubspec file. The generated registrant class is, again - * by default, called from the application's main {@link android.app.Activity}, which defaults to an - * instance of {@link io.flutter.app.FlutterActivity}, itself a {@link PluginRegistry}. - */ +/** Container class for Android API listeners used by {@link ActivityPluginBinding}. */ public interface PluginRegistry { - /** - * Returns a {@link Registrar} for receiving the registrations pertaining to the specified plugin. - * - * @param pluginKey a unique String identifying the plugin; typically the fully qualified name of - * the plugin's main class. - * @return A {@link Registrar} for receiving the registrations pertianing to the specified plugin. - * @deprecated See https://flutter.dev/go/android-project-migration for migration details. - */ - @Deprecated - @NonNull - Registrar registrarFor(@NonNull String pluginKey); - - /** - * Returns whether the specified plugin is known to this registry. - * - * @param pluginKey a unique String identifying the plugin; typically the fully qualified name of - * the plugin's main class. - * @return true if this registry has handed out a registrar for the specified plugin. - * @deprecated See https://flutter.dev/go/android-project-migration for migration details. - */ - @Deprecated - boolean hasPlugin(@NonNull String pluginKey); - - /** - * Returns the value published by the specified plugin, if any. - * - *

Plugins may publish a single value, such as an instance of the plugin's main class, for - * situations where external control or interaction is needed. Clients are expected to know the - * value's type. - * - * @param The type of the value. - * @param pluginKey a unique String identifying the plugin; typically the fully qualified name of - * the plugin's main class. - * @return the published value, possibly null. - * @deprecated See https://flutter.dev/go/android-project-migration for migration details. - */ - @Deprecated - @Nullable - T valuePublishedByPlugin(@NonNull String pluginKey); - - /** - * Receiver of registrations from a single plugin. - * - * @deprecated This registrar is for Flutter's v1 embedding. For instructions on migrating a - * plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @Deprecated - interface Registrar { - /** - * Returns the {@link android.app.Activity} that forms the plugin's operating context. - * - *

Plugin authors should not assume the type returned by this method is any specific subclass - * of {@code Activity} (such as {@link io.flutter.app.FlutterActivity} or {@link - * io.flutter.app.FlutterFragmentActivity}), as applications are free to use any activity - * subclass. - * - *

When there is no foreground activity in the application, this will return null. If a - * {@link Context} is needed, use context() to get the application's context. - * - *

This registrar is for Flutter's v1 embedding. To access an {@code Activity} from a plugin - * using the v2 embedding, see {@link ActivityPluginBinding#getActivity()}. To obtain an - * instance of an {@link ActivityPluginBinding} in a Flutter plugin, implement the {@link - * ActivityAware} interface. A binding is provided in {@link - * ActivityAware#onAttachedToActivity(ActivityPluginBinding)} and {@link - * ActivityAware#onReattachedToActivityForConfigChanges(ActivityPluginBinding)}. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @Nullable - Activity activity(); - - /** - * Returns the {@link android.app.Application}'s {@link Context}. - * - *

This registrar is for Flutter's v1 embedding. To access a {@code Context} from a plugin - * using the v2 embedding, see {@link - * FlutterPlugin.FlutterPluginBinding#getApplicationContext()} - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @NonNull - Context context(); - - /** - * Returns the active {@link Context}. - * - *

This registrar is for Flutter's v1 embedding. In the v2 embedding, there is no concept of - * an "active context". Either use the application {@code Context} or an attached {@code - * Activity}. See {@link #context()} and {@link #activity()} for more details. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @return the current {@link #activity() Activity}, if not null, otherwise the {@link - * #context() Application}. - */ - @NonNull - Context activeContext(); - - /** - * Returns a {@link BinaryMessenger} which the plugin can use for creating channels for - * communicating with the Dart side. - * - *

This registrar is for Flutter's v1 embedding. To access a {@code BinaryMessenger} from a - * plugin using the v2 embedding, see {@link - * FlutterPlugin.FlutterPluginBinding#getBinaryMessenger()} - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @NonNull - BinaryMessenger messenger(); - - /** - * Returns a {@link TextureRegistry} which the plugin can use for managing backend textures. - * - *

This registrar is for Flutter's v1 embedding. To access a {@code TextureRegistry} from a - * plugin using the v2 embedding, see {@link - * FlutterPlugin.FlutterPluginBinding#getTextureRegistry()} - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @NonNull - TextureRegistry textures(); - - /** - * Returns the application's {@link PlatformViewRegistry}. - * - *

Plugins can use the platform registry to register their view factories. - * - *

This registrar is for Flutter's v1 embedding. To access a {@code PlatformViewRegistry} - * from a plugin using the v2 embedding, see {@link - * FlutterPlugin.FlutterPluginBinding#getPlatformViewRegistry()} - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @NonNull - PlatformViewRegistry platformViewRegistry(); - - /** - * Returns the {@link FlutterView} that's instantiated by this plugin's {@link #activity() - * activity}. - * - *

This registrar is for Flutter's v1 embedding. The {@link FlutterView} referenced by this - * method does not exist in the v2 embedding. Additionally, no {@code View} is exposed to any - * plugins in the v2 embedding. Platform views can access their containing {@code View} using - * the platform views APIs. If you have a use-case that absolutely requires a plugin to access - * an Android {@code View}, please file a ticket on GitHub. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - */ - @NonNull - FlutterView view(); - - /** - * Returns the file name for the given asset. The returned file name can be used to access the - * asset in the APK through the {@link android.content.res.AssetManager} API. - * - *

TODO(mattcarroll): point this method towards new lookup method. - * - * @param asset the name of the asset. The name can be hierarchical - * @return the filename to be used with {@link android.content.res.AssetManager} - */ - @NonNull - String lookupKeyForAsset(@NonNull String asset); - - /** - * Returns the file name for the given asset which originates from the specified packageName. - * The returned file name can be used to access the asset in the APK through the {@link - * android.content.res.AssetManager} API. - * - *

TODO(mattcarroll): point this method towards new lookup method. - * - * @param asset the name of the asset. The name can be hierarchical - * @param packageName the name of the package from which the asset originates - * @return the file name to be used with {@link android.content.res.AssetManager} - */ - @NonNull - String lookupKeyForAsset(@NonNull String asset, @NonNull String packageName); - - /** - * Publishes a value associated with the plugin being registered. - * - *

The published value is available to interested clients via {@link - * PluginRegistry#valuePublishedByPlugin(String)}. - * - *

Publication should be done only when client code needs to interact with the plugin in a - * way that cannot be accomplished by the plugin registering callbacks with client APIs. - * - *

Overwrites any previously published value. - * - *

This registrar is for Flutter's v1 embedding. The concept of publishing values from - * plugins is not supported in the v2 embedding. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param value the value, possibly null. - * @return this {@link Registrar}. - */ - @NonNull - Registrar publish(@Nullable Object value); - - /** - * Adds a callback allowing the plugin to take part in handling incoming calls to {@code - * Activity#onRequestPermissionsResult(int, String[], int[])} or {@code - * androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, - * String[], int[])}. - * - *

This registrar is for Flutter's v1 embedding. To listen for permission results in the v2 - * embedding, use {@link - * ActivityPluginBinding#addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener)}. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param listener a {@link RequestPermissionsResultListener} callback. - * @return this {@link Registrar}. - */ - @NonNull - Registrar addRequestPermissionsResultListener( - @NonNull RequestPermissionsResultListener listener); - - /** - * Adds a callback allowing the plugin to take part in handling incoming calls to {@link - * Activity#onActivityResult(int, int, Intent)}. - * - *

This registrar is for Flutter's v1 embedding. To listen for {@code Activity} results in - * the v2 embedding, use {@link - * ActivityPluginBinding#addActivityResultListener(PluginRegistry.ActivityResultListener)}. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param listener an {@link ActivityResultListener} callback. - * @return this {@link Registrar}. - */ - @NonNull - Registrar addActivityResultListener(@NonNull ActivityResultListener listener); - - /** - * Adds a callback allowing the plugin to take part in handling incoming calls to {@link - * Activity#onNewIntent(Intent)}. - * - *

This registrar is for Flutter's v1 embedding. To listen for new {@code Intent}s in the v2 - * embedding, use {@link - * ActivityPluginBinding#addOnNewIntentListener(PluginRegistry.NewIntentListener)}. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param listener a {@link NewIntentListener} callback. - * @return this {@link Registrar}. - */ - @NonNull - Registrar addNewIntentListener(@NonNull NewIntentListener listener); - - /** - * Adds a callback allowing the plugin to take part in handling incoming calls to {@link - * Activity#onUserLeaveHint()}. - * - *

This registrar is for Flutter's v1 embedding. To listen for leave hints in the v2 - * embedding, use {@link - * ActivityPluginBinding#addOnUserLeaveHintListener(PluginRegistry.UserLeaveHintListener)}. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param listener a {@link UserLeaveHintListener} callback. - * @return this {@link Registrar}. - */ - @NonNull - Registrar addUserLeaveHintListener(@NonNull UserLeaveHintListener listener); - - /** - * Adds a callback allowing the plugin to take part in handling incoming calls to {@link - * Activity#onWindowFocusChanged(boolean)}. - * - *

This registrar is for Flutter's v1 embedding. To listen for leave hints in the v2 - * embedding, use {@link - * ActivityPluginBinding#addOnWindowFocusChangedListener(PluginRegistry.WindowFocusChangedListener)}. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param listener a {@link WindowFocusChangedListener} callback. - * @return this {@link Registrar}. - */ - @NonNull - Registrar addWindowFocusChangedListener(@NonNull WindowFocusChangedListener listener); - - /** - * Adds a callback allowing the plugin to take part in handling incoming calls to {@link - * Activity#onDestroy()}. - * - *

This registrar is for Flutter's v1 embedding. The concept of {@code View} destruction does - * not exist in the v2 embedding. However, plugins in the v2 embedding can respond to {@link - * ActivityAware#onDetachedFromActivityForConfigChanges()} and {@link - * ActivityAware#onDetachedFromActivity()}, which indicate the loss of a visual context for the - * running Flutter experience. Developers should implement {@link ActivityAware} for their - * {@link FlutterPlugin} if such callbacks are needed. Also, plugins can respond to {@link - * FlutterPlugin#onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding)}, which indicates that - * the given plugin has been completely disconnected from the associated Flutter experience and - * should clean up any resources. - * - *

For instructions on migrating a plugin from Flutter's v1 Android embedding to v2, visit - * http://flutter.dev/go/android-plugin-migration - * - * @param listener a {@link ViewDestroyListener} callback. - * @return this {@link Registrar}. - */ - // TODO(amirh): Add a line in the javadoc above that points to a Platform Views website guide - // when one is available (but not a website API doc) - @NonNull - Registrar addViewDestroyListener(@NonNull ViewDestroyListener listener); - } - /** * Delegate interface for handling result of permissions requests on behalf of the main {@link * Activity}. @@ -412,29 +72,4 @@ interface UserLeaveHintListener { interface WindowFocusChangedListener { void onWindowFocusChanged(boolean hasFocus); } - - /** - * Delegate interface for handling an {@link android.app.Activity}'s onDestroy method being - * called. A plugin that implements this interface can adopt the {@link FlutterNativeView} by - * retaining a reference and returning true. - * - * @deprecated See https://flutter.dev/go/android-project-migration for migration details. - */ - @Deprecated - interface ViewDestroyListener { - boolean onViewDestroy(@NonNull FlutterNativeView view); - } - - /** - * Callback interface for registering plugins with a plugin registry. - * - *

For example, an Application may use this callback interface to provide a background service - * with a callback for calling its GeneratedPluginRegistrant.registerWith method. - * - * @deprecated See https://flutter.dev/go/android-project-migration for migration details. - */ - @Deprecated - interface PluginRegistrantCallback { - void registerWith(@NonNull PluginRegistry registry); - } } diff --git a/shell/platform/android/io/flutter/plugin/editing/ListenableEditingState.java b/shell/platform/android/io/flutter/plugin/editing/ListenableEditingState.java index d887cdb8a8e9b..ea1d75a6a173c 100644 --- a/shell/platform/android/io/flutter/plugin/editing/ListenableEditingState.java +++ b/shell/platform/android/io/flutter/plugin/editing/ListenableEditingState.java @@ -18,7 +18,7 @@ /// The current editing state (text, selection range, composing range) the text input plugin holds. /// /// As the name implies, this class also notifies its listeners when the editing state changes. When -/// there're ongoing batch edits, change notifications will be deferred until all batch edits end +/// there are ongoing batch edits, change notifications will be deferred until all batch edits end /// (i.e. when the outermost batch edit ends). Listeners added during a batch edit will always be /// notified when all batch edits end, even if there's no real change. /// diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index e585a1392b602..e4bf714010efb 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -44,9 +44,8 @@ /** * Manages platform views. * - *

Each {@link io.flutter.embedding.engine.FlutterEngine} or {@link - * io.flutter.app.FlutterPluginRegistry} has a single platform views controller. A platform views - * controller can be attached to at most one Flutter view. + *

Each {@link io.flutter.embedding.engine.FlutterEngine} has a single platform views controller. + * A platform views controller can be attached to at most one Flutter view. */ public class PlatformViewsController implements PlatformViewsAccessibilityDelegate { private static final String TAG = "PlatformViewsController"; diff --git a/shell/platform/android/io/flutter/view/FlutterMain.java b/shell/platform/android/io/flutter/view/FlutterMain.java deleted file mode 100644 index 2092830111fa1..0000000000000 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.view; - -import android.content.Context; -import android.os.Handler; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import io.flutter.FlutterInjector; -import io.flutter.embedding.engine.loader.FlutterLoader; - -/** - * A legacy class to initialize the Flutter engine. - * - * @deprecated Replaced by {@link io.flutter.embedding.engine.loader.FlutterLoader}. - */ -@Deprecated -public class FlutterMain { - - public static class Settings { - private String logTag; - - @Nullable - public String getLogTag() { - return logTag; - } - - /** - * Set the tag associated with Flutter app log messages. - * - * @param tag Log tag. - */ - public void setLogTag(String tag) { - logTag = tag; - } - } - - /** - * Starts initialization of the native system. - * - * @param applicationContext The Android application context. - */ - public static void startInitialization(@NonNull Context applicationContext) { - FlutterInjector.instance().flutterLoader().startInitialization(applicationContext); - } - - /** - * Starts initialization of the native system. - * - *

This loads the Flutter engine's native library to enable subsequent JNI calls. This also - * starts locating and unpacking Dart resources packaged in the app's APK. - * - *

Calling this method multiple times has no effect. - * - * @param applicationContext The Android application context. - * @param settings Configuration settings. - */ - public static void startInitialization( - @NonNull Context applicationContext, @NonNull Settings settings) { - FlutterLoader.Settings newSettings = new FlutterLoader.Settings(); - newSettings.setLogTag(settings.getLogTag()); - FlutterInjector.instance().flutterLoader().startInitialization(applicationContext, newSettings); - } - - /** - * Blocks until initialization of the native system has completed. - * - *

Calling this method multiple times has no effect. - * - * @param applicationContext The Android application context. - * @param args Flags sent to the Flutter runtime. - */ - public static void ensureInitializationComplete( - @NonNull Context applicationContext, @Nullable String[] args) { - FlutterInjector.instance() - .flutterLoader() - .ensureInitializationComplete(applicationContext, args); - } - - /** - * Same as {@link #ensureInitializationComplete(Context, String[])} but waiting on a background - * thread, then invoking {@code callback} on the {@code callbackHandler}. - */ - public static void ensureInitializationCompleteAsync( - @NonNull Context applicationContext, - @Nullable String[] args, - @NonNull Handler callbackHandler, - @NonNull Runnable callback) { - FlutterInjector.instance() - .flutterLoader() - .ensureInitializationCompleteAsync(applicationContext, args, callbackHandler, callback); - } - - @NonNull - public static String findAppBundlePath() { - return FlutterInjector.instance().flutterLoader().findAppBundlePath(); - } - - @Deprecated - @Nullable - public static String findAppBundlePath(@NonNull Context applicationContext) { - return FlutterInjector.instance().flutterLoader().findAppBundlePath(); - } - - /** - * Returns the file name for the given asset. The returned file name can be used to access the - * asset in the APK through the {@link android.content.res.AssetManager} API. - * - * @param asset the name of the asset. The name can be hierarchical - * @return the filename to be used with {@link android.content.res.AssetManager} - */ - @NonNull - public static String getLookupKeyForAsset(@NonNull String asset) { - return FlutterInjector.instance().flutterLoader().getLookupKeyForAsset(asset); - } - - /** - * Returns the file name for the given asset which originates from the specified packageName. The - * returned file name can be used to access the asset in the APK through the {@link - * android.content.res.AssetManager} API. - * - * @param asset the name of the asset. The name can be hierarchical - * @param packageName the name of the package from which the asset originates - * @return the file name to be used with {@link android.content.res.AssetManager} - */ - @NonNull - public static String getLookupKeyForAsset(@NonNull String asset, @NonNull String packageName) { - return FlutterInjector.instance().flutterLoader().getLookupKeyForAsset(asset, packageName); - } -} diff --git a/shell/platform/android/io/flutter/view/FlutterNativeView.java b/shell/platform/android/io/flutter/view/FlutterNativeView.java deleted file mode 100644 index 2f027695b5ad3..0000000000000 --- a/shell/platform/android/io/flutter/view/FlutterNativeView.java +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.view; - -import android.app.Activity; -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.UiThread; -import io.flutter.Log; -import io.flutter.app.FlutterPluginRegistry; -import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener; -import io.flutter.embedding.engine.FlutterJNI; -import io.flutter.embedding.engine.dart.DartExecutor; -import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; -import io.flutter.plugin.common.*; -import java.nio.ByteBuffer; - -/** - * @deprecated {@link io.flutter.embedding.android.FlutterView} is the new API that now replaces - * this class. See https://flutter.dev/go/android-project-migration for more migration details. - */ -@Deprecated -public class FlutterNativeView implements BinaryMessenger { - private static final String TAG = "FlutterNativeView"; - - private final FlutterPluginRegistry mPluginRegistry; - private final DartExecutor dartExecutor; - private FlutterView mFlutterView; - private final FlutterJNI mFlutterJNI; - private final Context mContext; - private boolean applicationIsRunning; - - private final FlutterUiDisplayListener flutterUiDisplayListener = - new FlutterUiDisplayListener() { - @Override - public void onFlutterUiDisplayed() { - if (mFlutterView == null) { - return; - } - mFlutterView.onFirstFrame(); - } - - @Override - public void onFlutterUiNoLongerDisplayed() { - // no-op - } - }; - - public FlutterNativeView(@NonNull Context context) { - this(context, false); - } - - public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) { - if (isBackgroundView) { - Log.w(TAG, "'isBackgroundView' is no longer supported and will be ignored"); - } - mContext = context; - mPluginRegistry = new FlutterPluginRegistry(this, context); - mFlutterJNI = new FlutterJNI(); - mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener); - this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets()); - mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl()); - attach(this); - assertAttached(); - } - - public void detachFromFlutterView() { - mPluginRegistry.detach(); - mFlutterView = null; - } - - public void destroy() { - mPluginRegistry.destroy(); - dartExecutor.onDetachedFromJNI(); - mFlutterView = null; - mFlutterJNI.removeIsDisplayingFlutterUiListener(flutterUiDisplayListener); - mFlutterJNI.detachFromNativeAndReleaseResources(); - applicationIsRunning = false; - } - - @NonNull - public DartExecutor getDartExecutor() { - return dartExecutor; - } - - @NonNull - public FlutterPluginRegistry getPluginRegistry() { - return mPluginRegistry; - } - - public void attachViewAndActivity(FlutterView flutterView, Activity activity) { - mFlutterView = flutterView; - mPluginRegistry.attach(flutterView, activity); - } - - public boolean isAttached() { - return mFlutterJNI.isAttached(); - } - - public void assertAttached() { - if (!isAttached()) throw new AssertionError("Platform view is not attached"); - } - - public void runFromBundle(FlutterRunArguments args) { - if (args.entrypoint == null) { - throw new AssertionError("An entrypoint must be specified"); - } - assertAttached(); - if (applicationIsRunning) - throw new AssertionError("This Flutter engine instance is already running an application"); - mFlutterJNI.runBundleAndSnapshotFromLibrary( - args.bundlePath, - args.entrypoint, - args.libraryPath, - mContext.getResources().getAssets(), - null); - - applicationIsRunning = true; - } - - public boolean isApplicationRunning() { - return applicationIsRunning; - } - - @Deprecated - public static String getObservatoryUri() { - return FlutterJNI.getVMServiceUri(); - } - - public static String getVMServiceUri() { - return FlutterJNI.getVMServiceUri(); - } - - @Override - @UiThread - public TaskQueue makeBackgroundTaskQueue(TaskQueueOptions options) { - return dartExecutor.getBinaryMessenger().makeBackgroundTaskQueue(options); - } - - @Override - @UiThread - public void send(String channel, ByteBuffer message) { - dartExecutor.getBinaryMessenger().send(channel, message); - } - - @Override - @UiThread - public void send(String channel, ByteBuffer message, BinaryReply callback) { - if (!isAttached()) { - Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel); - return; - } - - dartExecutor.getBinaryMessenger().send(channel, message, callback); - } - - @Override - @UiThread - public void setMessageHandler(String channel, BinaryMessageHandler handler) { - dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler); - } - - @Override - @UiThread - public void setMessageHandler(String channel, BinaryMessageHandler handler, TaskQueue taskQueue) { - dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler, taskQueue); - } - - @Override - public void enableBufferingIncomingMessages() {} - - @Override - public void disableBufferingIncomingMessages() {} - - /*package*/ FlutterJNI getFlutterJNI() { - return mFlutterJNI; - } - - private void attach(FlutterNativeView view) { - mFlutterJNI.attachToNative(); - dartExecutor.onAttachedToJNI(); - } - - private final class EngineLifecycleListenerImpl implements EngineLifecycleListener { - // Called by native to notify right before the engine is restarted (cold reload). - @SuppressWarnings("unused") - public void onPreEngineRestart() { - if (mFlutterView != null) { - mFlutterView.resetAccessibilityTree(); - } - if (mPluginRegistry == null) { - return; - } - mPluginRegistry.onPreEngineRestart(); - } - - public void onEngineWillDestroy() { - // The old embedding doesn't actually have a FlutterEngine. It interacts with the JNI - // directly. - } - } -} diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java deleted file mode 100644 index 8dbdae146ef83..0000000000000 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ /dev/null @@ -1,992 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.view; - -import static io.flutter.Build.API_LEVELS; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.Insets; -import android.graphics.PixelFormat; -import android.graphics.SurfaceTexture; -import android.os.Build; -import android.os.Handler; -import android.text.format.DateFormat; -import android.util.AttributeSet; -import android.util.SparseArray; -import android.view.DisplayCutout; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.PointerIcon; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewStructure; -import android.view.WindowInsets; -import android.view.WindowManager; -import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.AccessibilityNodeProvider; -import android.view.autofill.AutofillValue; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputMethodManager; -import android.window.BackEvent; -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; -import androidx.annotation.UiThread; -import io.flutter.Log; -import io.flutter.app.FlutterPluginRegistry; -import io.flutter.embedding.android.AndroidTouchProcessor; -import io.flutter.embedding.android.KeyboardManager; -import io.flutter.embedding.engine.dart.DartExecutor; -import io.flutter.embedding.engine.renderer.FlutterRenderer; -import io.flutter.embedding.engine.renderer.SurfaceTextureWrapper; -import io.flutter.embedding.engine.systemchannels.AccessibilityChannel; -import io.flutter.embedding.engine.systemchannels.BackGestureChannel; -import io.flutter.embedding.engine.systemchannels.LifecycleChannel; -import io.flutter.embedding.engine.systemchannels.LocalizationChannel; -import io.flutter.embedding.engine.systemchannels.MouseCursorChannel; -import io.flutter.embedding.engine.systemchannels.NavigationChannel; -import io.flutter.embedding.engine.systemchannels.PlatformChannel; -import io.flutter.embedding.engine.systemchannels.SettingsChannel; -import io.flutter.embedding.engine.systemchannels.SystemChannel; -import io.flutter.embedding.engine.systemchannels.TextInputChannel; -import io.flutter.plugin.common.ActivityLifecycleListener; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.editing.TextInputPlugin; -import io.flutter.plugin.localization.LocalizationPlugin; -import io.flutter.plugin.mouse.MouseCursorPlugin; -import io.flutter.plugin.platform.PlatformPlugin; -import io.flutter.plugin.platform.PlatformViewsController; -import io.flutter.util.ViewUtils; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Deprecated Android view containing a Flutter app. - * - * @deprecated {@link io.flutter.embedding.android.FlutterView} is the new API that now replaces - * this class. See https://flutter.dev/go/android-project-migration for more migration details. - */ -@Deprecated -public class FlutterView extends SurfaceView - implements BinaryMessenger, - TextureRegistry, - MouseCursorPlugin.MouseCursorViewDelegate, - KeyboardManager.ViewDelegate { - /** - * Interface for those objects that maintain and expose a reference to a {@code FlutterView} (such - * as a full-screen Flutter activity). - * - *

This indirection is provided to support applications that use an activity other than {@link - * io.flutter.app.FlutterActivity} (e.g. Android v4 support library's {@code FragmentActivity}). - * It allows Flutter plugins to deal in this interface and not require that the activity be a - * subclass of {@code FlutterActivity}. - */ - public interface Provider { - /** - * Returns a reference to the Flutter view maintained by this object. This may be {@code null}. - * - * @return a reference to the Flutter view maintained by this object. - */ - FlutterView getFlutterView(); - } - - private static final String TAG = "FlutterView"; - - static final class ViewportMetrics { - float devicePixelRatio = 1.0f; - int physicalWidth = 0; - int physicalHeight = 0; - int physicalViewPaddingTop = 0; - int physicalViewPaddingRight = 0; - int physicalViewPaddingBottom = 0; - int physicalViewPaddingLeft = 0; - int physicalViewInsetTop = 0; - int physicalViewInsetRight = 0; - int physicalViewInsetBottom = 0; - int physicalViewInsetLeft = 0; - int systemGestureInsetTop = 0; - int systemGestureInsetRight = 0; - int systemGestureInsetBottom = 0; - int systemGestureInsetLeft = 0; - int physicalTouchSlop = -1; - } - - private final DartExecutor dartExecutor; - private final FlutterRenderer flutterRenderer; - private final NavigationChannel navigationChannel; - private final BackGestureChannel backGestureChannel; - private final LifecycleChannel lifecycleChannel; - private final LocalizationChannel localizationChannel; - private final PlatformChannel platformChannel; - private final SettingsChannel settingsChannel; - private final SystemChannel systemChannel; - private final InputMethodManager mImm; - private final TextInputPlugin mTextInputPlugin; - private final LocalizationPlugin mLocalizationPlugin; - private final MouseCursorPlugin mMouseCursorPlugin; - private final KeyboardManager mKeyboardManager; - private final AndroidTouchProcessor androidTouchProcessor; - private AccessibilityBridge mAccessibilityNodeProvider; - private final SurfaceHolder.Callback mSurfaceCallback; - private final ViewportMetrics mMetrics; - private final List mActivityLifecycleListeners; - private final List mFirstFrameListeners; - private final AtomicLong nextTextureId = new AtomicLong(0L); - private FlutterNativeView mNativeView; - private boolean mIsSoftwareRenderingEnabled = false; // using the software renderer or not - private boolean didRenderFirstFrame = false; - - private final AccessibilityBridge.OnAccessibilityChangeListener onAccessibilityChangeListener = - new AccessibilityBridge.OnAccessibilityChangeListener() { - @Override - public void onAccessibilityChanged( - boolean isAccessibilityEnabled, boolean isTouchExplorationEnabled) { - resetWillNotDraw(isAccessibilityEnabled, isTouchExplorationEnabled); - } - }; - - public FlutterView(Context context) { - this(context, null); - } - - public FlutterView(Context context, AttributeSet attrs) { - this(context, attrs, null); - } - - public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) { - super(context, attrs); - - Activity activity = ViewUtils.getActivity(getContext()); - if (activity == null) { - throw new IllegalArgumentException("Bad context"); - } - - if (nativeView == null) { - mNativeView = new FlutterNativeView(activity.getApplicationContext()); - } else { - mNativeView = nativeView; - } - - dartExecutor = mNativeView.getDartExecutor(); - flutterRenderer = new FlutterRenderer(mNativeView.getFlutterJNI()); - mIsSoftwareRenderingEnabled = mNativeView.getFlutterJNI().getIsSoftwareRenderingEnabled(); - mMetrics = new ViewportMetrics(); - mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density; - mMetrics.physicalTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); - setFocusable(true); - setFocusableInTouchMode(true); - - mNativeView.attachViewAndActivity(this, activity); - - mSurfaceCallback = - new SurfaceHolder.Callback() { - @Override - public void surfaceCreated(SurfaceHolder holder) { - assertAttached(); - mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface()); - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - assertAttached(); - mNativeView.getFlutterJNI().onSurfaceChanged(width, height); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - assertAttached(); - mNativeView.getFlutterJNI().onSurfaceDestroyed(); - } - }; - getHolder().addCallback(mSurfaceCallback); - - mActivityLifecycleListeners = new ArrayList<>(); - mFirstFrameListeners = new ArrayList<>(); - - // Create all platform channels - navigationChannel = new NavigationChannel(dartExecutor); - backGestureChannel = new BackGestureChannel(dartExecutor); - lifecycleChannel = new LifecycleChannel(dartExecutor); - localizationChannel = new LocalizationChannel(dartExecutor); - platformChannel = new PlatformChannel(dartExecutor); - systemChannel = new SystemChannel(dartExecutor); - settingsChannel = new SettingsChannel(dartExecutor); - - // Create and set up plugins - PlatformPlugin platformPlugin = new PlatformPlugin(activity, platformChannel); - addActivityLifecycleListener( - new ActivityLifecycleListener() { - @Override - public void onPostResume() { - platformPlugin.updateSystemUiOverlays(); - } - }); - mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - PlatformViewsController platformViewsController = - mNativeView.getPluginRegistry().getPlatformViewsController(); - mTextInputPlugin = - new TextInputPlugin(this, new TextInputChannel(dartExecutor), platformViewsController); - mKeyboardManager = new KeyboardManager(this); - - if (Build.VERSION.SDK_INT >= API_LEVELS.API_24) { - mMouseCursorPlugin = new MouseCursorPlugin(this, new MouseCursorChannel(dartExecutor)); - } else { - mMouseCursorPlugin = null; - } - mLocalizationPlugin = new LocalizationPlugin(context, localizationChannel); - androidTouchProcessor = - new AndroidTouchProcessor(flutterRenderer, /*trackMotionEvents=*/ false); - platformViewsController.attachToFlutterRenderer(flutterRenderer); - mNativeView - .getPluginRegistry() - .getPlatformViewsController() - .attachTextInputPlugin(mTextInputPlugin); - mNativeView.getFlutterJNI().setLocalizationPlugin(mLocalizationPlugin); - - // Send initial platform information to Dart - mLocalizationPlugin.sendLocalesToFlutter(getResources().getConfiguration()); - sendUserPlatformSettingsToDart(); - } - - @NonNull - public DartExecutor getDartExecutor() { - return dartExecutor; - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - Log.e(TAG, "dispatchKeyEvent: " + event.toString()); - if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - // Tell Android to start tracking this event. - getKeyDispatcherState().startTracking(event, this); - } else if (event.getAction() == KeyEvent.ACTION_UP) { - // Stop tracking the event. - getKeyDispatcherState().handleUpEvent(event); - } - // If the key processor doesn't handle it, then send it on to the - // superclass. The key processor will typically handle all events except - // those where it has re-dispatched the event after receiving a reply from - // the framework that the framework did not handle it. - return (isAttached() && mKeyboardManager.handleEvent(event)) || super.dispatchKeyEvent(event); - } - - public FlutterNativeView getFlutterNativeView() { - return mNativeView; - } - - public FlutterPluginRegistry getPluginRegistry() { - return mNativeView.getPluginRegistry(); - } - - public String getLookupKeyForAsset(String asset) { - return FlutterMain.getLookupKeyForAsset(asset); - } - - public String getLookupKeyForAsset(String asset, String packageName) { - return FlutterMain.getLookupKeyForAsset(asset, packageName); - } - - public void addActivityLifecycleListener(ActivityLifecycleListener listener) { - mActivityLifecycleListeners.add(listener); - } - - public void onStart() { - lifecycleChannel.appIsInactive(); - } - - public void onPause() { - lifecycleChannel.appIsInactive(); - } - - public void onPostResume() { - for (ActivityLifecycleListener listener : mActivityLifecycleListeners) { - listener.onPostResume(); - } - lifecycleChannel.appIsResumed(); - } - - public void onStop() { - lifecycleChannel.appIsPaused(); - } - - public void onMemoryPressure() { - mNativeView.getFlutterJNI().notifyLowMemoryWarning(); - systemChannel.sendMemoryPressureWarning(); - } - - /** - * Returns true if the Flutter experience associated with this {@code FlutterView} has rendered - * its first frame, or false otherwise. - */ - public boolean hasRenderedFirstFrame() { - return didRenderFirstFrame; - } - - /** - * Provide a listener that will be called once when the FlutterView renders its first frame to the - * underlaying SurfaceView. - */ - public void addFirstFrameListener(FirstFrameListener listener) { - mFirstFrameListeners.add(listener); - } - - /** Remove an existing first frame listener. */ - public void removeFirstFrameListener(FirstFrameListener listener) { - mFirstFrameListeners.remove(listener); - } - - @Override - public void enableBufferingIncomingMessages() {} - - @Override - public void disableBufferingIncomingMessages() {} - - /** - * Reverts this back to the {@link SurfaceView} defaults, at the back of its window and opaque. - */ - public void disableTransparentBackground() { - setZOrderOnTop(false); - getHolder().setFormat(PixelFormat.OPAQUE); - } - - public void setInitialRoute(String route) { - navigationChannel.setInitialRoute(route); - } - - public void pushRoute(String route) { - navigationChannel.pushRoute(route); - } - - public void popRoute() { - navigationChannel.popRoute(); - } - - @TargetApi(API_LEVELS.API_34) - @RequiresApi(API_LEVELS.API_34) - public void startBackGesture(@NonNull BackEvent backEvent) { - backGestureChannel.startBackGesture(backEvent); - } - - @TargetApi(API_LEVELS.API_34) - @RequiresApi(API_LEVELS.API_34) - public void updateBackGestureProgress(@NonNull BackEvent backEvent) { - backGestureChannel.updateBackGestureProgress(backEvent); - } - - @TargetApi(API_LEVELS.API_34) - @RequiresApi(API_LEVELS.API_34) - public void commitBackGesture() { - backGestureChannel.commitBackGesture(); - } - - @TargetApi(API_LEVELS.API_34) - @RequiresApi(API_LEVELS.API_34) - public void cancelBackGesture() { - backGestureChannel.cancelBackGesture(); - } - - private void sendUserPlatformSettingsToDart() { - // Lookup the current brightness of the Android OS. - boolean isNightModeOn = - (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) - == Configuration.UI_MODE_NIGHT_YES; - SettingsChannel.PlatformBrightness brightness = - isNightModeOn - ? SettingsChannel.PlatformBrightness.dark - : SettingsChannel.PlatformBrightness.light; - - settingsChannel - .startMessage() - .setTextScaleFactor(getResources().getConfiguration().fontScale) - .setUse24HourFormat(DateFormat.is24HourFormat(getContext())) - .setPlatformBrightness(brightness) - .send(); - } - - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mLocalizationPlugin.sendLocalesToFlutter(newConfig); - sendUserPlatformSettingsToDart(); - } - - float getDevicePixelRatio() { - return mMetrics.devicePixelRatio; - } - - public FlutterNativeView detach() { - if (!isAttached()) return null; - getHolder().removeCallback(mSurfaceCallback); - mNativeView.detachFromFlutterView(); - - FlutterNativeView view = mNativeView; - mNativeView = null; - return view; - } - - public void destroy() { - if (!isAttached()) return; - - getHolder().removeCallback(mSurfaceCallback); - releaseAccessibilityNodeProvider(); - - mNativeView.destroy(); - mNativeView = null; - } - - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - return mTextInputPlugin.createInputConnection(this, mKeyboardManager, outAttrs); - } - - @Override - public boolean checkInputConnectionProxy(View view) { - return mNativeView - .getPluginRegistry() - .getPlatformViewsController() - .checkInputConnectionProxy(view); - } - - @Override - public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { - super.onProvideAutofillVirtualStructure(structure, flags); - mTextInputPlugin.onProvideAutofillVirtualStructure(structure, flags); - } - - @Override - public void autofill(SparseArray values) { - mTextInputPlugin.autofill(values); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isAttached()) { - return super.onTouchEvent(event); - } - - requestUnbufferedDispatch(event); - - return androidTouchProcessor.onTouchEvent(event); - } - - @Override - public boolean onHoverEvent(MotionEvent event) { - if (!isAttached()) { - return super.onHoverEvent(event); - } - - boolean handled = mAccessibilityNodeProvider.onAccessibilityHoverEvent(event); - if (!handled) { - // TODO(ianh): Expose hover events to the platform, - // implementing ADD, REMOVE, etc. - } - return handled; - } - - /** - * Invoked by Android when a generic motion event occurs, e.g., joystick movement, mouse hover, - * track pad touches, scroll wheel movements, etc. - * - *

Flutter handles all of its own gesture detection and processing, therefore this method - * forwards all {@link MotionEvent} data from Android to Flutter. - */ - @Override - public boolean onGenericMotionEvent(MotionEvent event) { - boolean handled = - isAttached() && androidTouchProcessor.onGenericMotionEvent(event, getContext()); - return handled ? true : super.onGenericMotionEvent(event); - } - - @Override - protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { - mMetrics.physicalWidth = width; - mMetrics.physicalHeight = height; - updateViewportMetrics(); - super.onSizeChanged(width, height, oldWidth, oldHeight); - } - - // TODO(garyq): Add support for notch cutout API - // Decide if we want to zero the padding of the sides. When in Landscape orientation, - // android may decide to place the software navigation bars on the side. When the nav - // bar is hidden, the reported insets should be removed to prevent extra useless space - // on the sides. - private enum ZeroSides { - NONE, - LEFT, - RIGHT, - BOTH - } - - private ZeroSides calculateShouldZeroSides() { - // We get both orientation and rotation because rotation is all 4 - // rotations relative to default rotation while orientation is portrait - // or landscape. By combining both, we can obtain a more precise measure - // of the rotation. - Context context = getContext(); - int orientation = context.getResources().getConfiguration().orientation; - int rotation = - ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRotation(); - - if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - if (rotation == Surface.ROTATION_90) { - return ZeroSides.RIGHT; - } else if (rotation == Surface.ROTATION_270) { - // In android API >= 23, the nav bar always appears on the "bottom" (USB) side. - return Build.VERSION.SDK_INT >= API_LEVELS.API_23 ? ZeroSides.LEFT : ZeroSides.RIGHT; - } - // Ambiguous orientation due to landscape left/right default. Zero both sides. - else if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) { - return ZeroSides.BOTH; - } - } - // Square orientation deprecated in API 16, we will not check for it and return false - // to be safe and not remove any unique padding for the devices that do use it. - return ZeroSides.NONE; - } - - // TODO(garyq): Use new Android R getInsets API - // TODO(garyq): The keyboard detection may interact strangely with - // https://github.com/flutter/flutter/issues/22061 - - // Uses inset heights and screen heights as a heuristic to determine if the insets should - // be padded. When the on-screen keyboard is detected, we want to include the full inset - // but when the inset is just the hidden nav bar, we want to provide a zero inset so the space - // can be used. - - private int guessBottomKeyboardInset(WindowInsets insets) { - int screenHeight = getRootView().getHeight(); - // Magic number due to this being a heuristic. This should be replaced, but we have not - // found a clean way to do it yet (Sept. 2018) - final double keyboardHeightRatioHeuristic = 0.18; - if (insets.getSystemWindowInsetBottom() < screenHeight * keyboardHeightRatioHeuristic) { - // Is not a keyboard, so return zero as inset. - return 0; - } else { - // Is a keyboard, so return the full inset. - return insets.getSystemWindowInsetBottom(); - } - } - - // This callback is not present in API < 20, which means lower API devices will see - // the wider than expected padding when the status and navigation bars are hidden. - // The annotations to suppress "InlinedApi" and "NewApi" lints prevent lint warnings - // caused by usage of Android Q APIs. These calls are safe because they are - // guarded. - @Override - @SuppressLint({"InlinedApi", "NewApi"}) - public final WindowInsets onApplyWindowInsets(WindowInsets insets) { - // getSystemGestureInsets() was introduced in API 29 and immediately deprecated in 30. - if (Build.VERSION.SDK_INT == API_LEVELS.API_29) { - Insets systemGestureInsets = insets.getSystemGestureInsets(); - mMetrics.systemGestureInsetTop = systemGestureInsets.top; - mMetrics.systemGestureInsetRight = systemGestureInsets.right; - mMetrics.systemGestureInsetBottom = systemGestureInsets.bottom; - mMetrics.systemGestureInsetLeft = systemGestureInsets.left; - } - - boolean statusBarVisible = (SYSTEM_UI_FLAG_FULLSCREEN & getWindowSystemUiVisibility()) == 0; - boolean navigationBarVisible = - (SYSTEM_UI_FLAG_HIDE_NAVIGATION & getWindowSystemUiVisibility()) == 0; - - if (Build.VERSION.SDK_INT >= API_LEVELS.API_30) { - int mask = 0; - if (navigationBarVisible) { - mask = mask | android.view.WindowInsets.Type.navigationBars(); - } - if (statusBarVisible) { - mask = mask | android.view.WindowInsets.Type.statusBars(); - } - Insets uiInsets = insets.getInsets(mask); - mMetrics.physicalViewPaddingTop = uiInsets.top; - mMetrics.physicalViewPaddingRight = uiInsets.right; - mMetrics.physicalViewPaddingBottom = uiInsets.bottom; - mMetrics.physicalViewPaddingLeft = uiInsets.left; - - Insets imeInsets = insets.getInsets(android.view.WindowInsets.Type.ime()); - mMetrics.physicalViewInsetTop = imeInsets.top; - mMetrics.physicalViewInsetRight = imeInsets.right; - mMetrics.physicalViewInsetBottom = imeInsets.bottom; // Typically, only bottom is non-zero - mMetrics.physicalViewInsetLeft = imeInsets.left; - - Insets systemGestureInsets = - insets.getInsets(android.view.WindowInsets.Type.systemGestures()); - mMetrics.systemGestureInsetTop = systemGestureInsets.top; - mMetrics.systemGestureInsetRight = systemGestureInsets.right; - mMetrics.systemGestureInsetBottom = systemGestureInsets.bottom; - mMetrics.systemGestureInsetLeft = systemGestureInsets.left; - - // TODO(garyq): Expose the full rects of the display cutout. - - // Take the max of the display cutout insets and existing padding to merge them - DisplayCutout cutout = insets.getDisplayCutout(); - if (cutout != null) { - Insets waterfallInsets = cutout.getWaterfallInsets(); - mMetrics.physicalViewPaddingTop = - Math.max( - Math.max(mMetrics.physicalViewPaddingTop, waterfallInsets.top), - cutout.getSafeInsetTop()); - mMetrics.physicalViewPaddingRight = - Math.max( - Math.max(mMetrics.physicalViewPaddingRight, waterfallInsets.right), - cutout.getSafeInsetRight()); - mMetrics.physicalViewPaddingBottom = - Math.max( - Math.max(mMetrics.physicalViewPaddingBottom, waterfallInsets.bottom), - cutout.getSafeInsetBottom()); - mMetrics.physicalViewPaddingLeft = - Math.max( - Math.max(mMetrics.physicalViewPaddingLeft, waterfallInsets.left), - cutout.getSafeInsetLeft()); - } - } else { - // We zero the left and/or right sides to prevent the padding the - // navigation bar would have caused. - ZeroSides zeroSides = ZeroSides.NONE; - if (!navigationBarVisible) { - zeroSides = calculateShouldZeroSides(); - } - - // Status bar (top), navigation bar (bottom) and left/right system insets should - // partially obscure the content (padding). - mMetrics.physicalViewPaddingTop = statusBarVisible ? insets.getSystemWindowInsetTop() : 0; - mMetrics.physicalViewPaddingRight = - zeroSides == ZeroSides.RIGHT || zeroSides == ZeroSides.BOTH - ? 0 - : insets.getSystemWindowInsetRight(); - mMetrics.physicalViewPaddingBottom = - navigationBarVisible && guessBottomKeyboardInset(insets) == 0 - ? insets.getSystemWindowInsetBottom() - : 0; - mMetrics.physicalViewPaddingLeft = - zeroSides == ZeroSides.LEFT || zeroSides == ZeroSides.BOTH - ? 0 - : insets.getSystemWindowInsetLeft(); - - // Bottom system inset (keyboard) should adjust scrollable bottom edge (inset). - mMetrics.physicalViewInsetTop = 0; - mMetrics.physicalViewInsetRight = 0; - mMetrics.physicalViewInsetBottom = guessBottomKeyboardInset(insets); - mMetrics.physicalViewInsetLeft = 0; - } - - updateViewportMetrics(); - return super.onApplyWindowInsets(insets); - } - - private boolean isAttached() { - return mNativeView != null && mNativeView.isAttached(); - } - - void assertAttached() { - if (!isAttached()) throw new AssertionError("Platform view is not attached"); - } - - private void preRun() { - resetAccessibilityTree(); - } - - void resetAccessibilityTree() { - if (mAccessibilityNodeProvider != null) { - mAccessibilityNodeProvider.reset(); - } - } - - private void postRun() {} - - public void runFromBundle(FlutterRunArguments args) { - assertAttached(); - preRun(); - mNativeView.runFromBundle(args); - postRun(); - } - - /** - * Return the most recent frame as a bitmap. - * - * @return A bitmap. - */ - public Bitmap getBitmap() { - assertAttached(); - return mNativeView.getFlutterJNI().getBitmap(); - } - - private void updateViewportMetrics() { - if (!isAttached()) return; - mNativeView - .getFlutterJNI() - .setViewportMetrics( - mMetrics.devicePixelRatio, - mMetrics.physicalWidth, - mMetrics.physicalHeight, - mMetrics.physicalViewPaddingTop, - mMetrics.physicalViewPaddingRight, - mMetrics.physicalViewPaddingBottom, - mMetrics.physicalViewPaddingLeft, - mMetrics.physicalViewInsetTop, - mMetrics.physicalViewInsetRight, - mMetrics.physicalViewInsetBottom, - mMetrics.physicalViewInsetLeft, - mMetrics.systemGestureInsetTop, - mMetrics.systemGestureInsetRight, - mMetrics.systemGestureInsetBottom, - mMetrics.systemGestureInsetLeft, - mMetrics.physicalTouchSlop, - new int[0], - new int[0], - new int[0]); - } - - // Called by FlutterNativeView to notify first Flutter frame rendered. - public void onFirstFrame() { - didRenderFirstFrame = true; - - // Allow listeners to remove themselves when they are called. - List listeners = new ArrayList<>(mFirstFrameListeners); - for (FirstFrameListener listener : listeners) { - listener.onFirstFrame(); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - PlatformViewsController platformViewsController = - getPluginRegistry().getPlatformViewsController(); - mAccessibilityNodeProvider = - new AccessibilityBridge( - this, - new AccessibilityChannel(dartExecutor, getFlutterNativeView().getFlutterJNI()), - (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE), - getContext().getContentResolver(), - platformViewsController); - mAccessibilityNodeProvider.setOnAccessibilityChangeListener(onAccessibilityChangeListener); - - resetWillNotDraw( - mAccessibilityNodeProvider.isAccessibilityEnabled(), - mAccessibilityNodeProvider.isTouchExplorationEnabled()); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - releaseAccessibilityNodeProvider(); - } - - // TODO(mattcarroll): Confer with Ian as to why we need this method. Delete if possible, otherwise - // add comments. - private void resetWillNotDraw(boolean isAccessibilityEnabled, boolean isTouchExplorationEnabled) { - if (!mIsSoftwareRenderingEnabled) { - setWillNotDraw(!(isAccessibilityEnabled || isTouchExplorationEnabled)); - } else { - setWillNotDraw(false); - } - } - - @Override - public AccessibilityNodeProvider getAccessibilityNodeProvider() { - if (mAccessibilityNodeProvider != null && mAccessibilityNodeProvider.isAccessibilityEnabled()) { - return mAccessibilityNodeProvider; - } else { - // TODO(goderbauer): when a11y is off this should return a one-off snapshot of - // the a11y - // tree. - return null; - } - } - - private void releaseAccessibilityNodeProvider() { - if (mAccessibilityNodeProvider != null) { - mAccessibilityNodeProvider.release(); - mAccessibilityNodeProvider = null; - } - } - - // -------- Start: Mouse ------- - - @Override - @TargetApi(API_LEVELS.API_24) - @RequiresApi(API_LEVELS.API_24) - @NonNull - public PointerIcon getSystemPointerIcon(int type) { - return PointerIcon.getSystemIcon(getContext(), type); - } - - // -------- End: Mouse ------- - - // -------- Start: Keyboard ------- - - @Override - public BinaryMessenger getBinaryMessenger() { - return this; - } - - @Override - public boolean onTextInputKeyEvent(@NonNull KeyEvent keyEvent) { - return mTextInputPlugin.handleKeyEvent(keyEvent); - } - - @Override - public void redispatch(@NonNull KeyEvent keyEvent) { - getRootView().dispatchKeyEvent(keyEvent); - } - - // -------- End: Keyboard ------- - - @Override - @UiThread - public TaskQueue makeBackgroundTaskQueue(TaskQueueOptions options) { - return null; - } - - @Override - @UiThread - public void send(String channel, ByteBuffer message) { - send(channel, message, null); - } - - @Override - @UiThread - public void send(String channel, ByteBuffer message, BinaryReply callback) { - if (!isAttached()) { - Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel); - return; - } - mNativeView.send(channel, message, callback); - } - - @Override - @UiThread - public void setMessageHandler(@NonNull String channel, @NonNull BinaryMessageHandler handler) { - mNativeView.setMessageHandler(channel, handler); - } - - @Override - @UiThread - public void setMessageHandler( - @NonNull String channel, - @NonNull BinaryMessageHandler handler, - @NonNull TaskQueue taskQueue) { - mNativeView.setMessageHandler(channel, handler, taskQueue); - } - - /** Listener will be called on the Android UI thread once when Flutter renders the first frame. */ - public interface FirstFrameListener { - void onFirstFrame(); - } - - @Override - @NonNull - public TextureRegistry.SurfaceTextureEntry createSurfaceTexture() { - final SurfaceTexture surfaceTexture = new SurfaceTexture(0); - return registerSurfaceTexture(surfaceTexture); - } - - @Override - @NonNull - public ImageTextureEntry createImageTexture() { - throw new UnsupportedOperationException("Image textures are not supported in this mode."); - } - - @NonNull - @Override - public SurfaceProducer createSurfaceProducer() { - throw new UnsupportedOperationException( - "SurfaceProducer textures are not supported in this mode."); - } - - @Override - @NonNull - public TextureRegistry.SurfaceTextureEntry registerSurfaceTexture( - @NonNull SurfaceTexture surfaceTexture) { - surfaceTexture.detachFromGLContext(); - final SurfaceTextureRegistryEntry entry = - new SurfaceTextureRegistryEntry(nextTextureId.getAndIncrement(), surfaceTexture); - mNativeView.getFlutterJNI().registerTexture(entry.id(), entry.textureWrapper()); - return entry; - } - - final class SurfaceTextureRegistryEntry implements TextureRegistry.SurfaceTextureEntry { - private final long id; - private final SurfaceTextureWrapper textureWrapper; - private boolean released; - - SurfaceTextureRegistryEntry(long id, SurfaceTexture surfaceTexture) { - this.id = id; - this.textureWrapper = new SurfaceTextureWrapper(surfaceTexture); - - // The callback relies on being executed on the UI thread (unsynchronised read of - // mNativeView - // and also the engine code check for platform thread in - // Shell::OnPlatformViewMarkTextureFrameAvailable), - // so we explicitly pass a Handler for the current thread. - this.surfaceTexture().setOnFrameAvailableListener(onFrameListener, new Handler()); - } - - private SurfaceTexture.OnFrameAvailableListener onFrameListener = - new SurfaceTexture.OnFrameAvailableListener() { - @Override - public void onFrameAvailable(SurfaceTexture texture) { - if (released || mNativeView == null) { - // Even though we make sure to unregister the callback before releasing, as of Android - // O - // SurfaceTexture has a data race when accessing the callback, so the callback may - // still be called by a stale reference after released==true and mNativeView==null. - return; - } - - mNativeView - .getFlutterJNI() - .markTextureFrameAvailable(SurfaceTextureRegistryEntry.this.id); - } - }; - - public SurfaceTextureWrapper textureWrapper() { - return textureWrapper; - } - - @NonNull - @Override - public SurfaceTexture surfaceTexture() { - return textureWrapper.surfaceTexture(); - } - - @Override - public long id() { - return id; - } - - @Override - public void release() { - if (released) { - return; - } - released = true; - - // The ordering of the next 3 calls is important: - // First we remove the frame listener, then we release the SurfaceTexture, and only after we - // unregister - // the texture which actually deletes the GL texture. - - // Otherwise onFrameAvailableListener might be called after mNativeView==null - // (https://github.com/flutter/flutter/issues/20951). See also the check in onFrameAvailable. - surfaceTexture().setOnFrameAvailableListener(null); - textureWrapper.release(); - mNativeView.getFlutterJNI().unregisterTexture(id); - } - } -} diff --git a/shell/platform/android/io/flutter/view/TextureRegistry.java b/shell/platform/android/io/flutter/view/TextureRegistry.java index 23991b09813f5..1f21312cfcfd3 100644 --- a/shell/platform/android/io/flutter/view/TextureRegistry.java +++ b/shell/platform/android/io/flutter/view/TextureRegistry.java @@ -13,8 +13,8 @@ // TODO(mattcarroll): re-evalute docs in this class and add nullability annotations. /** - * Registry of backend textures used with a single {@link FlutterView} instance. Entries may be - * embedded into the Flutter view using the Texture widget. */ public interface TextureRegistry { diff --git a/shell/platform/android/test/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistryTest.java b/shell/platform/android/test/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistryTest.java deleted file mode 100644 index 421f857856cde..0000000000000 --- a/shell/platform/android/test/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistryTest.java +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.embedding.engine.plugins.shim; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Activity; -import android.content.Context; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import io.flutter.embedding.engine.FlutterEngine; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding; -import io.flutter.embedding.engine.plugins.PluginRegistry; -import io.flutter.embedding.engine.plugins.activity.ActivityAware; -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; - -@Config(manifest = Config.NONE) -@RunWith(AndroidJUnit4.class) -public class ShimPluginRegistryTest { - - @Mock private FlutterEngine mockFlutterEngine; - @Mock private FlutterPluginBinding mockFlutterPluginBinding; - @Mock private ActivityPluginBinding mockActivityPluginBinding; - @Mock private PluginRegistry mockPluginRegistry; - @Mock private Context mockApplicationContext; - @Mock private Activity mockActivity; - - @Before - public void setup() { - MockitoAnnotations.openMocks(this); - when(mockFlutterEngine.getPlugins()).thenReturn(mockPluginRegistry); - when(mockFlutterPluginBinding.getApplicationContext()).thenReturn(mockApplicationContext); - when(mockActivityPluginBinding.getActivity()).thenReturn(mockActivity); - } - - @SuppressWarnings("deprecation") - // Test is intentionally verifying deprecated behavior. - @Test - public void itSuppliesOldAPIsViaTheNewFlutterPluginBinding() { - ShimPluginRegistry registryUnderTest = new ShimPluginRegistry(mockFlutterEngine); - // Fully qualifed name because imports can not have deprecation supression. - // This is the consumption side of the old plugins. - io.flutter.plugin.common.PluginRegistry.Registrar registrarUnderTest = - registryUnderTest.registrarFor("test"); - - ArgumentCaptor shimAggregateCaptor = - ArgumentCaptor.forClass(FlutterPlugin.class); - // A single shim aggregate was added as a new plugin to the FlutterEngine's PluginRegistry. - verify(mockPluginRegistry).add(shimAggregateCaptor.capture()); - // This is really a ShimRegistrarAggregate acting as a FlutterPlugin which is the - // intermediate consumption side of the new plugin inside the shim. - FlutterPlugin shimAggregateUnderTest = shimAggregateCaptor.getValue(); - // The FlutterPluginBinding is the supply side of the new plugin. - shimAggregateUnderTest.onAttachedToEngine(mockFlutterPluginBinding); - - // Consume something from the old plugin API. - assertEquals(mockApplicationContext, registrarUnderTest.context()); - // Check that the value comes from the supply side of the new plugin. - verify(mockFlutterPluginBinding).getApplicationContext(); - } - - @SuppressWarnings("deprecation") - // Test is intentionally verifying deprecated behavior. - @Test - public void itSuppliesMultipleOldPlugins() { - ShimPluginRegistry registryUnderTest = new ShimPluginRegistry(mockFlutterEngine); - // Fully qualifed name because imports can not have deprecation supression. - io.flutter.plugin.common.PluginRegistry.Registrar registrarUnderTest1 = - registryUnderTest.registrarFor("test1"); - io.flutter.plugin.common.PluginRegistry.Registrar registrarUnderTest2 = - registryUnderTest.registrarFor("test2"); - - ArgumentCaptor shimAggregateCaptor = - ArgumentCaptor.forClass(FlutterPlugin.class); - verify(mockPluginRegistry).add(shimAggregateCaptor.capture()); - // There's only one aggregate for many old plugins. - FlutterPlugin shimAggregateUnderTest = shimAggregateCaptor.getValue(); - - // The FlutterPluginBinding is the supply side of the new plugin. - shimAggregateUnderTest.onAttachedToEngine(mockFlutterPluginBinding); - - // Since the 2 old plugins are supplied by the same intermediate FlutterPlugin, they should - // get the same value. - assertEquals(registrarUnderTest1.context(), registrarUnderTest2.context()); - verify(mockFlutterPluginBinding, times(2)).getApplicationContext(); - } - - @SuppressWarnings("deprecation") - // Test is intentionally verifying deprecated behavior. - @Test - public void itCanOnlySupplyActivityBindingWhenUpstreamActivityIsAttached() { - ShimPluginRegistry registryUnderTest = new ShimPluginRegistry(mockFlutterEngine); - io.flutter.plugin.common.PluginRegistry.Registrar registrarUnderTest = - registryUnderTest.registrarFor("test"); - - ArgumentCaptor shimAggregateCaptor = - ArgumentCaptor.forClass(FlutterPlugin.class); - verify(mockPluginRegistry).add(shimAggregateCaptor.capture()); - FlutterPlugin shimAggregateAsPlugin = shimAggregateCaptor.getValue(); - ActivityAware shimAggregateAsActivityAware = (ActivityAware) shimAggregateCaptor.getValue(); - - // Nothing is retrievable when nothing is attached. - assertNull(registrarUnderTest.context()); - assertNull(registrarUnderTest.activity()); - - shimAggregateAsPlugin.onAttachedToEngine(mockFlutterPluginBinding); - - assertEquals(mockApplicationContext, registrarUnderTest.context()); - assertNull(registrarUnderTest.activity()); - - shimAggregateAsActivityAware.onAttachedToActivity(mockActivityPluginBinding); - - // Now context is the activity context. - assertEquals(mockActivity, registrarUnderTest.activeContext()); - assertEquals(mockActivity, registrarUnderTest.activity()); - - shimAggregateAsActivityAware.onDetachedFromActivityForConfigChanges(); - - assertEquals(mockApplicationContext, registrarUnderTest.activeContext()); - assertNull(registrarUnderTest.activity()); - - shimAggregateAsActivityAware.onReattachedToActivityForConfigChanges(mockActivityPluginBinding); - assertEquals(mockActivity, registrarUnderTest.activeContext()); - assertEquals(mockActivity, registrarUnderTest.activity()); - - shimAggregateAsActivityAware.onDetachedFromActivity(); - - assertEquals(mockApplicationContext, registrarUnderTest.activeContext()); - assertNull(registrarUnderTest.activity()); - - // Attach an activity again. - shimAggregateAsActivityAware.onAttachedToActivity(mockActivityPluginBinding); - - assertEquals(mockActivity, registrarUnderTest.activeContext()); - assertEquals(mockActivity, registrarUnderTest.activity()); - - // Now rip out the whole engine. - shimAggregateAsPlugin.onDetachedFromEngine(mockFlutterPluginBinding); - - // And everything should have been made unavailable. - assertNull(registrarUnderTest.activeContext()); - assertNull(registrarUnderTest.activity()); - } -} diff --git a/testing/scenario_app/android/app/src/main/AndroidManifest.xml b/testing/scenario_app/android/app/src/main/AndroidManifest.xml index 3c194a37bf9c7..20e937e294c46 100644 --- a/testing/scenario_app/android/app/src/main/AndroidManifest.xml +++ b/testing/scenario_app/android/app/src/main/AndroidManifest.xml @@ -3,7 +3,6 @@ xmlns:tools="http://schemas.android.com/tools"> Date: Wed, 10 Apr 2024 09:52:40 -0700 Subject: [PATCH 2/4] re-add the PluginRegistry.Registrar interface in v1 PluginRegistry --- .../io/flutter/plugin/common/PluginRegistry.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java index 977b995ecf63a..6d4a7b39d2aff 100644 --- a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java +++ b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java @@ -12,6 +12,18 @@ /** Container class for Android API listeners used by {@link ActivityPluginBinding}. */ public interface PluginRegistry { + /** + * This interface exists solely for backwards compatibility for plugin authors. + * + * When the v1 embedding was initially deprecated, Flutter docs recommended plugin authors + * continue to include a `registerWith(PluginRegistry.Registrar)` for backwards compatibility + * with v1 apps. Removing it without warning would break them. + * + * TODO(gmackall): Delete this after plugin authors have been given one major release to migrate. + */ + @Deprecated + interface Registrar {} + /** * Delegate interface for handling result of permissions requests on behalf of the main {@link * Activity}. From 1490f57362399b58121293976a3054b56a222f74 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 10 Apr 2024 09:54:36 -0700 Subject: [PATCH 3/4] format --- .../android/io/flutter/plugin/common/PluginRegistry.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java index 6d4a7b39d2aff..c587d4f84384e 100644 --- a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java +++ b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java @@ -15,11 +15,12 @@ public interface PluginRegistry { /** * This interface exists solely for backwards compatibility for plugin authors. * - * When the v1 embedding was initially deprecated, Flutter docs recommended plugin authors - * continue to include a `registerWith(PluginRegistry.Registrar)` for backwards compatibility - * with v1 apps. Removing it without warning would break them. + *

When the v1 embedding was initially deprecated, Flutter docs recommended plugin authors + * continue to include a `registerWith(PluginRegistry.Registrar)` for backwards compatibility with + * v1 apps. Removing it without warning would break them. * - * TODO(gmackall): Delete this after plugin authors have been given one major release to migrate. + *

TODO(gmackall): Delete this after plugin authors have been given one major release to + * migrate. */ @Deprecated interface Registrar {} From f8b3fce173ec80743265c7d78c5182c1ce287e52 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Fri, 7 Jun 2024 12:44:51 -0700 Subject: [PATCH 4/4] re-delete io.flutter.plugin.common.PluginRegistry.Registrar --- .../io/flutter/plugin/common/PluginRegistry.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java index c587d4f84384e..977b995ecf63a 100644 --- a/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java +++ b/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java @@ -12,19 +12,6 @@ /** Container class for Android API listeners used by {@link ActivityPluginBinding}. */ public interface PluginRegistry { - /** - * This interface exists solely for backwards compatibility for plugin authors. - * - *

When the v1 embedding was initially deprecated, Flutter docs recommended plugin authors - * continue to include a `registerWith(PluginRegistry.Registrar)` for backwards compatibility with - * v1 apps. Removing it without warning would break them. - * - *

TODO(gmackall): Delete this after plugin authors have been given one major release to - * migrate. - */ - @Deprecated - interface Registrar {} - /** * Delegate interface for handling result of permissions requests on behalf of the main {@link * Activity}.