From 2b9965375959c6481a99dd60bc8a91309145a54e Mon Sep 17 00:00:00 2001 From: TJ Aitala Date: Tue, 3 Jun 2025 10:59:31 -0400 Subject: [PATCH] fix(live activities): Register push tokens in more places * Apple has confirmed that when using push-to-start, it is best to check both Activity<...>.pushToken in addition to Activity<...>.pushTokenUpdates --- as well as checking Activity<...>.activities in addition to Activity<...>.activityUpdates --- because your app may need to launch in the background and the launch time may end up being slower than the new values come in. In those cases, your task on the update sequence may start listening after the initial values were already provided. --- .../OneSignalLiveActivitiesManagerImpl.swift | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/OneSignalLiveActivities/Source/OneSignalLiveActivitiesManagerImpl.swift b/iOS_SDK/OneSignalSDK/OneSignalLiveActivities/Source/OneSignalLiveActivitiesManagerImpl.swift index 4d8865cc6..95c381bc1 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalLiveActivities/Source/OneSignalLiveActivitiesManagerImpl.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalLiveActivities/Source/OneSignalLiveActivitiesManagerImpl.swift @@ -190,6 +190,21 @@ public class OneSignalLiveActivitiesManagerImpl: NSObject, OSLiveActivities { @available(iOS 16.1, *) private static func listenForActivity(_ activityType: Attributes.Type, options: LiveActivitySetupOptions? = nil) { + + /* + Apple has confirmed that when using push-to-start, it is best to check both `Activity<...>.activities` in addition + `Activity<...>.activityUpdates` --- because your app may need to launch in the background and the launch time may end + up being slower than the new values come in. In those cases, your task on the update sequence may start listening after + the initial values were already provided. + */ + + // Establish listeners for activity (if any exist) + for activity in Activity.activities { + listenForActivityStateUpdates(activityType, activity: activity, options: options) + listenForActivityPushToUpdate(activityType, activity: activity, options: options) + } + + // Establish listeners for activity updates Task { OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OneSignal.LiveActivities listening for activity on: \(activityType)") for await activity in Activity.activityUpdates { @@ -198,6 +213,7 @@ public class OneSignalLiveActivitiesManagerImpl: NSObject, OSLiveActivities { // listening for the new activity's events. for otherActivity in Activity.activities { if activity.id != otherActivity.id && otherActivity.attributes.onesignal.activityId == activity.attributes.onesignal.activityId { + OneSignalLog.onesignalLog(.LL_DEBUG, message: "OneSignal.LiveActivities dismissing other activity: \(activityType):\(otherActivity.attributes.onesignal.activityId):\(otherActivity.id)") await otherActivity.end(nil, dismissalPolicy: ActivityUIDismissalPolicy.immediate) } } @@ -230,10 +246,26 @@ public class OneSignalLiveActivitiesManagerImpl: NSObject, OSLiveActivities { @available(iOS 16.1, *) private static func listenForActivityPushToUpdate(_ activityType: Attributes.Type, activity: Activity, options: LiveActivitySetupOptions? = nil) { if options == nil || options!.enablePushToUpdate { + + /* + Apple has confirmed that when using push-to-start, it is best to check both `Activity<...>.pushToken` in addition + `Activity<...>.pushTokenUpdates` --- because your app may need to launch in the background and the launch time may end + up being slower than the new values come in. In those cases, your task on the update sequence may start listening after + the initial values were already provided. + */ + + // Set the initial pushToken (if one exists) + if let pushToken = activity.pushToken { + OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OneSignal.LiveActivities enter with existing pushToken for: \(activityType):\(activity.attributes.onesignal.activityId):\(activity.id)") + let token = pushToken.map {String(format: "%02x", $0)}.joined() + OneSignalLiveActivitiesManagerImpl.enter(activity.attributes.onesignal.activityId, withToken: token) + } + // listen for activity update token updates so we can tell OneSignal how to update the activity Task { OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OneSignal.LiveActivities listening for pushToUpdate on: \(activityType):\(activity.attributes.onesignal.activityId):\(activity.id)") for await pushToken in activity.pushTokenUpdates { + OneSignalLog.onesignalLog(.LL_VERBOSE, message: "OneSignal.LiveActivities pushTokenUpdates observed for: \(activityType):\(activity.attributes.onesignal.activityId):\(activity.id)") let token = pushToken.map {String(format: "%02x", $0)}.joined() OneSignalLiveActivitiesManagerImpl.enter(activity.attributes.onesignal.activityId, withToken: token) }