nativeflow 0.1.3
nativeflow: ^0.1.3 copied to clipboard
OS-compliant background runtime for long-running Flutter apps. Keep your own socket/MQTT/location libraries; get recovery, persistent events and notifications.
NativeFlow
An OS-compliant native runtime for long-running, event-driven Flutter apps:
driver, delivery, fleet, field-service, IoT, chat and voice-agent apps.
NativeFlow provides the runtime. Your libraries own the protocol. The OS owns background policy.
Features #
| Android | iOS | |
|---|---|---|
| One runtime for all workloads (single foreground service) | ✅ | coordinated background modes |
| Adapters for your own libraries, with backoff + network-aware recovery | ✅ | ✅ |
| Restore after process death / app relaunch | ✅ | ✅ (relaunch) |
| Opt-in reboot restore | ✅ | — |
| Adapters survive the UI being swiped away (background engine) | ✅ | — |
| Persistent, acknowledged event store | ✅ | ✅ |
| Network state events | ✅ | ✅ |
| Notifications: channels, actions, deep links, groups | ✅ | ✅ |
| Full-screen call/alarm notifications | ✅ | — |
| Native floating overlays | ✅ | — |
| Live Activities / widget refresh | — | ✅ |
| OS-scheduled background tasks | JobScheduler | BGTaskScheduler |
Honest capability report (supported … unavailable) |
✅ | ✅ |
What NativeFlow is NOT #
- Not a socket, MQTT, HTTP, BLE or location library. It never opens a connection or reads GPS for you.
- Not a way to keep an app "alive forever" or to bypass Doze, OEM battery managers or iOS suspension. No library can guarantee a connection.
- Not a database. The event store is a bounded queue of runtime signals.
Install #
dependencies:
nativeflow: ^0.1.0
Then follow Android setup and iOS setup. Declare only what your app legitimately uses.
Quick start #
import 'package:nativeflow/nativeflow.dart';
await NativeFlow.initialize();
await NativeFlow.attach(RuntimeAdapter(
id: 'driver',
requirements: const RuntimeRequirements(capabilities: {
RuntimeCapability.backgroundExecution,
RuntimeCapability.network,
RuntimeCapability.notifications,
}),
start: (ctx) async {
channel = WebSocketChannel.connect(url); // your library
await channel.ready; // throw → retried with backoff
channel.stream.listen(
(m) => ctx.emit('ride.offer', payload: {'raw': '$m'}, persist: true),
onError: ctx.reportFailure, // → recover()
onDone: () => ctx.reportFailure('closed'),
);
},
stop: (ctx) async => channel.sink.close(),
));
await NativeFlow.start(const RuntimeOptions(
notification: ForegroundNotification(title: 'You are online'),
));
NativeFlow.events.named('ride.offer').listen((e) => showOffer(e.payload));
Documentation #
| Getting started | Install, setup, first adapter |
| Adapters | Wrapping WebSocket / Socket.IO / MQTT / BLE / location |
| Runtime lifecycle | States, sessions, engine ownership |
| Recovery | Backoff, process death, reboot |
| Events | Event bus, persistence, acknowledgement |
| Notifications · Overlays · Presentation & Live Activities | UI outside your app |
| Background tasks · Permissions · Capabilities | Platform features |
| Logging · Testing · Troubleshooting · Migration | Operating it |
| Architecture · Decisions · Roadmap | Design |
Example #
example/ is a complete driver app with one screen per API area.
It covers every public method, plus WebSocket, Socket.IO, MQTT and location
adapters that keep their own libraries, and a Live Activity widget extension.
Platform limits, stated plainly #
- Android: foreground services must be started while the app is visible
(Android 12+); typed services need their permission (Android 14+);
dataSyncis limited to 6 h per day and some types cannot start at boot (Android 15+). OEM battery managers may still kill the service. NativeFlow reportsinterruptedand restores at the next legitimate opportunity. - iOS: there are no persistent services. Without a declared continuous background mode (location, audio, VoIP), adapters are paused before suspension. BGTaskScheduler timing is decided by the OS.
- Events are delivered at least once. De-duplicate by
event.id.
Security #
A closed native command set with no reflective dispatch. Ids and payloads are validated (JSON only, 32 KB maximum). Payloads, notification content and credentials are never logged. No background activity launches. No dangerous permission is declared or requested on your behalf. The privacy manifest is included.