floaty_chatheads_android 3.0.0
floaty_chatheads_android: ^3.0.0 copied to clipboard
Android implementation of floaty_chatheads with SYSTEM_ALERT_WINDOW, foreground service, spring physics, theming, and TalkBack accessibility.
Changelog #
3.0.0 #
Breaking release. Minimum Flutter 3.44 / Dart 3.12, iOS 15, Android API 24. Built-in Kotlin end to end. See the migration notes at the end.
entryPointLibrarysupport (three-argumentDartEntrypoint), persisted with the rest of the config.showChatHeadcompletes once the overlay isolate is listening and throwsFloatyOverlayNotReadyException(after closing the overlay) when it never starts.- The overlay engine is reused when the chathead is shown again with the same entry point, and replaced when the entry point changes.
- Animated icon frames render into reused, triple-buffered bitmaps with a
precomputed shadow; frames that arrive during a render are coalesced
per bubble. Replaces
OverlayBitmapPool. - Default bubble and close-target icons decode once at native size; the touch tracker skips no-op WindowManager updates; debug mode stops its frame callback on close.
POST_NOTIFICATIONSdeclared and requested on Android 13+.- The collapsed bubble stack is drawn in its own small touchable window
(
BubbleWindow) that follows the top bubble, instead of in the full-screen window that Android 12+ caps at 80 percent opacity. The bubble is now fully opaque, and fling velocity is measured in screen coordinates. - The bubble window excludes its bounds from system gestures, so dragging an edge-snapped bubble no longer triggers Back.
NotificationConfig.visibilityhonored; channel name and running text moved to overridable string resources; explicitspecialUseforeground service type on Android 14+.showChatHeadfails withnot_attachedinstead of silently succeeding without an engine; the Activity is no longer required to show.- Restore-after-death: the auto-registered overlay-engine plugin instance no longer claims the main-app slot.
- Removed unused
WAKE_LOCKpermission, unusedcolors.xml, and the deprecatedpackageattribute from the manifest; addedconsumer-rules.pro. - Built-in Kotlin: no Kotlin Gradle Plugin is applied;
kotlin {}compiler options, Java 17. AGP 9.5, compileSdk 36, androidx.core 1.18, Material 1.14. Pigeon 29.0.11 with callback-style native signatures. FloatyChatheadsAndroidis nowfinal.- Minimum Flutter 3.44 / Dart 3.12.
2.1.0 #
New: PanelAnchor #
- feat: new
PanelAnchorenum (below/above/auto) onChatHeadConfig.panelAnchorcontrols where the expanded content panel opens relative to the bubble. The panel is always clamped to the screen bounds;autopicks below when there is room, otherwise above.
Behavior change (non-breaking API) #
-
The content panel now opens below the bubble by default. Previously the panel rendered from the top of the screen with the bubble row overlapping its top edge (Android) or grew down-right from the bubble's corner (iOS). Full-screen panels are unaffected (clamping keeps them at the top). Overlays that reserved top padding for the bubble row on card-sized panels should remove it.
-
On Android,
abovesnaps the expanded bubble row to the bottom of the screen so the panel has room above it. The anchor is resolved once per expand (no mid-animation flips) and survivespersistOnAppCloserestarts. -
fix: calling
FloatyOverlay.getOverlayPosition()from the overlay isolate crashed with a decode error because the overlay isolate's Pigeon codec assigns different type tags than the platform contract serving the same channels. Shared overlay channels now use only standard-codec payloads (getOverlayPositionreturns a map,updateFlagtakes the enum index). -
fix: the expanded panel was hard-coded to x=0 (assumed a full-width panel), so card-sized panels on wide/tablet screens rendered at the left edge while the bubble sat on the right. The panel now follows the active bubble's edge and is clamped on-screen; the scale-animation pivot tracks the bubble.
Chores #
compileSdk35 to 36; standalone build AGP 8.12 to 9.2. The dual-compat conditional KGP pattern is retained: it keeps Flutter 3.27 to 3.43 consumers building today and activates Built-in Kotlin automatically once Flutter's tooling stops applying KGP to plugins.- Pigeon regenerated with 26.3.x.
- Internal cleanup: expand logic deduplicated (was copied in three places), window-flag toggling extracted into a helper, velocity thresholds named.
2.0.0 #
Released as part of the floaty_chatheads 2.0 line. See the main package CHANGELOG for the full migration guide.
Toolchain (BREAKING) #
- Android
minSdkraised to 24 (was 23). compileSdkbumped to 35 (Android 15).- Plugin Java/Kotlin JVM target raised to 11 (was 1.8).
- Dart SDK floor
^3.0.0, Flutter floor>=3.10.0, the bare minimum the Dart code requires (final class,sealed class, records, pattern matching). The Kotlin Gradle setup stays on the legacyapply plugin: 'kotlin-android'+kotlinOptions { ... }pattern so it works on every Flutter version with Kotlin support. - Pigeon constraint normalized to
^26.3.3. - Depends on
floaty_chatheads_platform_interface: ^2.0.0.
Built-in Kotlin migration deferred #
android/build.gradle keeps the legacy pattern:
plugins {
id "com.android.library"
id "kotlin-android"
}
android {
// ...
kotlinOptions {
jvmTarget = '11'
}
}
Switching to Flutter's Built-in Kotlin pattern (top-level
kotlin { compilerOptions { ... } } and conditional KGP application)
would require Kotlin Gradle Plugin 2.0+, which Flutter only ships
starting at 3.27. Adopting it would lock out every consumer on
Flutter 3.10 to 3.26 just to silence one warning.
On Flutter 3.44+ you will see:
WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): floaty_chatheads_android, ...
That's intentional. When Flutter promotes the warning to a hard error, this plugin will migrate to Built-in Kotlin in a major release; until then, compatibility with the 3.10 to 3.43 install base is the priority. See https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-plugin-authors for the migration path.
Internals #
showChatHeadnow delegates default-value resolution toChatHeadConfigResolverinfloaty_chatheads_platform_interface, eliminating duplication with the iOS Dart shim. Pigeon enum/message construction stays in this package.
1.1.0 #
Enhancements #
- Widget-based chathead icons. The chathead bubble icon can now be
any Flutter widget (rendered to an image via the Dart offscreen
pipeline). Supports static widgets and animated widgets with
per-frame RGBA updates through the new
updateChatHeadIconPigeon method. Bitmap creation from RGBA bytes runs onDispatchers.Defaultto keep the main thread free. - Widget-based close icons. The close target icon and background can also be Flutter widgets. Widget-rendered close icons are scaled to the full close-target size (64 dp) instead of the 28 dp default, so the widget design controls the visual appearance.
- Added
closeIconIsWidget/closeBackgroundIsWidgetflags toOverlayConfigfor size-aware scaling inClose.kt.
Dependencies #
- Bumped
floaty_chatheads_platform_interfaceto^1.0.5.
1.0.7 #
Enhancements #
- Added
autoLaunchOnBackgroundsupport. The plugin registersApplication.ActivityLifecycleCallbacksto detect when all activities leave the foreground. When enabled, the chathead is shown automatically on background and dismissed on foreground. - Added
persistOnAppClosesupport. Controls whether the foreground service returnsSTART_STICKY(survives app death) orSTART_NOT_STICKY(stops on main app disconnect). When disabled, the service callscloseWindow(true)as soon as the main app disconnects. - Both new flags are persisted to SharedPreferences for recovery
after a
START_STICKYrestart.
Performance #
- Migrated from
ExecutorServiceto Kotlin Coroutines. All icon I/O (asset, network, byte-array decoding) now runs onDispatchers.IOvia structuredasync/await, replacing the previousExecutorService+Callableapproach. The main thread is never blocked: each icon load has an individualwithTimeoutOrNullguard. - Added
CoroutineScopelifecycle management. ASupervisorJob-backed scope (pluginScope) is created inonAttachedToEngineand cancelled inonDetachedFromEngine, ensuring all in-flight coroutines are cleaned up when the plugin is detached.
Bug Fixes #
- Fixed chathead freeze caused by async race condition.
showChatHeadandaddChatHeadare now@asyncPigeon methods. The DartFutureresolves only after the overlay window is fully created, preventing the half-initialized state that caused the overlay to appear frozen.
Dependencies #
- Added
kotlinx-coroutines-android:1.7.3.
1.0.6 #
Bug Fixes #
- Fixed
CompletableFuturecrash on Android 6.0 (API 23).CompletableFuture.supplyAsyncrequires API 24+, but the module'sminSdkVersionis 23. Replaced withExecutorService+Callable(available since API 1) for parallel icon loading. - Fixed resource leak in
loadBitmapFromNetwork.InputStreamandHttpURLConnectionare now released viause { }and afinallyblock, ensuring cleanup even ifBitmapFactory.decodeStreamthrows.
1.0.5 #
Bug Fixes #
- Fixed chathead close crash when GPS streaming is active. Removing
the
FlutterViewfrom its parent during the drag-to-close gesture while the overlay engine was still processing GPS data caused a 300ms window of orphaned rendering. The redundantcontent.removeAllViews()call was removed, sincecloseWindow(true)already handles cleanup viadetachEngine(). - Fixed foreground service not stopping after chathead close. The
destroyEngine()call threw an exception (self-destructing engine from Pigeon handler), preventingstopSelf()from being reached. Reordered service teardown sostopForeground()andstopSelf()execute beforedestroyEngine(), with the latter wrapped in a try/catch. - Fixed NPE in
hideChatHeadsdelayed callback. ReplacedFloatyContentJobService.instance!!force-unwrap with safe call?.to handle cases where the service is already destroyed.
Enhancements #
- Deferred connection signal on app restart.
onAttachedToEngineno longer sendsconnected:trueto the overlay immediately when an existing service is detected. Instead it sets up the message relay viaonMainAppRelay()and defers the connection signal untilisChatHeadActive()is called from the Dart side, which acts as an implicit "ready" signal that guarantees channel handlers are registered before the overlay flushes its action queue. - Native close notification to main app. When the chathead is
closed via drag-to-close or the overlay's close button, the native
layer now sends a system envelope message to the main Dart isolate
so
FloatyChatheads.onClosedfires reliably. - Extracted magic delay constants. Replaced inline delay numbers
with named companion-object constants (
CLOSE_DELAY_MS,HIDE_DELAY_MS,EXPAND_CONTENT_DELAY_MS). - Improved null safety in
onSpringUpdate. Replaced ~10topChatHead!!force-unwraps with a safe local binding. - DRY: consolidated
hideChatHeads(). Merged two near-identical branches into a single method with anisClosedparameter. - DRY: extracted
notifyOverlay()helper. Consolidated 5 repeated Pigeon notification methods into a single inline function. - Added
NotificationConfig.descriptionsupport. The foreground notification now shows a custom title and body text whendescriptionis provided.
1.0.4 #
Bug Fixes #
- Fixed overlay and main app communication completely broken. When
FlutterEngineGroup.createAndRunEngine()creates the overlay engine, it auto-registers all plugins, includingFloatyChatheadsPlugin. This secondonAttachedToEnginecall overwrote the companion-objectactiveInstanceandmainMessengerwith the overlay engine's instances, causing all messages from the overlay to loop back to the overlay instead of reaching the main Dart isolate. Added anactiveInstance != nullguard inonAttachedToEngineto skip setup on the overlay engine, and a matchingisMainEnginePluginguard inonDetachedFromEngineto prevent the overlay engine from tearing down the main engine's state.
Metadata #
- Shortened pubspec description to meet pub.dev 60 to 180 character guideline.
- Added
example/example.mdfor the pub.dev example tab.
1.0.3 #
Enhancements #
- Upgraded Pigeon to 26.2.3. Regenerated all Dart and Kotlin Pigeon bindings. No API surface changes; the upgrade picks up codec and code-generation improvements from the latest Pigeon release.
1.0.2 #
Enhancements #
- Debug logs are now optional and silent by default. All native
Log.d/w/eoutput is gated behindManagment.debugMode. Developers enable verbose logging by settingdebugMode: trueinChatHeadConfig; production builds produce zero log noise. Three convenience helpers (Managment.logD,logW,logE) replace every rawLog.*call acrossFloatyContentJobService,FlutterContentPanel, andChatHeads.
Bug Fixes #
- Fixed content panel rendering fullscreen on subsequent launches.
The root cause was a two-stage data loss: when the service had not
started yet,
showChatHead()only persisted the entry point toSharedPreferences, omitting content dimensions and all other config. When the service'sonCreate()later calledrestoreConfig(), it overwrote the in-memoryManagmentvalues withnull, causingcreateWindow()to skipsetContentSize()and fall back toMATCH_PARENT. The fix saves the full config to SharedPreferences in the plugin's else branch and adds a defensive guard inonCreate()to skiprestoreConfig()whenManagmentis already populated. - Fixed content panel dimensions and touch interaction leaking between
chathead sessions. The plugin now explicitly tears down stale windows
and calls
createWindow()directly with freshManagmentvalues instead of deferring toonStartCommand().
1.0.1 #
- Documentation and metadata updates.
1.0.0 #
Initial Release #
- Android implementation of
floaty_chatheadsusingSYSTEM_ALERT_WINDOW. - Pigeon-generated type-safe communication between Dart and Kotlin.
- Facebook Rebound spring physics for bubble drag and snap animations.
- Foreground service with configurable notification.
- Separate
FlutterEnginefor overlay content panels. - Theming support: badge colors, bubble border, shadow, close tint.
- Overlay palette delivery to Flutter overlay isolate.
- Size preset resolution with half-screen and full-screen sentinels.
- Debug overlay view with bounds, spring HUD, FPS counter, and Pigeon message log.
- Full TalkBack accessibility: content descriptions, state announcements, focus management, and custom accessibility actions.
- Snap-to-edge with configurable margin and position persistence.
- Entrance animations: slide-in and fade-in variants.
- Badge counter updates from both main app and overlay.
- Programmatic expand / collapse.