bring_app_to_foreground 0.1.1 copy "bring_app_to_foreground: ^0.1.1" to clipboard
bring_app_to_foreground: ^0.1.1 copied to clipboard

PlatformAndroid

Bring a Flutter app to the foreground from the background on Android (incoming VoIP/dispatch calls, alarms) via the Display-over-other-apps permission.

bring_app_to_foreground #

Bring your Flutter app to the foreground from the background on Android — even when the screen is off or locked.

The classic use case is a real-time event that has to put a UI in front of the user without them touching the phone: an incoming VoIP / taxi-dispatch call, an alarm, or a critical alert. Your background code calls bringToFront() and your own activity is reordered to the front, the screen wakes, and your UI shows on top of the lockscreen.

This was extracted from a production taxi-driver app and is validated on Android 14/15.

Why this is harder than it looks #

On Android 12+ (API 31+) a background app cannot bring itself to the foreground by default:

  • A plain ActivityManager.moveTaskToFront() from a background socket/callback is silently blocked by Background Activity Launch (BAL) restrictions.
  • USE_FULL_SCREEN_INTENT notifications are auto-denied for non-dialer apps on Android 14+.

The one mechanism a normal app can rely on is the SYSTEM_ALERT_WINDOW ("Display over other apps") permission, which is a hard BAL exemption. With it granted, the app may relaunch its own task from the background — locked or unlocked, over any other app. The catch: this permission must be granted manually by the user from a system settings page. There is no inline runtime dialog.

So this plugin does exactly two jobs:

  1. Check / request the overlay permission.
  2. Bring the app to the front (relaunch the task with REORDER_TO_FRONT plus wake / show-when-locked flags).

Platform support #

Platform Behavior
Android ✅ Full support (API 21+; logic is version-guarded for 12+).
iOS No-op. iOS has no public task-reorder API (CallKit is separate).
Web No-op.
Desktop No-op.

Every method is safe to call on any platform and never throws. Off Android, bringToFront() does nothing and the permission methods return false.

Install #

dependencies:
  bring_app_to_foreground: ^0.1.0
import 'package:bring_app_to_foreground/bring_app_to_foreground.dart';

Manifest — nothing to add #

The plugin declares SYSTEM_ALERT_WINDOW in its own manifest, and Android's manifest merging pulls it into your app automatically. You do not need to add the permission to your app's AndroidManifest.xml.

Usage #

// 1. Check whether the OS will allow the foreground pull.
final granted = await BringAppToForeground.hasPermission();

// 2. If not, send the user to the settings page to grant it.
//    (Show your own explanation first — see "Asking nicely" below.)
if (!granted) {
  await BringAppToForeground.requestPermission();
}

// 3. Whenever a background event needs the app on screen:
await BringAppToForeground.bringToFront();

Incoming-call example #

/// Call this from your VoIP / FCM / socket handler when a call arrives.
Future<void> onIncomingCall(Call call) async {
  if (await BringAppToForeground.hasPermission()) {
    await BringAppToForeground.bringToFront(); // app pops to the front, locked or not
  }
  // Keep showing a full-screen-intent / heads-up notification as a fallback
  // for when the permission isn't granted — that's notification work and lives
  // in your app, not in this plugin.
  navigateToIncomingCallScreen(call);
}

Re-checking after the user returns #

requestPermission() opens a system settings page; the user leaves your app to toggle the switch, so the value it returns reflects the status before they come back. Re-check on resume:

class _MyState extends State<MyWidget> with WidgetsBindingObserver {
  bool _granted = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _refresh();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) _refresh();
  }

  Future<void> _refresh() async {
    final granted = await BringAppToForeground.hasPermission();
    if (mounted) setState(() => _granted = granted);
  }
}

A complete, runnable version of this is in example/.

Asking nicely #

"Display over other apps" is a sensitive permission. Best practice:

  • Request it as a non-blocking onboarding step — the app should keep working if the user declines (they just lose the auto-foreground).
  • Show a short prominent disclosure dialog first, explaining why you need it (e.g. "so incoming calls can wake your screen"), then call requestPermission().

What you have to do — and what you don't #

You do NOT need to:

  • ❌ Add any permission to your app's AndroidManifest.xml. SYSTEM_ALERT_WINDOW (and REORDER_TASKS) are declared in the plugin and merged into your app automatically. (Verified: an app that declares zero permissions ends up with both in its merged manifest just by depending on this package.)
  • ❌ Reference or subclass MainActivity, register anything, or edit Gradle.
  • ❌ Add permission_handler or any other dependency — this plugin has none.

You DO need to:

  • ✅ Call requestPermission() once so the user manually grants "Display over other apps" in system settings (there is no silent/runtime grant for it), then re-check with hasPermission() on resume.
  • ✅ Call bringToFront() from your own background trigger (VoIP/FCM/socket).

That's the whole integration — exactly the Usage snippet. No hidden steps.

Limitations — read this #

This plugin reorders your app's existing task to the front. It is not a background-execution or wake-from-dead framework. Concretely:

  • The user must grant the overlay permission manually. Until they do, bringToFront() is silently blocked by the OS on Android 12+ (hasPermission() returns false). This is an Android platform rule, not a plugin choice.
  • Your app must still be alive in the background. If the process was killed or swiped from Recents, there is no Dart code running to call bringToFront(), and there is no Activity to reorder. In that case you first need a background waker — a high-priority FCM data message, a foreground service, or a background isolate — to start your Dart code, which then calls bringToFront(). This plugin does not keep your app alive.
  • An Activity must be attached. Called from a context with no Activity (e.g. a bare background isolate), bringToFront() logs a warning and no-ops instead of throwing.
  • Full-screen-intent notifications are separate. Showing a call UI on the lockscreen via a notification is notification work that lives in your app; it is intentionally out of scope here.
  • Android only. iOS/web/desktop are safe no-ops (see the table above).

API #

Method Returns Description
bringToFront() Future<void> Pull the app's task to the front; wake the screen; show over lock.
hasPermission() Future<bool> Is "Display over other apps" granted? false off Android.
requestPermission() Future<bool> Open the settings page; returns the (pre-return) status.

How it works under the hood #

On bringToFront() the plugin, on the bound activity:

  1. Calls setShowWhenLocked(true) + setTurnScreenOn(true) (or the legacy window flags below API 27) so the app surfaces over the keyguard.
  2. Resolves getLaunchIntentForPackage(packageName) and starts it with FLAG_ACTIVITY_NEW_TASK | REORDER_TO_FRONT | SINGLE_TOP.
  3. Also calls moveTaskToFront(...) as a belt-and-suspenders fallback.

It's ActivityAware, so it always acts on the current activity rather than hard-referencing your MainActivity.

License #

MIT — see LICENSE.

0
likes
160
points
--
downloads

Documentation

API reference

Publisher

verified publisherorestislef.gr

Weekly Downloads

Bring a Flutter app to the foreground from the background on Android (incoming VoIP/dispatch calls, alarms) via the Display-over-other-apps permission.

Homepage
Repository (GitHub)
View/report issues

Topics

#android #foreground #voip #background #lockscreen

License

MIT (license)

Dependencies

flutter

More

Packages that depend on bring_app_to_foreground

Packages that implement bring_app_to_foreground