flutter_activity_kit 0.5.1
flutter_activity_kit: ^0.5.1 copied to clipboard
Declarative iOS Live Activities (Dynamic Island & Lock Screen) and Android Ongoing Notifications with push token sync, rich state models, and preview widgets.
flutter_activity_kit #
Unified Flutter API for iOS Live Activities (Dynamic Island & Lock Screen) and Android Ongoing Notifications with push token sync, rich state models, and a pure Dart UI DSL.
π What's New in v0.5.1 #
- π¨ Pure Dart UI DSL: Build custom Live Activity widgets in 100% Dart (
LAColumn,LARow,LAText,LAImage,LAProgressBar,LAButton,LASpacer,LAContainer,LATimer) and transpile them to native SwiftUI. - π Smart Folder Scanning (
lib/live_activity_widgets/): Put your Dart widget definitions inlib/live_activity_widgets/and rundart run flutter_activity_kit:generate_swiftto generate all Swift widgets automatically. - π§© Built-in Templates: Pre-configured templates for
navigation(Mini-Map route canvas),delivery,sports(live scoreboard),workout(chronometer & metrics), andgeneric. - πΊοΈ Mini-Map & Route Tracking: Native vector route canvas for Dynamic Island and Lock Screen.
- π Compact Lock Screen Banner: Optimized padding and sizing to eliminate clipping within Apple's 160pt height constraint.
Features #
- iOS 16.1+ Live Activities: Lock Screen banners, Dynamic Island (compact, expanded, minimal).
- Android Ongoing Notifications: High priority status bar chips, progress bars, timers, and interactive action buttons.
- Hardware Timers: 60 FPS real-time countdowns and chronometers rendered natively by the OS.
- Pure Dart UI DSL: Write Live Activity layouts in Dart; transpile to native SwiftUI.
- APNs & FCM Remote Sync: Push-to-update and iOS 17.2+ push-to-start token streams.
- Reactive Controller:
ActivityController<T>with auto-sync and built-in debouncing. - In-App Previews: Flutter preview widgets for Dynamic Island and Android notifications.
Install #
dependencies:
flutter_activity_kit: ^0.5.1
π¨ Building Live Activities in Pure Dart #
You can build Live Activities in 100% pure Dart without writing any Swift!
1. Define your widget in Dart: #
Create lib/live_activity_widgets/flight_live_activity_widget.dart:
import 'package:flutter_activity_kit/flutter_activity_kit.dart';
class FlightLiveActivityWidget extends LiveActivityWidgetDefinition {
const FlightLiveActivityWidget()
: super(
name: 'FlightTracker',
activityType: 'FlightAttributes',
actions: const [
ActivityAction(id: 'boarding_pass', title: 'Boarding Pass'),
],
);
@override
LAWidget buildLockScreen(LAContext context) {
return LAColumn(
spacing: 6,
children: [
LARow(
children: [
const LAImage.system('airplane.departure', color: LAColor.cyan),
LAText(context.title, font: LAFont.headline, bold: true),
const LASpacer(),
LAText(context.status, font: LAFont.caption, bold: true, color: LAColor.cyan),
],
),
LAText(context.message, font: LAFont.subheadline, color: LAColor.gray),
const LAProgressBar(tint: LAColor.cyan),
const LARow(
children: [
LAButton(
title: 'Boarding Pass',
actionId: 'boarding_pass',
systemIcon: 'ticket.fill',
isProminent: true,
tint: LAColor.cyan,
),
],
),
],
);
}
}
2. Transpile to Swift: #
Run the generator in your project root:
dart run flutter_activity_kit:generate_swift
The generator will scan lib/live_activity_widgets/ and generate native, crash-proof SwiftUI code in ios/LiveActivityWidget/.
π¦ Built-In Templates #
If you don't want to design custom layouts, choose from pre-configured templates:
| Template | CLI Command | Features |
|---|---|---|
navigation |
dart run flutter_activity_kit:generate_swift --name Ride --template navigation |
Vector Route Mini-Map, ETA badge, Waypoints, Call/Share actions |
delivery |
dart run flutter_activity_kit:generate_swift --name Order --template delivery |
Step progress bar, Courier status, Call Courier / Cancel |
sports |
dart run flutter_activity_kit:generate_swift --name Match --template sports |
Live Match Scoreboard, Team shields, Match Stats action |
workout |
dart run flutter_activity_kit:generate_swift --name Run --template workout |
Real-time Chronometer, Pace & Distance metrics, Pause/Finish |
generic |
dart run flutter_activity_kit:generate_swift --name Generic --template generic |
Multi-purpose status capsule, progress bar, timer, and buttons |
π Quick Start in Dart #
Start an Activity (1 line): #
import 'package:flutter_activity_kit/flutter_activity_kit.dart';
final session = await FlutterActivityKit.start(
activityType: 'DeliveryAttributes',
title: 'Bella Pizza',
message: 'Chef is baking your pizza',
status: 'Baking π₯',
progress: 0.45,
countdown: const Duration(minutes: 18), // Hardware-rendered 60 FPS countdown!
attributes: const {'orderId': 'ORD-9812'},
actions: const [
ActivityAction(id: 'call_driver', title: 'Call Driver', icon: 'ic_menu_call'),
ActivityAction(id: 'cancel_order', title: 'Cancel', isDestructive: true),
],
);
Update the Activity: #
await session.quickUpdate(
title: 'Out for Delivery',
message: 'Driver Alex is on the way (0.8 miles away)',
status: 'On the Way π΅',
progress: 0.85,
countdown: const Duration(minutes: 5),
);
End the Activity: #
await session.quickEnd(
title: 'Order Delivered',
message: 'Enjoy your meal!',
status: 'Delivered π',
dismissalPolicy: ActivityDismissalPolicy.immediate,
);
ποΈ Handling Action Button Taps #
When the user taps an action button on the iOS Lock Screen banner or Android Notification:
// Wrap your root widget or listen declaratively:
FlutterActivityKit.onAction('call_driver', (event) async {
print('User tapped Call Driver for activity: ${event.activityId}');
final phoneUrl = Uri.parse('tel:+15550199');
if (await canLaunchUrl(phoneUrl)) {
await launchUrl(phoneUrl);
}
});
β‘ Reactive Controller (ActivityController<T>) #
For state-driven apps (workouts, real-time tracking, WebSocket streams):
final workoutController = ActivityController<WorkoutState>(
initialState: WorkoutState(distance: 0.0, pace: '0:00'),
activityType: 'WorkoutAttributes',
stateToContent: (state) => ActivityContent(
state: MapActivityContentState({
'title': 'Outdoor Run',
'message': 'Distance: ${state.distance} km β’ Pace: ${state.pace}',
'progress': state.distance / 10.0,
}),
),
);
// Start
await workoutController.start();
// Update anywhere in your business logic (auto-debounced to prevent OS rate limits):
workoutController.updateState(
WorkoutState(distance: 4.2, pace: '5:10 min/km'),
);
π‘ Remote Push Sync (APNs & FCM) #
Listen for device tokens to push updates directly from your backend server:
FlutterActivityKit.pushTokenEvents.listen((event) {
final activityId = event.activityId;
final apnsToken = event.pushToken;
// Send apnsToken to your backend (Node.js, Go, Firebase)
apiService.registerPushToken(activityId: activityId, token: apnsToken);
});
βοΈ Platform Setup #
iOS #
- In
ios/Runner/Info.plistadd:<key>NSSupportsLiveActivities</key> <true/> <key>NSSupportsLiveActivitiesFrequentUpdates</key> <true/> - In Xcode: File β New β Target β Widget Extension (name it
LiveActivityWidget, check Include Live Activity). - Run
dart run flutter_activity_kit:generate_swiftand add the generated file to your Widget Extension target.
Android #
No native configuration needed. Permissions and ongoing notification channels are handled automatically.
π License #
MIT License. Created by PinzaruLab.