My start live activity CURL is not starting my live activity and I keep getting a decoding failure even though my curl matches my content state so my live activity is not starting. heres my CURL
--header "apns-topic: MuscleMemory.KimchiLabs.com.push-type.liveactivity" \
--header "apns-push-type: liveactivity" \
--header "apns-priority: 10" \
--header "authorization: bearer eyJhbGciOiJFUzI1NiIsImtpZCI6IjI4MjVTNjNEV0IifQ.eyJpc3MiOiJMOTZYUlBCSzQ2IiwiaWF0IjoxNzU3NDYwMzQ2fQ.5TGvDRk5ZYLsvncjKwXIZYN78X88v5lCwX4fRvfl1QXjwv8tOtO2uoId27LQahXA3zqjruu_2YoOfqEtrppKXQ" \
--data '{
"aps": {
"timestamp": '"$(date +%s)"',
"event": "start",
"content-state": {
"plain_text": "hello world",
"userContentPage": ["hello world"]
},
"alert": { "sound": "chime.aiff" }
},
"attributes-type": "KimchiKit.DynamicRepAttributes",
"attributes": {}
}' \
--http2 https://api.sandbox.push.apple.com/3/device/802fe7b4066e26b51ede7188a7077a9603507a0fa6ee8ffda946a864e75aa139602861538d6fb12100afbe9a3338d6c7c799d947dfacb2ee835f0339ecdc3165c9ed7e54839f5a3b89b76a011f5826cc
and here is my content state
public struct ContentState: Codable, Hashable {
public var plainText: String
public var userContentPage: [String]
public enum CodingKeys: String, CodingKey {
case plainText = "plain_text"
case userContentPage
}
public init(plainText: String, userContentPage: [String]) {
self.plainText = plainText
self.userContentPage = userContentPage
}
}
public init() {}
}
ActivityKit
RSS for tagHelp people keep track of tasks and events that they care about with Live Activities on the Lock Screen, the Dynamic Island, and in StandBy.
Posts under ActivityKit tag
107 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
On earlier iOS versions Live Activity displays correctly according to mode set.
Can't find an opened issue for that
version: iOS 26
device: iPhone 16
While the activityBackgroundTint modifier is intended to set the background color of a Live Activity, it often fails to dynamically update, leaving the activity with an incorrect background. Replacing it with
ZStack {
Color(.background)
....
}
solves the problem, but this is a workaround. The activityBackgroundTint modifier is still needed, at a minimum, so that the "Allow Live Activity for the app" extension does not have the default color.
Live Activity: no value in pushTokenUpdates and pushToStartTokenUpdates not called after app restart
When running application after installation I get a value in pushTokenUpdates and also the call to pushToStartTokenUpdates returns with the token value.
But, if I kill the app and restart it again, there is no value in pushTokenUpdates and the call to pushToStartTokenUpdates does not return.
Am I suppose to use the push to start token from the previous application run?
is there a different solution?
After opening 5 live activities using live activity push-to-start push notifications, I clear them from lock screen.
From this point forward I am unable to open new live activities.
Device log shows:
Could not create a new activity from push notification: ActivityKit.ActivityAuthorizationError.targetMaximumExceeded
How can I handle such use case?
shouldn't the count of opened live activities be reduced once the user clears the live activities? is this a bug?
When sending multiple push to start notifications to start a live activities in a short time frame, after around 10 pushes live activities are no longer being started.
Device logs show the following entry:
Push-to-start budget exceeded for com.att.tlv.myatt::pushToStart; not starting activity
What can be done to be able to open more live activities via push-to-start in a short time frame (increase the push-to-start budget)?
Can this be related to the development environment and it will not happen on production?
NSSupportsLiveActivitiesFrequentUpdates is already set to YES
Does the alert only serve the following purposes:
required for start events
require for any event that needs to alert the user (with sound or having the live activity show in expanded presentation)
while its content DO NOT matter. Only the presence of the field and its attributes matter.
The only time its content matter are when the receiving device is an Apple Watch.
Is that correct?
Hi, I'm having this issue that I have have not been able to figure out as I've gone through a checklist and it seems I have everything in place, but im sending my pushToStartTokenUpdates token to a server and im able to test starting a live activity via CURL where it shows my push token going through and even my test payload but after a while I get this issue in my logs where it fails to find a live activity
Push notifications are set up, im sending my token to APN and im even able to start live activities locally.
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
User Notifications
ActivityKit
The docs are conflicting.
https://developer.apple.com/documentation/activitykit/starting-and-updating-live-activities-with-activitykit-push-notifications#End-the-Live-Activity-with-a-custom-dismissal-date says:
When you end a Live Activity, by default the Live Activity appears on the Lock Screen for up to four hours after it ends to allow people to glance at their phone to refer to the latest information.
However here it says:
https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities#Understand-constraints
A Live Activity can be active for up to eight hours unless its app or a person ends it before this limit. After the eight-hour limit, the system automatically ends the Live Activity, and immediately removes it from the Dynamic Island. However, the Live Activity remains on the Lock Screen until a person removes it or for up to four additional hours before the system removes it — whichever comes first. As a result, a Live Activity remains on the Lock Screen for a maximum of 12 hours.
So is it 4 hrs OR '8 for Dynamic Island vs 12 for Lock Screen'?
I'm developing an app which will show the driver ETA and rendering the progress bar of the current ETA.
Intuitively the backend server sends the push notification every 3 seconds through firebase cloud message service to APNS so that the device can refresh the dynamic island smoothly.
But the live activity doesn't refresh as frequently as the backend service does.
It should refresh every 3 seconds but it turns out like refresh 30 ~ 60 seconds, sometimes it didn't refresh at all.
any body facing the same?
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
APNS
User Notifications
ActivityKit
Hey there, i start a live activity with notification , and but sometime it can not update, it happens sometime and make me so confuse;
like about 2025-08-19 +8.0 09:20:52
updatetoken : 40ead3fd4dd4a934548c5455c645fc6920edfaa0ddad98abd619dc1d2662389c15d3dc3b420bdec733d9438d25ae61cb55601ae64292b3064a71ffb8d0355633f3f0f2254e6f7438282ce83366d8430c
app can not accept push update msg, and APNs has show success when server send update msg to APP;
how can i check the APNS to APP?
Thanks
Hi everyone,
I’m working on implementing Live Activities in my app, and I’ve encountered an issue where the Live Activity updates work intermittently when the app is in the background. Sometimes they update correctly, but at other times, they don’t update at all, even though they should be running in the background.
However, when the app is brought to the foreground, the updates happen correctly.
A few things I’ve checked:
The app is using ActivityKit to update the Live Activity with Activity.update().
I’ve enabled the necessary background modes in the Capabilities section.
Is there a possibility that I’m hitting the system budget limit while experiencing this issue? If this is a limitation, how can I avoid it or manage this situation?
Has anyone else faced this issue? Any advice or potential solutions would be greatly appreciated!
Thank you!
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
Swift
SwiftUI
WidgetKit
ActivityKit
I'm developing an app which will show the driver ETA and rendering the progress bar of the current ETA.
Intuitively the backend server sends the push notification every 3 seconds through firebase cloud message service to APNS so that the device can refresh the dynamic island smoothly.
But the live activity doesn't refresh as frequently as the backend service does.
It should refresh every 3 seconds but it turns out like refresh 30 ~ 60 seconds, sometimes it didn't refresh at all.
any body facing the same?
When I use the Activity.request method to start the Dynamic Island widget, there have been continuous crash reports online, Could you please provide some ideas on how to fix this crash? Thanks!
Crash backtraces:
0ActivityKitblock_copy_helper.101 (in ActivityKit)+21416
1CombinePublishers.FlatMap.Outer.receive(B.Output) (in Combine)+296
2Combineprotocol witness for Subscriber.receive(A.Input) in conformance Publishers.FlatMap<A, B>.Outer<A1> (in Combine)+20
3CombinePublishers.HandleEvents.Inner.receive(A.Output) (in Combine)+204
4Combineprotocol witness for Subscriber.receive(A.Input) in conformance Publishers.HandleEvents<A>.Inner<A1> (in Combine)+20
5CombineFilterProducer.receive(B) (in Combine)+2508
6Combineprotocol witness for Subscriber.receive(A.Input) in conformance FilterProducer<A, B, C, D, E> (in Combine)+20
7Combinepartial apply for closure #4 (C) in Publishers._Merged.request(Subscribers.Demand) (in Combine)+52
8CombinePublishers._Merged.guardedApplyDownstream<A>((C)) (in Combine)+180
9CombinePublishers._Merged.receive(A, Int) (in Combine)+400
10CombinePublishers._Merged.Side.receive(A) (in Combine)+20
11CombineJust.Inner.request(Subscribers.Demand) (in Combine)+692
12Combineprotocol witness for Subscription.request(Subscribers.Demand) in conformance Just<A>.Inner<A1> (in Combine)+20
13CombinePublishers._Merged.receive(subscription: Subscription, _: Int) (in Combine)+496
14CombinePublishers._Merged.Side.receive(subscription: Subscription) (in Combine)+20
15CombineJust.receive<A>(subscriber: A1) (in Combine)+420
16CombinePublishers.Merge.receive<A>(subscriber: A1) (in Combine)+380
17CombinePublisherBox.receive<A>(subscriber: A1) (in Combine)+104
18CombineAnyPublisher.receive<A>(subscriber: A1) (in Combine)+60
19CombinePublishers.RemoveDuplicates.receive<A>(subscriber: A1) (in Combine)+220
20CombinePublishers.HandleEvents.receive<A>(subscriber: A1) (in Combine)+300
21CombinePublisherBox.receive<A>(subscriber: A1) (in Combine)+104
22CombineAnyPublisher.receive<A>(subscriber: A1) (in Combine)+60
23CombinePublishers.FlatMap.receive<A>(subscriber: A1) (in Combine)+416
24CombinePublishers.RemoveDuplicates.receive<A>(subscriber: A1) (in Combine)+220
25CombinePublisherBox.receive<A>(subscriber: A1) (in Combine)+104
26CombineAnyPublisher.receive<A>(subscriber: A1) (in Combine)+60
27CombinePublishers.CompactMap.receive<A>(subscriber: A1) (in Combine)+440
28CombinePublisherBox.receive<A>(subscriber: A1) (in Combine)+104
29CombineAnyPublisher.receive<A>(subscriber: A1) (in Combine)+60
30CombinePublishers.SetFailureType.receive<A>(subscriber: A1) (in Combine)+420
31CombinePublishers.FlatMap.receive<A>(subscriber: A1) (in Combine)+416
32CombinePublishers.RemoveDuplicates.receive<A>(subscriber: A1) (in Combine)+220
33CombinePublisherBox.receive<A>(subscriber: A1) (in Combine)+104
34CombineAnyPublisher.receive<A>(subscriber: A1) (in Combine)+60
35CombinePublishers.CompactMap.receive<A>(subscriber: A1) (in Combine)+440
36CombinePublisherBox.receive<A>(subscriber: A1) (in Combine)+104
37CombineAnyPublisher.receive<A>(subscriber: A1) (in Combine)+60
38CombinePublishers.ReceiveOn.receive<A>(subscriber: A1) (in Combine)+660
39CombinePublisher.sink(receiveCompletion: (Subscribers.Completion<A.Failure>), receiveValue: (A.Output)) (in Combine)+316
40ActivityKitblock_copy_helper.101 (in ActivityKit)+33364
41ActivityKitblock_copy_helper.101 (in ActivityKit)+26716
42ActivityKitblock_copy_helper.101 (in ActivityKit)+53192
43ActivityKitblock_copy_helper.101 (in ActivityKit)+52408
44ActivityKitblock_destroy_helper.25 (in ActivityKit)+1140
45ActivityKitblock_destroy_helper.62 (in ActivityKit)+8220
46ActivityKitblock_destroy_helper.62 (in ActivityKit)+9364
47libswiftDispatch.dylibpartial apply for thunk for @callee_guaranteed () -> (@out A, @error @owned Error) (in libswiftDispatch.dylib)+24
48libswiftDispatch.dylibthunk for @callee_guaranteed () -> (@out A, @error @owned Error)partial apply (in libswiftDispatch.dylib)+12
49libswiftDispatch.dylibclosure #1 () in closure #1 (()) in OS_dispatch_queue._syncHelper<A>(fn: (()), execute: (), rescue: (Error)) (in libswiftDispatch.dylib)+188
50libswiftDispatch.dylibpartial apply for thunk for @callee_guaranteed () -> () (in libswiftDispatch.dylib)+24
51libswiftDispatch.dylibthunk for @escaping @callee_guaranteed () -> () (in libswiftDispatch.dylib)+24
52libdispatch.dylib__dispatch_client_callout (in libdispatch.dylib)+16
53libdispatch.dylib__dispatch_lane_barrier_sync_invoke_and_complete (in libdispatch.dylib)+52
54libswiftDispatch.dylibimplicit closure #2 (()) in implicit closure #1 (OS_dispatch_queue) in OS_dispatch_queue.asyncAndWait<A>(execute: ()) (in libswiftDispatch.dylib)+188
55libswiftDispatch.dylibpartial apply for implicit closure #2 (()) in implicit closure #1 (OS_dispatch_queue) in OS_dispatch_queue.sync<A>(execute: ()) (in libswiftDispatch.dylib)+72
56libswiftDispatch.dylibOS_dispatch_queue._syncHelper<A>(fn: (()), execute: (), rescue: (Error)) (in libswiftDispatch.dylib)+400
57libswiftDispatch.dylibOS_dispatch_queue.asyncAndWait<A>(execute: ()) (in libswiftDispatch.dylib)+136
58libswiftDispatch.dylibOS_dispatch_queue.sync<A>(execute: ()) (in libswiftDispatch.dylib)+60
59ActivityKitblock_destroy_helper.62 (in ActivityKit)+3272
60ActivityKitblock_destroy_helper.62 (in ActivityKit)+724
61ActivityKit___swift_store_extra_inhabitant_indexTm (in ActivityKit)+24928
62ActivityKit___swift_store_extra_inhabitant_indexTm (in ActivityKit)+23900
63 XXXApp static LiveActivityService.request()
......
When using the ManagedSettings API to block apps everything is blocked as expected (the app itself, Notifications, Live Activities on the Lock Screen etc) except for Compact Live Activities of those apps (that are shown in the Dynamic Island). I feel the expected behavior would be to block also the Compact Live Activities.
Our use case:
In Spoilerblock we want to prevent users from being exposed to spoilers before they've had time to watch for example a sports game.
Current workaround:
Right now the best we can do is to ask the user to disable Live Activities for apps that could expose results, to not risk being exposed to a spoiler.
Hi Apple team,
I'm experiencing a persistent issue with writing to UserDefaults from a widget extension on iOS. Here's the situation:
I've set up an App Group: group.test.blah
The main app has the correct entitlement and can read/write from UserDefaults(suiteName:) using this group successfully.
I can read the value written by the app from the widget (e.g., "testFromApp": "hiFromApp").
The widget extension has the same App Group enabled under Signing & Capabilities.
The provisioning profile reflects the App Group and the build installs successfully on a real device.
The suite name is correct and matches across both targets.
I’ve confirmed via FileManager.default.containerURL(...) that the app group container resolves properly.
When I try to write from the widget extension like this
let sharedDefaults = UserDefaults(suiteName: "group.test.blah")
sharedDefaults?.set("hiFromWidget", forKey: "testFromWidget")
...I get this error in the console:
Couldn't write values for keys (
testFromWidget
) in CFPrefsPlistSource<0x1140d2880> (Domain: group.test.blah, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): setting preferences outside an application's container requires user-preference-write or file-write-data sandbox access
Questions:
What could still cause the widget extension to lack write access to the app group container, even though it reads just fine?
Are there any internal sandboxing nuances or timing-related issues specific to Live Activity widgets that could explain this?
Is this a known limitation or platform issue?
Topic:
App & System Services
SubTopic:
Widgets & Live Activities
Tags:
Extensions
Entitlements
ActivityKit
Files and Storage
Background
I'm developing an iOS app with Live Activities that allows users to select custom background images. While these custom images display correctly in widgets, they fail to appear in Live Activities on both Lock Screen and Dynamic Island, despite successful image loading and data transfer.
Technical Details
iOS Version: Testing on iOS 17.2+
Image Storage: Using App Group shared container for image sharing between main app and widget extension
Image Loading: Successfully confirmed via logs - images load correctly with proper dimensions
UI Framework: SwiftUI with ActivityKit
What Works
✅ Custom images display correctly in Home Screen widgets
✅ Built-in bundled images work in Live Activities
✅ Image data successfully transfers via App Group shared container
✅ Image loading logs show successful UIImage creation with correct dimensions
What Doesn't Work
❌ Custom user images don't display in Live Activities (Lock Screen)
❌ Custom user images don't display in Dynamic Island
❌ Images appear as black/gray background despite successful loading
Code Implementation
I've tried multiple approaches:
1. SwiftUI Image approach:
Image(uiImage: customImage)
.resizable()
.aspectRatio(contentMode: .fill)
2. containerBackground API approach:
.containerBackground(for: .widget) {
Image(uiImage: customImage)
.resizable()
.aspectRatio(contentMode: .fill)
}
3. UIKit wrapper approach:
struct UIImageViewWrapper: UIViewRepresentable {
let image: UIImage
func makeUIView(context: Context) -> UIImageView {
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
return imageView
}
func updateUIView(_ uiView: UIImageView, context: Context) {
uiView.image = image
}
}
Observations
Images load successfully (confirmed via console logs)
File paths are correct and accessible
Same image loading code works perfectly in widgets
When testing with UIKit approach, a red prohibition icon appears, suggesting system restrictions
Questions
Is there a technical limitation preventing user-provided images from displaying in Live Activities?
Are there specific security restrictions for Live Activity backgrounds that don't apply to widgets?
Is this behavior intentional based on Apple's design guidelines for Live Activities?
What's the recommended approach for custom backgrounds in Live Activities?
Apple Documentation Reference
I found this guidance in "10 questions with the Live Activities team":
"The Dynamic Island is most immersive when you don't provide background color or imagery — think of it purely as a canvas of foreground view elements."
However, this seems to be design guidance rather than a technical restriction, and it doesn't specifically address Lock Screen Live Activities.
Expected Behavior
Custom user images should display as backgrounds in Live Activities, similar to how they work in widgets.
Current Workaround
I've implemented a color extraction system that generates gradients based on the dominant colors of user images, but users specifically want to see their actual images.
Has anyone successfully implemented custom user images as Live Activity backgrounds, or can Apple clarify the intended behavior and limitations?
Thank you for any insights!
I know for start events, sending the timestamp isn't required. So that's easy.
However when I'm testing Live Activity using the Apple Push Notification Console. A lot of times I just need to copy/paste the payload and resend it again.
But then the timestamp field needs to get updated each time, because if it's from a time in the past, then it won't trigger.
This requires me to have to use an EPOCH converter to find the right time and then copy/paste it.
Is there a better solution to this? I know I can use curl, but that is not in the scope of my question.
Hello forum,
Hope you all are doing great!
We’ve implemented Live Activities in our iOS app to display live soccer scores on the lock screen. The feature generally works as expected when the app is in backgroun or app is invoked when the push is sent. However, we’re observing an issue affecting approximately 20–30% of users where the Live Activity starts successfully but no subsequent score or commentary updates are received.
Upon investigation, it appears the OS is not waking the app when the Live Activity starts. This wake-up is critical for syncing the activity token with backend service we use, which is required for delivering updates.
Key Points:
Starting a Live Activity does not require the app to be invoked since we start with Push token
However, for updates to be delivered, the app must be woken at the start to send the latest pushh token to Backend.
In affected cases, even manually sending a background push does not wake the app—it remains terminated until manually opened by the user.
We’d like to understand is there any other way to deliver start and updates from backend at later point when user mark a team/match favorite.
Core requirement is that user need not to open the app except when marking the team as favorite.
Apps like FotMob, MLB, Chrome browser doing same when team is marked as favorite and subscribed for live activities and I observed they are getting updates properly most of the times
Hello everyone,
I'm implementing the "Push to Start" feature for Live Activities, and I've run into an issue where the activity seems to be processed by the system but never appears on the Lock Screen or in the Dynamic Island.
I suspect there's a silent crash happening in my widget extension immediately after launch, but I'm unable to capture any logs or crash reports in the Xcode debugger.
Here is the flow and all the relevant data:
1. The Process
My app successfully requests a pushToStartToken using Activity<EJourneyLiveActivityAttributes>.pushToStartTokenUpdates
The token is sent to our server.
The server uses this token to send a "start" event APNs push notification.
The device console logs (from liveactivitiesd) show that the push is received and the system is "Publishing event".
Expected Result: The Live Activity UI appears on the device.
Actual Result: Nothing appears. The UI is completely absent.
2. Device Console Logs
Here are the logs from the device console, which indicate a successful receipt of the push:
pushServer default 12:08:22.716353+0200 liveactivitiesd Received push event for com.wavepointer.ejourney.staging::pushToStart
pushServer default 12:08:22.716818+0200 liveactivitiesd Reduced budget for com.wavepointer.ejourney.staging::pushToStart to: 7
pushServer default 12:08:22.723458+0200 liveactivitiesd Publishing event: timestamp: 2025-07-24 08:57:19 +0000; activityIdentifier: 53C3EE9D-623C-4F38-93AE-8BB807429DAA; eventType: start(...)
3. APNs Payload
This is the exact payload being sent from our server:
{
"aps": {
"event": "start",
"timestamp": 1753347375,
"attributes-type": "EJourneyLiveActivityAttributes",
"attributes": {
"journeyId": "test123453"
},
"content-state": {
"distanceInMeters": 1000,
"depTime": 1752745104,
"arrTime": 1752748704,
"depStop": "Arth, Am See",
"arrStop": "Oberarth, Bifang",
"depZone": "571",
"arrZone": "566",
"co2Save": 5.0,
"co2SavePerc": 44,
"companyName": "WP Innovation",
"countryCode": "CH",
"categoryId": 5,
"subcategoryId": 3,
"stationStartAssoc": "Assoc1",
"stationEndAssoc": "Assoc2"
}
}
}
4. ActivityAttributes Struct
To prevent decoding errors, I have made all properties in my ContentState optional and added a custom decoder.
@available(iOS 16.1, *)
struct EJourneyLiveActivityAttributes: ActivityAttributes, Hashable {
public struct ContentState: Codable, Hashable {
var distanceInMeters: Int = 0
var depTime: Int = 1752843769
var arrTime: Int = 1752843769
var depStop: String = ""
var arrStop: String = ""
var depZone: String = ""
var arrZone: String = ""
var co2Save: Double?
var co2SavePerc: Int = 0
var companyName: String = "Test"
var countryCode: String = "CH"
var categoryId: Int = 3
var subcategoryId: Int = 4
var stationStartAssoc: String?
var stationEndAssoc: String?
}
var journeyId: String?
}
What I've Tried
I have carefully checked that my Codable struct matches the JSON payload. I've made all properties optional to avoid crashes from missing keys.
I have tried attaching the Xcode debugger to the widget extension process (Debug -> Attach to Process...) before sending the push, but no logs, errors, or crash reports appear in the Xcode console. The process seems to terminate before it can log anything.
My question is: What could cause the widget extension to fail so early that it doesn't even produce a crash log in the attached debugger? Are there other methods to debug this kind of silent failure?
Any help would be greatly appreciated. Thank you!