flutter_live_activities 0.0.3 flutter_live_activities: ^0.0.3 copied to clipboard
Flutter plugin for Live Activities, Use it to create [DynamicIsland UI] and [Lock screen/banner UI],then update them and handle the click action
Flutter Live Activities #
This plugin requires notification permission
1. Add a Widget to the iOS project
- Directory structure
2. Edit Runner/Info.plist
and live_activity_test/Info.plist
both add:
<plist version="1.0">
<dict>
...
<key>NSSupportsLiveActivities</key>
<true/>
...
</dict>
</plist>
3. Create a data channel in widget swift file
live_activity_test/live_activity_testLiveActivity.swift
import ActivityKit
import SwiftUI
import WidgetKit
// Custom data model
struct TestData {
var text: String
init?(JSONData data: [String: String]) {
self.text = data["text"] ?? ""
}
init(text: String) {
self.text = text
}
}
// Data channel <- Must!
struct FlutterLiveActivities: ActivityAttributes, Identifiable {
public typealias LiveData = ContentState
public struct ContentState: Codable, Hashable {
var data: [String: String]
}
var id = UUID()
}
@available(iOSApplicationExtension 16.1, *)
struct live_activity_testLiveActivity: Widget {
var body: some WidgetConfiguration {
// Binding
ActivityConfiguration(for: FlutterLiveActivities.self) { context in
// Lock screen/banner UI goes here
// Json to model
let data = TestData(JSONData: context.state.data)
// UI
VStack {
Text(data?.text ?? "")
}
.activityBackgroundTint(Color.cyan)
.activitySystemActionForegroundColor(Color.black)
} dynamicIsland: { context in
// Json to model
let data = TestData(JSONData: context.state.data)
// DynamicIsland
return DynamicIsland {
// Expanded UI goes here. Compose the expanded UI through
// various regions, like leading/trailing/center/bottom
DynamicIslandExpandedRegion(.leading) {
Text("Leading")
}
DynamicIslandExpandedRegion(.trailing) {
Text("Trailing")
}
DynamicIslandExpandedRegion(.bottom) {
// Show data from flutter
Text(data?.text ?? "")
}
} compactLeading: {
Text("L")
} compactTrailing: {
Text("T")
} minimal: {
Text("Min")
}
.keylineTint(Color.red)
}
}
}
For more layout information, please refer to: live activities
4. APIs
import 'package:flutter_live_activities/flutter_live_activities.dart';
...
final FlutterLiveActivities _liveActivitiesPlugin = FlutterLiveActivities();
String? _latestActivityId;
- Check if the liveActivities function is enabled
await _liveActivitiesPlugin.areActivitiesEnabled();
- Get launch url
await _liveActivitiesPlugin.getInitUri()
- Create a live activity
_latestActivityId = await _liveActivitiesPlugin.createActivity(<String, String>{'text': 'Hello World'});
- Update a live activity
if(_latestActivityId != null) {
await _liveActivitiesPlugin.updateActivity(_latestActivityId!, <String, String>{'text': 'Update Hello World'});
}
- End a live activity
if(_latestActivityId != null) {
await _liveActivitiesPlugin.endActivity(_latestActivityId!);
}
- End all live activities
await _liveActivitiesPlugin.endAllActivities();
- Get all live activities id
await _liveActivitiesPlugin.getAllActivities()
5. Deeplink
-
The default urlScheme is
FLA
-
Edit urlScheme in your project
- Swift code:
@available(iOSApplicationExtension 16.1, *)
struct live_activity_testLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: FlutterLiveActivities.self) { context in
...
} dynamicIsland: { context in
let data = TestData(JSONData: context.state.data)
return DynamicIsland {
...
DynamicIslandExpandedRegion(.bottom) {
// Create an action via `Link`
Link(destination: URL(string: "FLA://xxxxxxx.xxxxxx")!) {
Text(data?.text ?? "")
.background(.red)
}
}
} compactLeading: {
Text("L")
} compactTrailing: {
Text("T")
} minimal: {
Text("Min")
}
.widgetURL(URL(string: "FLA://www.apple.com")) // or use widgetURL
.keylineTint(Color.red)
}
}
}
- Dart code:
_subscription ??= _liveActivitiesPlugin.uriStream(urlScheme: 'FLA').listen((String? uri) {
dev.log('deeplink uri: $uri');
});