diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index b5596ac3e6184b636d6702c6c2c4600bae5526c6..0068333f8ff7c30e2dc865bda2fe5d8667f8eb5b 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -6,6 +6,8 @@ package io.flutter.embedding.android; import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; +import android.arch.lifecycle.Lifecycle; +import android.arch.lifecycle.LifecycleOwner; import android.content.Context; import android.content.Intent; import android.os.Build; @@ -349,8 +351,14 @@ public class FlutterFragment extends Fragment { if (shouldAttachEngineToActivity()) { // Notify any plugins that are currently attached to our FlutterEngine that they // are now attached to an Activity. - // TODO(mattcarroll): send in a real lifecycle. - flutterEngine.getActivityControlSurface().attachToActivity(getActivity(), null); + // + // Passing this Fragment's Lifecycle should be sufficient because as long as this Fragment + // is attached to its Activity, the lifecycles should be in sync. Once this Fragment is + // detached from its Activity, that Activity will be detached from the FlutterEngine, too, + // which means there shouldn't be any possibility for the Fragment Lifecycle to get out of + // sync with the Activity. We use the Fragment's Lifecycle because it is possible that the + // attached Activity is not a LifecycleOwner. + flutterEngine.getActivityControlSurface().attachToActivity(getActivity(), getLifecycle()); } } @@ -590,8 +598,11 @@ public class FlutterFragment extends Fragment { if (shouldAttachEngineToActivity()) { // Notify plugins that they are no longer attached to an Activity. - // TODO(mattcarroll): differentiate between detaching for config changes and otherwise. - flutterEngine.getActivityControlSurface().detachFromActivity(); + if (getActivity().isChangingConfigurations()) { + flutterEngine.getActivityControlSurface().detachFromActivityForConfigChanges(); + } else { + flutterEngine.getActivityControlSurface().detachFromActivity(); + } } // Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment, diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java b/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java index d7c924574514d61945f1d8a75860b2eab76edefe..da7df39551ee4d4c020ca21e74cb5258a96757b9 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java @@ -53,6 +53,7 @@ class FlutterEnginePluginRegistry implements PluginRegistry, private final Map, ActivityAware> activityAwarePlugins = new HashMap<>(); private Activity activity; private FlutterEngineActivityPluginBinding activityPluginBinding; + private boolean isWaitingForActivityReattachment = false; // ServiceAware private final Map, ServiceAware> serviceAwarePlugins = new HashMap<>(); @@ -259,7 +260,8 @@ class FlutterEnginePluginRegistry implements PluginRegistry, @Override public void attachToActivity(@NonNull Activity activity, @NonNull Lifecycle lifecycle) { - Log.d(TAG, "Attaching to an Activity."); + Log.v(TAG, "Attaching to an Activity." + + (isWaitingForActivityReattachment ? " This is after a config change." : "")); // If we were already attached to an Android component, detach from it. detachFromAndroidComponent(); @@ -269,14 +271,21 @@ class FlutterEnginePluginRegistry implements PluginRegistry, // Notify all ActivityAware plugins that they are now attached to a new Activity. for (ActivityAware activityAware : activityAwarePlugins.values()) { - activityAware.onAttachedToActivity(activityPluginBinding); + if (isWaitingForActivityReattachment) { + activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding); + } else { + activityAware.onAttachedToActivity(activityPluginBinding); + } } + isWaitingForActivityReattachment = false; } @Override public void detachFromActivityForConfigChanges() { - Log.d(TAG, "Detaching from an Activity for config changes."); + Log.v(TAG, "Detaching from an Activity for config changes."); if (isAttachedToActivity()) { + isWaitingForActivityReattachment = true; + for (ActivityAware activityAware : activityAwarePlugins.values()) { activityAware.onDetachedFromActivityForConfigChanges(); } @@ -289,25 +298,9 @@ class FlutterEnginePluginRegistry implements PluginRegistry, } } - @Override - public void reattachToActivityAfterConfigChange(@NonNull Activity activity, @NonNull Lifecycle lifecycle) { - Log.d(TAG, "Re-attaching to an Activity after config change."); - if (!isAttachedToActivity()) { - this.activity = activity; - activityPluginBinding = new FlutterEngineActivityPluginBinding(activity); - this.flutterEngineAndroidLifecycle.setBackingLifecycle(lifecycle); - - for (ActivityAware activityAware : activityAwarePlugins.values()) { - activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding); - } - } else { - Log.e(TAG, "Attempted to reattach plugins to an Activity after config changes, but an Activity was already attached."); - } - } - @Override public void detachFromActivity() { - Log.d(TAG, "Detaching from an Activity."); + Log.v(TAG, "Detaching from an Activity."); if (isAttachedToActivity()) { for (ActivityAware activityAware : activityAwarePlugins.values()) { activityAware.onDetachedFromActivity(); @@ -323,7 +316,7 @@ class FlutterEnginePluginRegistry implements PluginRegistry, @Override public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResult) { - Log.d(TAG, "Forwarding onRequestPermissionsResult() to plugins."); + Log.v(TAG, "Forwarding onRequestPermissionsResult() to plugins."); if (isAttachedToActivity()) { return activityPluginBinding.onRequestPermissionsResult(requestCode, permissions, grantResult); } else { @@ -334,7 +327,7 @@ class FlutterEnginePluginRegistry implements PluginRegistry, @Override public boolean onActivityResult(int requestCode, int resultCode, @NonNull Intent data) { - Log.d(TAG, "Forwarding onActivityResult() to plugins."); + Log.v(TAG, "Forwarding onActivityResult() to plugins."); if (isAttachedToActivity()) { return activityPluginBinding.onActivityResult(requestCode, resultCode, data); } else { @@ -345,7 +338,7 @@ class FlutterEnginePluginRegistry implements PluginRegistry, @Override public void onNewIntent(@NonNull Intent intent) { - Log.d(TAG, "Forwarding onNewIntent() to plugins."); + Log.v(TAG, "Forwarding onNewIntent() to plugins."); if (isAttachedToActivity()) { activityPluginBinding.onNewIntent(intent); } else { @@ -355,7 +348,7 @@ class FlutterEnginePluginRegistry implements PluginRegistry, @Override public void onUserLeaveHint() { - Log.d(TAG, "Forwarding onUserLeaveHint() to plugins."); + Log.v(TAG, "Forwarding onUserLeaveHint() to plugins."); if (isAttachedToActivity()) { activityPluginBinding.onUserLeaveHint(); } else { diff --git a/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityControlSurface.java b/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityControlSurface.java index a99d41b5783ed4795f078e9ea3d230172290b6e2..a25bd0826992e2780e55f06e77562971ddb40012 100644 --- a/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityControlSurface.java +++ b/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityControlSurface.java @@ -58,16 +58,6 @@ public interface ActivityControlSurface { */ void detachFromActivityForConfigChanges(); - /** - * Call this method from the {@link Activity} that was previously attached to this - * {@code ActivityControlSurface}'s {@link FlutterEngine}, and was just recreated after a - * configuration change. - *

- * This method gives each {@link ActivityAware} plugin an opportunity to re-establish necessary - * references to the given {@link Activity}. - */ - void reattachToActivityAfterConfigChange(@NonNull Activity activity, @NonNull Lifecycle lifecycle); - /** * Call this method from the {@link Activity} that is attached to this {@code ActivityControlSurfaces}'s * {@link FlutterEngine} when the {@link Activity} is about to be destroyed for non-configuration-change