Updating LiveActivities with Push notifications (使用推送通知更新实时活动)

huangapple go评论67阅读模式
英文:

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,可能有两个问题:

  1. 与过期时间戳相关的问题。
  2. 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.

  1. Issue with stale timestamps
  2. 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!

huangapple
  • 本文由 发表于 2023年5月15日 14:53:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76251528.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定