英文:
Updating LiveActivities with Push notifications
问题
I can help you translate the code-related parts. Here's the translation:
我正在尝试使用推送通知更新实时活动,并使用以下两种方法之一来启动实时活动,另一种来更新实时活动:
func startActivity(completion: @escaping (String) -> Void) {
print("startActivity()正在运行")
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("请求了披萨送货实时活动 \(String(describing: self.deliveryActivity?.id)).")
Task {
for await data in self.deliveryActivity!.pushTokenUpdates {
let myToken = data.map {String(format: "%02x", $0)}.joined()
print("Token打印: \(myToken)")
completion(myToken)
}
}
} catch (let error) {
print("请求披萨送货实时活动时出错 \(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: "送货更新", body: "您的披萨订单将在25分钟内送达。", sound: .default)
let updatedContent = ActivityContent(state: updatedDeliveryStatus, staleDate: nil)
do {
try await self.deliveryActivity?.update(updatedContent, alertConfiguration: alertConfiguration)
} catch {
print("更新实时活动失败: \(error)")
}
}
Please note that I've translated the Swift code, but I haven't translated the curl command since it contains specific placeholders like $AUTHENTICATION_TOKEN
, $APNS_HOST_NAME
, and $DEVICE_TOKEN
that should remain unchanged for your specific setup. If you have any further questions or need additional assistance, feel free to ask.
英文:
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.
答案1
得分: 0
当您运行curl时,如果收到状态码200
的响应,则推送通知已成功发送到设备。
假设您收到了状态码200,可能有两个问题:
- 与过期时间戳相关的问题。
- 与
ContentState
的可序列化性有关。
时间戳
每次发送推送时,您的时间戳都需要更新(不能使用相同的时间戳发送2次推送)。并且时间必须是当前时间。您可以在这里获取当前时间。
ContentState
iOS使用可编码方式将推送通知的“content-state”反序列化为结构“ContentState”。为了使其工作,键必须完全匹配。 (我知道这个ContentState是来自他们的示例,但他们在推送示例中使用了一个更简单的示例)
ClosedRange是可编码的,但我不知道键是什么(可能不是“start”和“end”)。
尝试在ContentState中仅放置基本类型,然后查看是否解决了问题。如果是这样,您可以进一步研究ClosedRange的可编码性。请告诉我进展如何!
"content-state": {
"driverName": "托尼·斯塔克",
"deliveryStartInt": 1663300480,
"deliveryEndInt": 1663301480
}
},
public struct ContentState: Codable, Hashable {
var driverName: String
var deliveryStartInt: Int
var deliveryEndInt: Int
}
英文:
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.
- Issue with stale timestamps
- Issue with
ContentState
serializability
Timestamp
Your 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.
ContentState
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
}
答案2
得分: 0
"Ok so I figured it out.
What I did not realize is the timestamp key in the apns payload, i.e;
"timestamp":1663300480
Needs to be updated every time you send a payload. You can get the latest time stamps from here. Hope this helps!
英文:
Ok so I figured it out.
What I did not realise is the timestamp key in the apns payload, i.e;
"timestamp":1663300480
Needs to be updated every time you send a payload. You can get the latest time stamps from here. Hope this helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论