Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterPluginRegist
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/DrawableSplashScreen.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/ExclusiveAppComponent.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityLaunchConfigs.java
Expand All @@ -728,7 +727,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/Splas
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/TransparencyMode.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineCache.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java
Expand Down
5 changes: 2 additions & 3 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ android_java_sources = [
"io/flutter/embedding/android/AndroidKeyProcessor.java",
"io/flutter/embedding/android/AndroidTouchProcessor.java",
"io/flutter/embedding/android/DrawableSplashScreen.java",
"io/flutter/embedding/android/ExclusiveAppComponent.java",
"io/flutter/embedding/android/FlutterActivity.java",
"io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java",
"io/flutter/embedding/android/FlutterActivityLaunchConfigs.java",
Expand All @@ -148,7 +147,7 @@ android_java_sources = [
"io/flutter/embedding/android/TransparencyMode.java",
"io/flutter/embedding/engine/FlutterEngine.java",
"io/flutter/embedding/engine/FlutterEngineCache.java",
"io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java",
"io/flutter/embedding/engine/FlutterEnginePluginRegistry.java",
"io/flutter/embedding/engine/FlutterJNI.java",
"io/flutter/embedding/engine/FlutterOverlaySurface.java",
"io/flutter/embedding/engine/FlutterShellArgs.java",
Expand Down Expand Up @@ -430,7 +429,7 @@ action("robolectric_tests") {
"test/io/flutter/embedding/android/FlutterViewTest.java",
"test/io/flutter/embedding/android/RobolectricFlutterActivity.java",
"test/io/flutter/embedding/engine/FlutterEngineCacheTest.java",
"test/io/flutter/embedding/engine/FlutterEngineConnectionRegistryTest.java",
"test/io/flutter/embedding/engine/FlutterEnginePluginRegistryTest.java",
"test/io/flutter/embedding/engine/FlutterEngineTest.java",
"test/io/flutter/embedding/engine/FlutterJNITest.java",
"test/io/flutter/embedding/engine/FlutterShellArgsTest.java",
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -560,102 +560,56 @@ protected void onPause() {
@Override
protected void onStop() {
super.onStop();
if (stillAttachedForEvent("onStop")) {
delegate.onStop();
}
delegate.onStop();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (stillAttachedForEvent("onSaveInstanceState")) {
delegate.onSaveInstanceState(outState);
}
}

/**
* Irreversibly release this activity's control of the {@link FlutterEngine} and its
* subcomponents.
*
* <p>Calling will disconnect this activity's view from the Flutter renderer, disconnect this
* activity from plugins' {@link ActivityControlSurface}, and stop system channel messages from
* this activity.
*
* <p>After calling, this activity should be disposed immediately and not be re-used.
*/
private void release() {
delegate.onDestroyView();
delegate.onDetach();
delegate.release();
delegate = null;
}

@Override
public void detachFromFlutterEngine() {
Log.v(
TAG,
"FlutterActivity "
+ this
+ " connection to the engine "
+ getFlutterEngine()
+ " evicted by another attaching activity");
release();
delegate.onSaveInstanceState(outState);
}

@Override
protected void onDestroy() {
super.onDestroy();
if (stillAttachedForEvent("onDestroy")) {
release();
}
delegate.onDestroyView();
delegate.onDetach();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (stillAttachedForEvent("onActivityResult")) {
delegate.onActivityResult(requestCode, resultCode, data);
}
delegate.onActivityResult(requestCode, resultCode, data);
}

@Override
protected void onNewIntent(@NonNull Intent intent) {
// TODO(mattcarroll): change G3 lint rule that forces us to call super
super.onNewIntent(intent);
if (stillAttachedForEvent("onNewIntent")) {
delegate.onNewIntent(intent);
}
delegate.onNewIntent(intent);
}

@Override
public void onBackPressed() {
if (stillAttachedForEvent("onBackPressed")) {
delegate.onBackPressed();
}
delegate.onBackPressed();
}

@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (stillAttachedForEvent("onRequestPermissionsResult")) {
delegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
delegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
public void onUserLeaveHint() {
if (stillAttachedForEvent("onUserLeaveHint")) {
delegate.onUserLeaveHint();
}
delegate.onUserLeaveHint();
}

@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (stillAttachedForEvent("onTrimMemory")) {
delegate.onTrimMemory(level);
}
delegate.onTrimMemory(level);
}

/**
Expand Down Expand Up @@ -954,7 +908,7 @@ public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
* <p>Returning false from this method does not preclude a {@link FlutterEngine} from being
* attaching to a {@code FlutterActivity} - it just prevents the attachment from happening
* automatically. A developer can choose to subclass {@code FlutterActivity} and then invoke
* {@link ActivityControlSurface#attachToActivity(ExclusiveAppComponent, Lifecycle)} and {@link
* {@link ActivityControlSurface#attachToActivity(Activity, Lifecycle)} and {@link
* ActivityControlSurface#detachFromActivity()} at the desired times.
*
* <p>One reason that a developer might choose to manually manage the relationship between the
Expand Down Expand Up @@ -1007,12 +961,4 @@ public boolean shouldRestoreAndSaveState() {
}
return true;
}

private boolean stillAttachedForEvent(String event) {
if (delegate == null) {
Log.v(TAG, "FlutterActivity " + hashCode() + " " + event + " called after release.");
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
* the same form. <strong>Do not use this class as a convenient shortcut for any other
* behavior.</strong>
*/
/* package */ class FlutterActivityAndFragmentDelegate implements ExclusiveAppComponent<Activity> {
/* package */ final class FlutterActivityAndFragmentDelegate {
private static final String TAG = "FlutterActivityAndFragmentDelegate";
private static final String FRAMEWORK_RESTORATION_BUNDLE_KEY = "framework";
private static final String PLUGINS_RESTORATION_BUNDLE_KEY = "plugins";
Expand Down Expand Up @@ -154,6 +154,14 @@ void onAttach(@NonNull Context context) {
setupFlutterEngine();
}

// Regardless of whether or not a FlutterEngine already existed, the PlatformPlugin
// is bound to a specific Activity. Therefore, it needs to be created and configured
// every time this Fragment attaches to a new Activity.
// TODO(mattcarroll): the PlatformPlugin needs to be reimagined because it implicitly takes
// control of the entire window. This is unacceptable for non-fullscreen
// use-cases.
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);

if (host.shouldAttachEngineToActivity()) {
// Notify any plugins that are currently attached to our FlutterEngine that they
// are now attached to an Activity.
Expand All @@ -164,32 +172,15 @@ void onAttach(@NonNull Context context) {
// 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.
Log.v(TAG, "Attaching FlutterEngine to the Activity that owns this delegate.");
flutterEngine.getActivityControlSurface().attachToActivity(this, host.getLifecycle());
Log.v(TAG, "Attaching FlutterEngine to the Activity that owns this Fragment.");
flutterEngine
.getActivityControlSurface()
.attachToActivity(host.getActivity(), host.getLifecycle());
}

// Regardless of whether or not a FlutterEngine already existed, the PlatformPlugin
// is bound to a specific Activity. Therefore, it needs to be created and configured
// every time this Fragment attaches to a new Activity.
// TODO(mattcarroll): the PlatformPlugin needs to be reimagined because it implicitly takes
// control of the entire window. This is unacceptable for non-fullscreen
// use-cases.
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);

host.configureFlutterEngine(flutterEngine);
}

@Override
public @NonNull Activity getAppComponent() {
final Activity activity = host.getActivity();
if (activity == null) {
throw new AssertionError(
"FlutterActivityAndFragmentDelegate's getAppComponent should only "
+ "be queried after onAttach, when the host's activity should always be non-null");
}
return activity;
}

/**
* Obtains a reference to a FlutterEngine to back this delegate and its {@code host}.
*
Expand Down Expand Up @@ -489,24 +480,6 @@ void onSaveInstanceState(@Nullable Bundle bundle) {
}
}

@Override
public void detachFromFlutterEngine() {
if (host.shouldDestroyEngineWithHost()) {
// The host owns the engine and should never have its engine taken by another exclusive
// activity.
throw new AssertionError(
"The internal FlutterEngine created by "
+ host
+ " has been attached to by another activity. To persist a FlutterEngine beyond the "
+ "ownership of this activity, explicitly create a FlutterEngine");
}

// Default, but customizable, behavior is for the host to call {@link #onDetach}
// deterministically as to not mix more events during the lifecycle of the next exclusive
// activity.
host.detachFromFlutterEngine();
}

/**
* Invoke this from {@code Activity#onDestroy()} or {@code Fragment#onDetach()}.
*
Expand Down Expand Up @@ -768,15 +741,6 @@ private void ensureAlive() {
*/
boolean shouldDestroyEngineWithHost();

/**
* Callback called when the {@link FlutterEngine} has been attached to by another activity
* before this activity was destroyed.
*
* <p>The expected behavior is for this activity to synchronously stop using the {@link
* FlutterEngine} to avoid lifecycle crosstalk with the new activity.
*/
void detachFromFlutterEngine();

/** Returns the Dart entrypoint that should run when a new {@link FlutterEngine} is created. */
@NonNull
String getDartEntrypointFunctionName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package io.flutter.embedding.android;

import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import io.flutter.embedding.engine.FlutterEngine;
Expand All @@ -20,8 +21,8 @@ public interface FlutterEngineConfigurator {
*
* <p>This method is called after the given {@link FlutterEngine} has been attached to the owning
* {@code FragmentActivity}. See {@link
* io.flutter.embedding.engine.plugins.activity.ActivityControlSurface#attachToActivity(
* ExclusiveAppComponent, Lifecycle)}.
* io.flutter.embedding.engine.plugins.activity.ActivityControlSurface#attachToActivity(Activity,
* Lifecycle)}.
*
* <p>It is possible that the owning {@code FragmentActivity} opted not to connect itself as an
* {@link io.flutter.embedding.engine.plugins.activity.ActivityControlSurface}. In that case, any
Expand Down
Loading