So basically when running the my application on my physical device (iPhone 15 Pro Max) or on iPhone 16 pro on the simulator, when I start a Live Activity it is kind of in the dynamic island. When clicked it opens my app and expands when held but without any content.
empty dynamic island
My app contains 3 targets, the iOS App, Widget Extensions and a Shared framework to distribute models, utility functions and components.
Following Things are true:
- App has Notification permission
- App has required Live Activities permissions
- App has push notification sign in & capabilities
- App has no errors
I have tried the following:
- Making content more static
- logging Activity presence
What I expect:
- Visible UI for both Dynamic Island and Lock Screen
here is my code:
Main iOS Application
import ActivityKit
import SwiftUI
import SharedDripe
class LiveActivityManager {
static let shared = LiveActivityManager()
private var tripActivity: Activity<TripSummaryAttributes>?
func startTripActivity(trip: Trip, unitSystem: User.UnitSystem) async {
guard ActivityAuthorizationInfo().areActivitiesEnabled else {
print("❌ Live Activities not supported on this device")
return
}
do {
let initialState = TripSummaryAttributes.ContentState(
trip: trip,
unitSystem: unitSystem
)
let content = ActivityContent(
state: initialState,
staleDate: Calendar.current.date(byAdding: .hour, value: 8, to: Date())
)
let activity = try Activity<TripSummaryAttributes>.request(
attributes: TripSummaryAttributes(),
content: content,
pushType: nil
)
tripActivity = activity
print("✅ Live Activity started successfully")
print("Activity ID: (activity.id)")
print("Activity state: (activity.activityState)")
} catch {
print("❌ Error starting Live Activity: (error)")
print("Error details: (error.localizedDescription)")
}
}
func endTripActivity() async {
await endAllActivities()
tripActivity = nil
}
func endAllActivities() async {
print("Ending all live activities...")
for activity in Activity<TripSummaryAttributes>.activities {
await activity.end(nil, dismissalPolicy: .immediate)
print("Ended activity with ID: (activity.id)")
}
}
}
How I call the Live Activity (toggled by a button)
await LiveActivityManager.shared.startTripActivity(trip: currentTrip, unitSystem: unitSystem)
Widget Extension
//
// DripeAcitiviesWidget.swift
// Dripe
//
// Created by Noah Onyejese on 14.12.24.
//
import ActivityKit
import SwiftUI
import WidgetKit
import SharedDripe
struct LiveActiveTripView: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: TripSummaryAttributes.self) { context in
// Lock screen view
ZStack {
Color.blue // Background
Text("ACTIVE TRIP TEST")
.foregroundColor(.white)
.padding()
}
} dynamicIsland: { context in
DynamicIsland {
// Expanded
DynamicIslandExpandedRegion(.center) {
Text("TEST EXPANDED")
.foregroundColor(.white)
}
} compactLeading: {
// Leading compact
Text("🚗")
.foregroundColor(.white)
} compactTrailing: {
// Trailing compact
Text("TEST")
.foregroundColor(.white)
} minimal: {
// Minimal
Text("🚗")
.foregroundColor(.white)
}
}
}
}
@main
struct DripeWidgetBundle: WidgetBundle {
var body: some Widget {
LiveActiveTripView()
}
}
Shared Framework
public struct TripSummaryAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
public var trip: Trip
public var unitSystem: User.UnitSystem
public init(trip: Trip, unitSystem: User.UnitSystem) {
self.trip = trip
self.unitSystem = unitSystem
}
}
public init() {}
}
Thanks in advance!
Noah Onyejese is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.