diff --git a/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/GopeedProfiles.java b/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/GopeedProfiles.java index 62508c17..2be5775a 100644 --- a/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/GopeedProfiles.java +++ b/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/GopeedProfiles.java @@ -15,7 +15,11 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; // Internal host bridge: profile creation and proxy completion precede navigation. -final class GopeedProfiles { +public final class GopeedProfiles { + private static final java.util.Map views = new java.util.IdentityHashMap<>(); + + public static void viewCreated(android.webkit.WebView view, String id) { views.put(view, id); } + public static void viewDestroyed(android.webkit.WebView view) { views.remove(view); } private static SharedPreferences preferences; private static final Set cleared = new HashSet<>(); private static final String DELETIONS = "pendingDeletions"; @@ -47,6 +51,26 @@ final class GopeedProfiles { } static void remove(MethodCall call, MethodChannel.Result result) { + waitForViews(call, result, 100); + } + + private static void waitForViews(MethodCall call, MethodChannel.Result result, int attempts) { + String id = call.argument("gopeedProfileId"); + if (views.containsValue(id)) { + if (attempts <= 0) { + result.error("PROFILE_REMOVE_FAILED", "WebView pages have not finished closing", null); + return; + } + // The plugin destroys WebViews asynchronously after about:blank loads. + // Wait for actual native destruction, not just Dart widget disposal. + new android.os.Handler(android.os.Looper.getMainLooper()).postDelayed( + () -> waitForViews(call, result, attempts - 1), 100); + return; + } + removeData(call, result); + } + + private static void removeData(MethodCall call, MethodChannel.Result result) { if (!WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE)) { result.error("UNAVAILABLE", "Android WebView profile removal is unavailable", null); return; diff --git a/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java b/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java index 727d8d4e..e27b1c88 100755 --- a/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java +++ b/ui/flutter/third_party/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InAppWebView.java @@ -195,6 +195,7 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie super(context, containerView, customSettings.useHybridComposition); if (!customSettings.gopeedProfileId.isEmpty()) { WebViewCompat.setProfile(this, customSettings.gopeedProfileId); + com.pichillilorenzo.flutter_inappwebview_android.GopeedProfiles.viewCreated(this, customSettings.gopeedProfileId); } this.plugin = plugin; this.id = id; @@ -2107,5 +2108,6 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie @Override public void destroy() { super.destroy(); + com.pichillilorenzo.flutter_inappwebview_android.GopeedProfiles.viewDestroyed(this); } }