0 purchases
system alert window
system_alert_window #
A flutter plugin to show Truecaller like overlay window, over all other apps along with callback events. Android Go or Android 11 & above, this plugin shows notification bubble, in other android versions, it shows an overlay window.
Android #
Demo #
1. Clip of example app and 2. Working of button click in the background
Manifest #
//Permissions
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE " />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
//Linking the previously added application class
android:name=".Application"
android:label="system_alert_window_example"
android:icon="@mipmap/ic_launcher">
copied to clipboard
Android 10 & below, Android GO (API 27)
Uses 'draw on top' permission and displays it as a overlay window
Android 11 & above
With SystemWindowPrefMode.OVERLAY, system alert windows uses 'overlay functionality' wherever it's supported. In that mode, it will show as bubbles if the 'display over other apps' is not supported.
With SystemWindowPrefMode.DEFAULT/SystemWindowPrefMode.BUBBLE, User has to allow 'All conversations can bubble' in the notification settings of the app. Uses Android Bubble APIs to show the overlay window inside a notification bubble.
Android GO (API 29)
User has to manually enable bubbles from the developer options. Uses Android Bubble APIs to show the overlay window inside a notification bubble.
IOS #
Displays as a notification in the notification center [Help Needed]
Example #
Show Overlay
Request overlay permission
await SystemAlertWindow.requestPermissions;
copied to clipboard
Inside main.dart create an entry point for your Overlay widget; #
// overlay entry point
@pragma("vm:entry-point")
void overlayMain() {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: Material(child: Text("My overlay"))
));
}
//Open overLay content
// - Optional arguments:
/// `gravity` Position of the window and default is [SystemWindowGravity.CENTER]
/// `width` Width of the window and default is [Constants.MATCH_PARENT]
/// `height` Height of the window and default is [Constants.WRAP_CONTENT]
/// `notificationTitle` Notification title, applicable in case of bubble
/// `notificationBody` Notification body, applicable in case of bubble
/// `prefMode` Preference for the system window. Default is [SystemWindowPrefMode.DEFAULT]
/// `isDisableClicks` Disables the clicks across the system window. Default is false. This is not applicable for bubbles.
await SystemAlertWindow.showSystemWindow();
/// update the overlay flag while the overlay in action
/// - Optional arguments:
/// `gravity` Position of the window and default is [SystemWindowGravity.CENTER]
/// `width` Width of the window and default is [Constants.MATCH_PARENT]
/// `height` Height of the window and default is [Constants.WRAP_CONTENT]
/// `notificationTitle` Notification title, applicable in case of bubble
/// `notificationBody` Notification body, applicable in case of bubble
/// `prefMode` Preference for the system window. Default is [SystemWindowPrefMode.DEFAULT]
/// `isDisableClicks` Disables the clicks across the system window. Default is false. This is not applicable for bubbles.
await FlutterOverlayWindow.updateSystemWindow();
// closes overlay if open
await SystemAlertWindow.closeSystemWindow();
// broadcast data to and from overlay app
await SystemAlertWindow.sendMessageToOverlay("Hello from the other side");
//streams message shared between overlay and main app
SystemAlertWindow.overlayListener.listen((event) {
log("Current Event: $event");
});
copied to clipboard
Close the overlay #
SystemAlertWindow.closeSystemWindow();
copied to clipboard
Isolate communication
Use this snippet, if you want the callbacks on your main thread, instead of handling them in an isolate (like mentioned above)
Create an isolate_manager.dart
import 'dart:isolate';
import 'dart:ui';
class IsolateManager{
static const FOREGROUND_PORT_NAME = "foreground_port";
static SendPort lookupPortByName() {
return IsolateNameServer.lookupPortByName(FOREGROUND_PORT_NAME);
}
static bool registerPortWithName(SendPort port) {
assert(port != null, "'port' cannot be null.");
removePortNameMapping(FOREGROUND_PORT_NAME);
return IsolateNameServer.registerPortWithName(port, FOREGROUND_PORT_NAME);
}
static bool removePortNameMapping(String name) {
assert(name != null, "'name' cannot be null.");
return IsolateNameServer.removePortNameMapping(name);
}
}
copied to clipboard
While initializing system alert window in your code
await SystemAlertWindow.checkPermissions;
ReceivePort _port = ReceivePort();
IsolateManager.registerPortWithName(_port.sendPort);
_port.listen((dynamic callBackData) {
String tag= callBackData[0];
switch (tag) {
case "personal_btn":
print("Personal button click : Do what ever you want here. This is inside your application scope");
break;
case "simple_button":
print("Simple button click : Do what ever you want here. This is inside your application scope");
break;
case "focus_button":
print("Focus button click : Do what ever you want here. This is inside your application scope");
break;
}
});
SystemAlertWindow.registerOnClickListener(callBackFunction);
copied to clipboard
Now the callBackFunction should looks like
bool callBackFunction(String tag) {
print("Got tag " + tag);
SendPort port = IsolateManager.lookupPortByName();
port.send([tag]);
return true;
}
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.