From d7718617183dc7a510fb7d607153917aae2c2163 Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Tue, 2 Feb 2021 12:03:13 -0800 Subject: [PATCH 1/3] fixes android deeplink query paremeter null crashes --- .../FlutterActivityAndFragmentDelegate.java | 2 +- ...lutterActivityAndFragmentDelegateTest.java | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index 0990604b9ba1b..e3d0235ff621e 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -400,7 +400,7 @@ private String maybeGetInitialRouteFromIntent(Intent intent) { Uri data = intent.getData(); if (data != null && !data.getPath().isEmpty()) { String pathAndQuery = data.getPath(); - if (!data.getQuery().isEmpty()) { + if (data.getQuery() != null && !data.getQuery().isEmpty()) { pathAndQuery += "?" + data.getQuery(); } return pathAndQuery; 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 509b97791cd9c..2a4928cb1c480 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java @@ -456,6 +456,33 @@ public void itForwardsOnRequestPermissionsResultToFlutterEngine() { .setInitialRoute("/custom/route?query=test"); } + @Test + public void + itSendsInitialRouteFromIntentOnStartIfNoInitialRouteFromActivityAndShouldHandleDeeplinkingNoQueryParameter() { + Intent intent = FlutterActivity.createDefaultIntent(RuntimeEnvironment.application); + intent.setData(Uri.parse("http://myApp/custom/route")); + + ActivityController activityController = + Robolectric.buildActivity(FlutterActivity.class, intent); + FlutterActivity flutterActivity = activityController.get(); + + when(mockHost.getActivity()).thenReturn(flutterActivity); + when(mockHost.getInitialRoute()).thenReturn(null); + 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 setup in onAttach(). + delegate.onAttach(RuntimeEnvironment.application); + // Emulate app start. + delegate.onStart(); + + // Verify that the navigation channel was given the initial route message. + verify(mockFlutterEngine.getNavigationChannel(), times(1)) + .setInitialRoute("/custom/route"); + } + @Test public void itSendsdefaultInitialRouteOnStartIfNotDeepLinkingFromIntent() { // Creates an empty intent without launch uri. @@ -501,6 +528,26 @@ public void itSendsPushRouteMessageWhenOnNewIntent() { .pushRoute("/custom/route?query=test"); } + @Test + public void itSendsPushRouteMessageWhenOnNewIntentNoQuery() { + 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 setup in onAttach(). + delegate.onAttach(RuntimeEnvironment.application); + + Intent mockIntent = mock(Intent.class); + when(mockIntent.getData()).thenReturn(Uri.parse("http://myApp/custom/route")); + // Emulate the host and call the method that we expect to be forwarded. + delegate.onNewIntent(mockIntent); + + // Verify that the navigation channel was given the push route message. + verify(mockFlutterEngine.getNavigationChannel(), times(1)) + .pushRoute("/custom/route"); + } + @Test public void itForwardsOnNewIntentToFlutterEngine() { // Create the real object that we're testing. From e30fa48594c52022cfe8fc1d22590dcd63088d7e Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Tue, 2 Feb 2021 12:36:28 -0800 Subject: [PATCH 2/3] update --- .../android/FlutterActivityAndFragmentDelegateTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2a4928cb1c480..09979bd91a3cd 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java @@ -529,7 +529,7 @@ public void itSendsPushRouteMessageWhenOnNewIntent() { } @Test - public void itSendsPushRouteMessageWhenOnNewIntentNoQuery() { + public void itSendsPushRouteMessageWhenOnNewIntentNoQueryParameter() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); From 71b2799189aafa519a6d68519e35fafc6c74bc3f Mon Sep 17 00:00:00 2001 From: Chun-Heng Tai Date: Tue, 2 Feb 2021 12:37:30 -0800 Subject: [PATCH 3/3] format --- .../FlutterActivityAndFragmentDelegateTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) 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 09979bd91a3cd..848ad8505495e 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java @@ -456,7 +456,7 @@ public void itForwardsOnRequestPermissionsResultToFlutterEngine() { .setInitialRoute("/custom/route?query=test"); } - @Test + @Test public void itSendsInitialRouteFromIntentOnStartIfNoInitialRouteFromActivityAndShouldHandleDeeplinkingNoQueryParameter() { Intent intent = FlutterActivity.createDefaultIntent(RuntimeEnvironment.application); @@ -479,8 +479,7 @@ public void itForwardsOnRequestPermissionsResultToFlutterEngine() { delegate.onStart(); // Verify that the navigation channel was given the initial route message. - verify(mockFlutterEngine.getNavigationChannel(), times(1)) - .setInitialRoute("/custom/route"); + verify(mockFlutterEngine.getNavigationChannel(), times(1)).setInitialRoute("/custom/route"); } @Test @@ -528,7 +527,7 @@ public void itSendsPushRouteMessageWhenOnNewIntent() { .pushRoute("/custom/route?query=test"); } - @Test + @Test public void itSendsPushRouteMessageWhenOnNewIntentNoQueryParameter() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. @@ -544,8 +543,7 @@ public void itSendsPushRouteMessageWhenOnNewIntentNoQueryParameter() { delegate.onNewIntent(mockIntent); // Verify that the navigation channel was given the push route message. - verify(mockFlutterEngine.getNavigationChannel(), times(1)) - .pushRoute("/custom/route"); + verify(mockFlutterEngine.getNavigationChannel(), times(1)).pushRoute("/custom/route"); } @Test