diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 66c2acd8e886b..1a6d48f160dde 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -774,13 +774,18 @@ public String getDartEntrypointFunctionName() { * * If both preferences are set, the {@code Intent} preference takes priority. * + *
If none is set, the {@link FlutterActivityAndFragmentDelegate} retrieves the initial route + * from the {@code Intent} through the Intent.getData() instead. + * *
The reason that a {@code Subclasses may override this method to directly control the initial route.
+ *
+ * If this method returns null, the {@link FlutterActivityAndFragmentDelegate} retrieves the
+ * initial route from the {@code Intent} through the Intent.getData() instead.
*/
- @NonNull
public String getInitialRoute() {
if (getIntent().hasExtra(EXTRA_INITIAL_ROUTE)) {
return getIntent().getStringExtra(EXTRA_INITIAL_ROUTE);
@@ -792,9 +797,9 @@ public String getInitialRoute() {
Bundle metadata = activityInfo.metaData;
String desiredInitialRoute =
metadata != null ? metadata.getString(INITIAL_ROUTE_META_DATA_KEY) : null;
- return desiredInitialRoute != null ? desiredInitialRoute : DEFAULT_INITIAL_ROUTE;
+ return desiredInitialRoute;
} catch (PackageManager.NameNotFoundException e) {
- return DEFAULT_INITIAL_ROUTE;
+ return null;
}
}
diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
index 78585172dd683..1ecbd0fafc908 100644
--- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
+++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
@@ -9,6 +9,7 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -362,18 +363,21 @@ private void doInitialFlutterViewRun() {
// So this is expected behavior in many cases.
return;
}
-
+ String initialRoute = host.getInitialRoute();
+ if (initialRoute == null) {
+ initialRoute = getInitialRouteFromIntent(host.getActivity().getIntent());
+ }
Log.v(
TAG,
"Executing Dart entrypoint: "
+ host.getDartEntrypointFunctionName()
+ ", and sending initial route: "
- + host.getInitialRoute());
+ + initialRoute);
// The engine needs to receive the Flutter app's initial route before executing any
// Dart code to ensure that the initial route arrives in time to be applied.
- if (host.getInitialRoute() != null) {
- flutterEngine.getNavigationChannel().setInitialRoute(host.getInitialRoute());
+ if (initialRoute != null) {
+ flutterEngine.getNavigationChannel().setInitialRoute(initialRoute);
}
String appBundlePathOverride = host.getAppBundlePath();
@@ -388,6 +392,14 @@ private void doInitialFlutterViewRun() {
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
}
+ private String getInitialRouteFromIntent(Intent intent) {
+ Uri data = intent.getData();
+ if (data != null && !data.toString().isEmpty()) {
+ return data.toString();
+ }
+ return null;
+ }
+
/**
* Invoke this from {@code Activity#onResume()} or {@code Fragment#onResume()}.
*
@@ -622,8 +634,12 @@ void onRequestPermissionsResult(
void onNewIntent(@NonNull Intent intent) {
ensureAlive();
if (flutterEngine != null) {
- Log.v(TAG, "Forwarding onNewIntent() to FlutterEngine.");
+ Log.v(TAG, "Forwarding onNewIntent() to FlutterEngine and sending pushRoute message.");
flutterEngine.getActivityControlSurface().onNewIntent(intent);
+ String initialRoute = getInitialRouteFromIntent(intent);
+ if (initialRoute != null && !initialRoute.isEmpty()) {
+ flutterEngine.getNavigationChannel().pushRoute(initialRoute);
+ }
} else {
Log.w(TAG, "onNewIntent() invoked before FlutterFragment was attached to an Activity.");
}
diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
index ff15581a57b22..486d36925d8b1 100644
--- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
+++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java
@@ -646,13 +646,18 @@ public String getDartEntrypointFunctionName() {
*
* If both preferences are set, the {@code Intent} preference takes priority.
*
+ * If none is set, the {@link FlutterActivityAndFragmentDelegate} retrieves the initial route
+ * from the {@code Intent} through the Intent.getData() instead.
+ *
* The reason that a {@code Subclasses may override this method to directly control the initial route.
+ *
+ * If this method returns null, the {@link FlutterActivityAndFragmentDelegate} retrieves the
+ * initial route from the {@code Intent} through the Intent.getData() instead.
*/
- @NonNull
protected String getInitialRoute() {
if (getIntent().hasExtra(EXTRA_INITIAL_ROUTE)) {
return getIntent().getStringExtra(EXTRA_INITIAL_ROUTE);
@@ -664,9 +669,9 @@ protected String getInitialRoute() {
Bundle metadata = activityInfo.metaData;
String desiredInitialRoute =
metadata != null ? metadata.getString(INITIAL_ROUTE_META_DATA_KEY) : null;
- return desiredInitialRoute != null ? desiredInitialRoute : DEFAULT_INITIAL_ROUTE;
+ return desiredInitialRoute;
} catch (PackageManager.NameNotFoundException e) {
- return DEFAULT_INITIAL_ROUTE;
+ return null;
}
}
diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
index 4a621b3344107..329f730175627 100644
--- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
+++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java
@@ -15,6 +15,7 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import io.flutter.FlutterInjector;
@@ -43,6 +44,7 @@
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
@Config(manifest = Config.NONE)
@@ -426,6 +428,50 @@ public void itForwardsOnRequestPermissionsResultToFlutterEngine() {
.onRequestPermissionsResult(any(Integer.class), any(String[].class), any(int[].class));
}
+ @Test
+ public void itSendsInitialRouteFromIntentOnStartIfnoInitialRouteFromActivity() {
+ Intent intent = FlutterActivity.createDefaultIntent(RuntimeEnvironment.application);
+ intent.setData(Uri.parse("http://myApp/custom/route"));
+
+ ActivityController