Repository navigation
Description
Steps to reproduce
QuickActionsAndroid.initialize() throws PlatformException(quick_action_getlaunchaction_no_activity) whenever main() runs in a FlutterEngine that has no Activity attached. Apps cannot prevent this, because initialize() calls getLaunchAction() unconditionally.
The easiest real-world trigger is a cached engine shared with a background service. audio_service is a common example: its AudioServiceActivity supplies a cached engine via AudioServicePlugin.getFlutterEngine(), and AudioService.onCreate() warms up that same engine. So the process, and main() with it, starts with no Activity at all when the service is started headlessly by a media button, a Bluetooth device, or Android Auto binding the MediaBrowserService.
Minimal reproduction using the app in this repo's quick_actions example plus audio_service:
- Set the launcher activity to
com.ryanheise.audioservice.AudioServiceActivityinAndroidManifest.xml. - Call
QuickActions().initialize(...)inmain(). - Start the audio service without any UI:
(on API < 26,
adb shell am start-foreground-service -n <package>/com.ryanheise.audioservice.AudioServiceadb shell am startservice)
I reproduced this on Android 12 (API 31), Android 8.0 (API 26) and Android 16 (API 36) emulators. API 24 is unaffected, since isVersionAllowed() returns null before the activity check.
A second trigger exists without any background service: because a cached engine outlives its activity, the Dart isolate keeps running after the activity detaches, so getLaunchAction() can be reached with activity == null if the activity is destroyed while main() is still awaiting.
Expected results
initialize() completes and reports no launch action. "There is no Activity, therefore nothing launched this app via a shortcut" is a legitimate state with an obvious correct answer: null.
Actual results
initialize() throws:
PlatformException(quick_action_getlaunchaction_no_activity, There is no activity available when launching action, null, null)
#0 AndroidQuickActionsApi.getLaunchAction (package:quick_actions_android/src/messages.g.dart:123:7)
#1 QuickActionsAndroid.initialize (package:quick_actions_android/quick_actions_android.dart:34:28)
Why I think this should return null rather than throw
QuickActions.java#L104-L109 (still present at main, unchanged since before the Pigeon conversion in #5099):
if (activity == null) {
throw new FlutterError(
"quick_action_getlaunchaction_no_activity",
"There is no activity available when launching action",
null);
}-
The throw provides no recovery value. When an
Activitylater attaches,QuickActionsPlugin.onAttachedToActivity()callsonNewIntent(activity.getIntent()), which reports the shortcut throughAndroidQuickActionsFlutterApi.launchAction(). Andinitialize()registers the Dart handler before it callsgetLaunchAction(), so the handler is already installed when the exception is thrown. I verified on-device that swallowing the exception loses nothing: the shortcut is still delivered correctly. The throw only converts a recoverable state into an app-visible error. -
nullis already the established idiom in this method for "cannot answer":if (!isVersionAllowed()) { return null; }on the line above. -
Callers have no way to check first. There is no
hasActivity-style API, so the only remedy available to apps is atry/catchon a magic error-code string aroundinitialize(), in every app that could ever run engine-first. -
This is not app misuse. Cached and pre-warmed engines are a supported Flutter pattern (
FlutterEngineCache,FlutterEngineGroup), and [quick_actions] start event is reported twice with pre-warmed FlutterEngine #89615 is another known quick_actions issue in the same pre-warmed-engine area.
I'd suggest logging a warning and returning null, so a genuinely misconfigured launcher activity (per the README note about #152883) stays diagnosable in logcat without being fatal to the caller. Happy to open a PR along those lines.
Code sample
Code sample
// Runs when the engine is warmed up by a background service, with no Activity attached.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
// Throws PlatformException(quick_action_getlaunchaction_no_activity).
await const QuickActions().initialize((type) => debugPrint(type));
}Logs
Logs
E flutter : [ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: PlatformException(quick_action_getlaunchaction_no_activity, There is no activity available when launching action, null, null)
E flutter : #0 AndroidQuickActionsApi.getLaunchAction (package:quick_actions_android/src/messages.g.dart:123:7)
E flutter : <asynchronous suspension>
E flutter : #1 QuickActionsAndroid.initialize (package:quick_actions_android/quick_actions_android.dart:34:28)
E flutter : <asynchronous suspension>Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.44.2, on Ubuntu 26.04 LTS 7.0.0-28-generic, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
Reproduced with quick_actions 1.1.0 / quick_actions_android 1.0.21 and again on
quick_actions_android 1.0.32 (latest).
Activity
mbcorona commentedon Jul 31, 2026
Hi @Sembauke , thanks for the detailed report and the proposed fix.
Routing to the Android team for evaluation.
[quick_actions_android] Return null from getLaunchAction when no acti…
github-actions commentedon Oct 20, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.