I am trying to update the live activities with push notifications and I use the two methods one to start the live activity and the other to update the live activity which are as follows:
func startActivity(completion: @escaping (String) -> Void) {
print("startActivity() is running")
let attributes = PizzaDeliveryAttributes(numberOfPizzas: 2, totalAmount: "420", orderNumber: "359")
let future = Calendar.current.date(byAdding: .minute, value: 35, to: Date())!.addingTimeInterval(40)
let date = Date.now...future
let initialContentState = PizzaDeliveryAttributes.ContentState(driverName: "Bill James", deliveryTimer:date)
let activityContent = ActivityContent(state: initialContentState, staleDate: Calendar.current.date(byAdding: .minute, value: 30, to: Date())!)
do {
self.deliveryActivity = try Activity.request(attributes: attributes, content: activityContent, pushType: .token)
print("Requested a pizza delivery Live Activity \(String(describing: self.deliveryActivity?.id)).")
Task {
for await data in self.deliveryActivity!.pushTokenUpdates {
let myToken = data.map {String(format: "%02x", $0)}.joined()
print("Token printed: \(myToken)")
completion(myToken)
}
}
} catch (let error) {
print("Error requesting pizza delivery Live Activity \(error.localizedDescription).")
}
}
func updatePizzaDeliveryStatus(minutes: String, seconds: String) async {
var future = Calendar.current.date(byAdding: .minute, value: (Int(minutes) ?? 0), to: Date())!
future = Calendar.current.date(byAdding: .second, value: (Int(seconds) ?? 0), to: future)!
let date = Date.now...future
let updatedDeliveryStatus = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Anne Johnson", deliveryTimer: date)
let alertConfiguration = AlertConfiguration(title: "Delivery update", body: "Your pizza order will arrive in 25 minutes.", sound: .default)
let updatedContent = ActivityContent(state: updatedDeliveryStatus, staleDate: nil)
do {
try await self.deliveryActivity?.update(updatedContent, alertConfiguration: alertConfiguration)
} catch {
print("Failed to update Live Activity: \(error)")
}
}
I am able to generate pushTokens on every new live activity started and also send the curl command through to update the live activity which I will provide below. I expect the dynamic content of the attributes to update, but nothing happens when the push goes through.
curl -v \
--header "apns-topic:<Bundle-Id>.push-type.liveactivity" \
--header "apns-push-type:liveactivity" \
--header "authorization: bearer $AUTHENTICATION_TOKEN" \
--data \
'{"aps": {
"timestamp":1663300480,
"event": "update",
"content-state": {
"driverName": "Tony Stark",
"deliveryTimer": {
"start": 1663300480,
"end": 1663301480
}
},
"alert": {
"title": "Race Update",
"body": "Tony Stark is now leading the race!"
}
}}' \
--http2 \
https://${APNS_HOST_NAME}/3/device/$DEVICE_TOKEN
And this is what content state in the attributes look like:
public struct ContentState: Codable, Hashable {
var driverName: String
var deliveryTimer: ClosedRange<Date>
}
Any help or insight is deeply appreciated.
When you run your curl, if you're getting a status code 200
response, then the push notifications are making it to the device.
Assuming you're getting a 200, I can see it being two things.
ContentState
serializabilityYour timestamp needs to be updated each time you send a push (can't send 2 pushes with the same timestamp). And the time has to be current. You can get that here.
iOS is using codable to deserialize the push notification content-state
into the struct ContentState
. For this to work, the keys must match exactly for both. (I know this ContentState is from their example, but they use a simpler one for the push example)
ClosedRange is codable, but I don't know what the keys are (possibly not start
and end
).
Try putting only primitive types in your ContentState and see if that fixes it. If so, you can investigate the codability of ClosedRange. Let me know how that goes!
"content-state": {
"driverName": "Tony Stark",
"deliveryStartInt": 1663300480,
"deliveryEndInt": 1663301480,
}
},
public struct ContentState: Codable, Hashable {
var driverName: String
var deliveryStartInt: Int
var deliveryEndInt: Int
}