overlay_pop_up

A new Flutter plugin to display pop ups or screens over other apps in Android even when app is closed or killed.

Buy Me A Coffee

Demo

Preview

Android

add this to your AndroidManifest.xml

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

 <application>
        ...
        <service
           android:name="com.requiemz.overlay_pop_up.OverlayService"
           android:exported="false" />
    </application>

Android 14

applications that target SDK 34 and use foreground service should include foregroundServiceType attribute(see documentation).

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

 <application>
        ...
        <service
           android:name="com.requiemz.overlay_pop_up.OverlayService"
           android:exported="false"
           <!-- add this -->
           android:foregroundServiceType="camera, dataSync, location, etc" />
    </application>

Flutter implementation

configure your main.dart entry point a widget to display (make sure to add @pragma('vm:entry-point'))

NOTE: Now you can pass as parameter the dart entry point method name when showOverlay is called

@pragma("vm:entry-point")
void overlayPopUp() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Text('Hello Pub.dev!'),
  ));
}

Overlay Methods

returns true when overlay permission is alreary granted if permission is not granted then open app settings

await OverlayPopUp.requestPermission();

returns true or false according to permission status

await OverlayPopUp.checkPermission();

display your overlay and return true if is showed

PARAMS

  • height is not required by default is MATCH_PARENT

  • width is not required by default is MATCH_PARENT

  • verticalAlignment is not required by default is CENTER for more info see: developer.android.com/reference/android/view/Gravity

  • horizontalAlignment is not required by default is CENTER for more info see: developer.android.com/reference/android/view/Gravity

  • backgroundBehavior by default is focusable flag that is you can take focus inside a overlay for example inside a textfield and tapThrough you can tap through the overlay background even if has MATCH_PARENT sizes.

  • screenOrientation by default orientation is portrait.

  • closeWhenTapBackButton by default when user presses back button the overlay no has any action if you pass true then back button will close overlay.

  • isDraggable by default is false therefore the overlay canĀ“t be dragged.

  • swipeToDismiss by default is false. When enabled, users can drag the overlay to a drop zone (trash icon) at the bottom of the screen to dismiss it. Features include:

    • Drop zone with trash icon appears when dragging starts
    • Overlay shrinks when entering drop zone area
    • Pulse animation on drop zone when overlay is nearby
    • Smooth dismiss animation when released in drop zone
    • Works together with isDraggable for free movement in all directions
  • entryPointMethodName by default is 'overlayPopUp' if you want you can change it

    await OverlayPopUp.showOverlay(
      width: 300,
      height: 350,
      isDraggable: true,
      swipeToDismiss: true, // Enable swipe to dismiss
    );
    

    returns true if overlay closed correctly or already is closed

    await OverlayPopUp.closeOverlay();
    

    returns the overlay status true = open, false = closed

    await OverlayPopUp.isActive();
    

    returns the last overlay position if drag is enabled

    await OverlayPopUp.getOverlayPosition();
    

Bidirectional Messaging

Send Data from Main App to Overlay

// From main app - send to overlay
await OverlayPopUp.sendToOverlay({'data': 'hello from main app!'});
await OverlayPopUp.sendToOverlay('hello');

Send Data from Overlay to Main App

// From overlay widget - send to main app
await OverlayPopUp.sendToMainApp({'from': 'overlay', 'message': 'Hello!'});

Receive Data in Main App (from Overlay)

// In your main app - listen for messages FROM overlay
StreamSubscription? listener;

@override
void initState() {
  super.initState();
  // Initialize message handler early
  OverlayPopUp.initializeMessageHandler();

  // Listen for messages from overlay
  listener = OverlayPopUp.dataListener?.listen((data) {
    print('Received from overlay: $data');
  });
}

@override
void dispose() {
  listener?.cancel();
  super.dispose();
}

Receive Data in Overlay Widget (from Main App)

// In your overlay widget - listen for messages FROM main app
StreamBuilder(
  stream: OverlayPopUp.overlayDataListener,  // Use overlayDataListener here!
  builder: (context, snapshot) {
    return Text(snapshot.data?['message'] ?? 'No data');
  },
)

Summary

Location Send Method Receive Stream
Main App sendToOverlay() dataListener (receives from overlay)
Overlay Widget sendToMainApp() overlayDataListener (receives from main app)

Libraries

overlay_pop_up