Skip to content

Add iOS 17.2+ push-to-start for Live Activity renewal#622

Open
bjorkert wants to merge 3 commits intodevfrom
feat/la-ios17-push-to-start
Open

Add iOS 17.2+ push-to-start for Live Activity renewal#622
bjorkert wants to merge 3 commits intodevfrom
feat/la-ios17-push-to-start

Conversation

@bjorkert
Copy link
Copy Markdown
Member

@bjorkert bjorkert commented Apr 27, 2026

Summary

On iOS 17.2 and later, the Live Activity now renews itself silently in the background instead of asking you to open the app every 7–8 hours. iOS 16 keeps the existing behavior unchanged.

How it works

Apple ends every Live Activity after about 8 hours. Until now, when that limit got close, LoopFollow had to wait for you to bring the app to the foreground so it could request a fresh one — and if you didn't, you'd get a notification asking you to.

iOS 17.2 added a way to start a Live Activity from a server-side push instead of from the foreground app. LoopFollow now uses that:

  • When it's time to renew, the app sends an APNs push to itself. iOS creates a new Live Activity from the push, and the old one is replaced silently.
  • The same push-to-start path is used when you toggle the Live Activity on or hit Restart, so there's only one creation flow on iOS 17.2+.
  • Updates still ride APNs the same way they did before.

Because everything goes through APNs, valid APNs credentials become a hard requirement for Live Activities, to make that obvious before something silently breaks, the Settings UI now validates them.

Settings UX

  • APN page: shows a green check or orange warning next to the Key ID and APNs key as you type, with a one-line hint if either looks wrong.
  • Live Activity page: the section footer points to the APN settings, and a warning row appears above the Restart button if the credentials are missing or invalid.

iOS 16 behavior

Unchanged. Same Activity.request() flow, same renewal-failed notification when the app is backgrounded at the deadline. The iOS 17 paths are gated by #available so the legacy code can be removed in one go when the deployment target eventually moves to 17.2.

iOS 17.2+ now uses APNs push-to-start for every Live Activity creation
path — initial start, renewal, and forced restart — so the LA can renew
silently in the background instead of requiring the user to foreground
the app at the 7.5 h ceiling. iOS 16.x retains the existing
Activity.request() flow with the renewal-failed notification; the
#available gates are at the entry points so the legacy helpers can be
removed in one commit when the deployment target reaches 17.2.

Push-to-start uses a silent payload (alert with empty title/body +
interruption-level: passive) so adoption is invisible on phone and
watch. The push-to-start token is observed at startup and persisted
between launches; activityUpdates adoption resets the renewal deadline.
The "tap to update" overlay is suppressed on iOS 17.2+ unless renewal
has actually failed, since the time-based pre-emptive warning would be
misleading when push-to-start is handling renewal automatically.

Settings:
- APN page: inline validity badges for Key ID and APNs key, with one-
  line error text when either is malformed.
- Live Activity page: section footer noting APNs is required, plus a
  warning row when credentials are missing or invalid.
bjorkert added a commit that referenced this pull request Apr 27, 2026
# Conflicts:
#	LoopFollow/LiveActivity/LiveActivityManager.swift
#	LoopFollow/Settings/LiveActivitySettingsView.swift
Deployment target is 16.6, so #available(iOS 16.2, *) is always true at
runtime and the @available(iOS 16.2, *) on Activity.activityUpdates is
satisfied by the deployment target alone. The runtime branch and its
'(iOS 16.2+)' log strings just made the file harder to read alongside
the real iOS 17.2 push-to-start gating.
UIDevice.current.systemVersion reports the iOS-equivalent on Mac
Catalyst, so use ProcessInfo.operatingSystemVersion (and label it
macOS) when running as a Catalyst app.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant