A Flutter plugin to show a draggable “bubble” (chat‑head style) on Android, with an optional expandable Flutter view.
- Platform: Android (minSdk 24+) 🤖
- Features ⭐:
- Draggable bubble with show/hide
- Expand to a Flutter route
- Foreground service notification
- Event stream: tap, movement, errors
- Overlay permission handling
Add to your pubspec.yaml:
dependencies:
pl_bubble:
path: ../pl_bubbleImport:
import 'package:pl_bubble/pl_bubble.dart';- Ensure your Android project applies the Flutter Gradle plugin and uses minSdk 24+.
- Icons used by the plugin are provided; you can replace them:
android/src/main/res/drawable/ic_close_bubble.xmlandroid/src/main/res/drawable/ic_flutter.xml
Add the following (adjust as needed for your app and targetSdk):
<!-- android/app/src/main/AndroidManifest.xml -->
<manifest>
<!-- Required for showing a bubble above other apps (runtime consent required) -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- Foreground service for long-running bubble overlay -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 13+ notification permission (for foreground notification) -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application>
<!-- Your existing configuration -->
</application>
</manifest>Notes:
- The overlay permission is granted by the user in Settings; the plugin will request/open the Settings screen when needed.
- POST_NOTIFICATIONS is required on Android 13+ for the foreground service notification to be visible.
void initBubble() {
BubbleService.instance.initialize(
const BubbleConfig(
startPosition: BubblePosition(x: 0, y: 300),
bubbleSize: Size(90, 90),
showBubbleWhenInit: false,
expandBubbleConfig: ExpandBubbleConfig(
width: double.maxFinite,
height: 500.0,
routeEngine: "/expandBubble",
),
// Optional notification
// notificationConfig: NotificationConfig(
// contentTitle: "Bubble Service",
// contentText: "Running…",
// ),
),
);
BubbleService.instance.eventStream.listen((event) {
if (event is BubbleClickEvent) {
BubbleService.instance.expandBubble();
}
});
}
Future<void> showBubble() => BubbleService.instance.showBubble();Register an expand route in your MaterialApp 👇:
MaterialApp(
debugShowCheckedModeBanner: false,
routes: {
"/": (_) => const MainPage(),
"/expandBubble": (_) => const ExpandBubblePage(),
},
);- Initialize:
initialize(BubbleConfig config) - Show/hide:
showBubble(),hideBubble(),closeBubble() - Expand/collapse:
expandBubble({bool isRemoveBubble = false}),closeExpandBubble(),hideExpandBubble() - Move:
moveBubble(BubblePosition(x, y)) - Events: subscribe to
eventStream - Permissions:
hasOverlayPermission(),requestOverlayPermission()
BubbleConfig— layout/behavior (size, startPosition, draggable, etc.)ExpandBubbleConfig— expanded view size androuteEngineNotificationConfig— foreground service title/textBubblePosition— x/y
See example/lib/main.dart for a runnable setup demonstrating initialization, events, and expansion.
- If Gradle sync complains about Flutter plugin application, ensure your Android project uses a consistent Flutter Gradle setup and that
local.propertiescontainsflutter.sdk. - If
io.flutter.*is unresolved, sync Gradle and ensure the Flutter plugin is applied.
See LICENSE.
| Feature / Platform | Android | iOS | Web | macOS | Windows | Linux |
|---|---|---|---|---|---|---|
| Show draggable bubble | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Expand bubble (Flutter route) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Foreground notification | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Overlay permission handling | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |