diff --git a/packages/quick_actions/quick_actions_android/android/src/main/java/io/flutter/plugins/quickactions/QuickActions.java b/packages/quick_actions/quick_actions_android/android/src/main/java/io/flutter/plugins/quickactions/QuickActions.java index 5d07406bdac0..f738d5722093 100644 --- a/packages/quick_actions/quick_actions_android/android/src/main/java/io/flutter/plugins/quickactions/QuickActions.java +++ b/packages/quick_actions/quick_actions_android/android/src/main/java/io/flutter/plugins/quickactions/QuickActions.java @@ -11,6 +11,7 @@ import android.content.Intent; import android.content.res.Resources; import android.os.Build; +import android.util.Log; import androidx.annotation.ChecksSdkIntAtLeast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -28,6 +29,7 @@ import org.jetbrains.annotations.NotNull; final class QuickActions implements AndroidQuickActionsApi { + private static final String TAG = "QuickActionsAndroid"; static final String EXTRA_ACTION = "some unique action key"; private final Context context; @@ -102,10 +104,12 @@ public void clearShortcutItems() { return null; } if (activity == null) { - throw new FlutterError( - "quick_action_getlaunchaction_no_activity", - "There is no activity available when launching action", - null); + // The engine can run without an attached activity, for instance when it is cached and warmed + // up by a background service. Nothing launched the app in that case, so there is no launch + // action to report. Any action that arrives later is reported through the plugin's + // onNewIntent listener once an activity attaches. + Log.d(TAG, "There is no activity available when getting the launch action."); + return null; } final Intent intent = activity.getIntent(); final String launchAction = intent.getStringExtra(EXTRA_ACTION); diff --git a/packages/quick_actions/quick_actions_android/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java b/packages/quick_actions/quick_actions_android/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java index 114201240d74..100f4a7a8528 100644 --- a/packages/quick_actions/quick_actions_android/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java +++ b/packages/quick_actions/quick_actions_android/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java @@ -6,8 +6,11 @@ import static io.flutter.plugins.quickactions.QuickActions.EXTRA_ACTION; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.app.Activity; @@ -50,6 +53,21 @@ public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHa static final int UNSUPPORTED_BUILD = 24; static final String SHORTCUT_TYPE = "action_one"; + @Test + public void getLaunchAction_noActivity_returnsNull() { + // Arrange + // Build.VERSION.SDK_INT is 0 in unit tests, so the version check is stubbed to make sure the + // null activity, and not the unsupported version, is what is being exercised here. + final QuickActions quickActions = spy(new QuickActions(mock(Context.class))); + doReturn(true).when(quickActions).isVersionAllowed(); + + // Act + final String launchAction = quickActions.getLaunchAction(); + + // Assert + assertNull(launchAction); + } + @Test public void canAttachToEngine() { final TestBinaryMessenger testBinaryMessenger = new TestBinaryMessenger();