diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index 9400b8b1d6..d8b3fc809b 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -443,15 +443,17 @@ import java.util.Arrays; private String maybeGetInitialRouteFromIntent(Intent intent) { if (host.shouldHandleDeeplinking()) { Uri data = intent.getData(); - if (data != null && !data.getPath().isEmpty()) { + if (data != null) { String fullRoute = data.getPath(); - if (data.getQuery() != null && !data.getQuery().isEmpty()) { - fullRoute += "?" + data.getQuery(); + if (fullRoute != null && !fullRoute.isEmpty()) { + if (data.getQuery() != null && !data.getQuery().isEmpty()) { + fullRoute += "?" + data.getQuery(); + } + if (data.getFragment() != null && !data.getFragment().isEmpty()) { + fullRoute += "#" + data.getFragment(); + } + return fullRoute; } - if (data.getFragment() != null && !data.getFragment().isEmpty()) { - fullRoute += "#" + data.getFragment(); - } - return fullRoute; } } return null; diff --git a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java index 9287172414..d7b90c0a8c 100644 --- a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java +++ b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java @@ -598,6 +598,28 @@ public class FlutterActivityAndFragmentDelegateTest { .pushRoute("/custom/route?query=test"); } + @Test + public void itDoesNotSendPushRouteMessageWhenOnNewIntentIsNonHierarchicalUri() { + when(mockHost.shouldHandleDeeplinking()).thenReturn(true); + // Create the real object that we're testing. + FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); + + // --- Execute the behavior under test --- + // The FlutterEngine is set up in onAttach(). + delegate.onAttach(RuntimeEnvironment.application); + + Intent mockIntent = mock(Intent.class); + + // mailto: URIs are non-hierarchical + when(mockIntent.getData()).thenReturn(Uri.parse("mailto:test@test.com")); + + // Emulate the host and call the method + delegate.onNewIntent(mockIntent); + + // Verify that the navigation channel was not given a push route message. + verify(mockFlutterEngine.getNavigationChannel(), times(0)).pushRoute("mailto:test@test.com"); + } + @Test public void itSendsPushRouteMessageWhenOnNewIntentWithQueryParameterAndFragment() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true);