Fix remote Live Activity token lifecycle#4671
Conversation
HA core no longer reads or stores these fields (removed in home-assistant/core#166072 per code review). Sending unused data wastes bandwidth on every app registration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aligns with home-assistant/core#166072 where the webhook handlers were renamed from mobile_app_live_activity_token/dismissed to live_activity_token/dismissed to match the naming convention of all other webhooks in the mobile_app integration (none of which carry the prefix). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follows the rename in LiveActivityRegistry.swift from mobile_app_live_activity_* to live_activity_* to stay consistent with HA core's webhook naming convention. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Now that the supports_live_activities registration fields are gone, ActivityKit types are no longer referenced in this file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
clear_notification with a tag already ends Live Activities via HandlerClearNotification, making end_live_activity redundant. Removes HandlerEndLiveActivity and its registration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drops HandlerEndLiveActivityTests and all end_live_activity routing tests. clear_notification with a tag covers the dismissal path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…re-fcm-prs # Conflicts: # Sources/App/Resources/hu.lproj/Localizable.strings # Sources/App/Resources/ko-KR.lproj/Localizable.strings # Sources/App/Resources/ru.lproj/Localizable.strings # Sources/App/Resources/sv.lproj/Localizable.strings # Sources/App/Settings/DebugView.swift # Sources/App/Settings/LiveActivity/LiveActivitySettingsView.swift # Sources/App/Settings/Settings/SettingsItem.swift
There was a problem hiding this comment.
Pull request overview
This PR updates Live Activity lifecycle handling so remotely started activities are observed and reported to Home Assistant Core using the updated webhook schema.
Changes:
- Adds observation of ActivityKit remote Live Activity starts.
- Changes Live Activity token/dismissal webhook payload keys to Core’s strict schema.
- Updates contract tests for the revised webhook wire format.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
Sources/Shared/LiveActivity/LiveActivityRegistry.swift |
Adds remote activity observation and updates webhook payload construction. |
Sources/App/AppDelegate.swift |
Starts the remote Live Activity observer at app launch. |
Tests/Shared/LiveActivity/LiveActivityContractTests.swift |
Updates frozen webhook key expectations. |
| guard entries[tag] == nil else { continue } | ||
|
|
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4671 +/- ##
=======================================
Coverage ? 43.92%
=======================================
Files ? 280
Lines ? 16997
Branches ? 0
=======================================
Hits ? 7466
Misses ? 9531
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Hey @bgoncal, found a small unrelated bug while testing on the simulator, I didn't know if you'd rather fold this into this PR rather than making a whole nother one for it. Up to you: One-line fix in self.localPushManagers = .init { [weak self] server in
let manager = LocalPushManager(server: server)
manager.delegate = self?.localPushDelegate // ← add this
let token = NotificationCenter.default.addObserver(Verified it clearing the notification on the simulator with the local push websocket on top of all these changes and my incoming |
|
Also found a second related bug. The Custom init(from:) + encode(to:) on ContentState reading the value as Double then Date(timeIntervalSince1970:) Branch: https://github.com/rwarner/iOS/tree/fix/live-activity-codable-and-direct-delegate (the second commit, ea5067b). Same question for if you want to include it in your PR here or have it be seperate |
|
@rwarner Please open a PR for those fixes you mentioned above, I think it makes sense, even though I dislike have custom decoders, if there is no other way, thats fine |
## Summary Follow-up fixes to two issues surfaced while testing #4671 end-to-end. 1. **`HALiveActivityAttributes.ContentState.countdownEnd` decoded via Unix epoch.** ActivityKit decodes the `content-state` JSON arriving via APNs with the default `JSONDecoder`, whose `Date` strategy is `.deferredToDate` (seconds since the 2001 reference date). HA core sends `countdown_end` as Unix epoch seconds, matching the documented `data.when` / `data.when_relative` user contract and the in-app handler that already does `Date(timeIntervalSince1970:)`. Without a manual decode the APNs push path renders countdowns ~31 years in the future. Adds explicit `init(from:)` and `encode(to:)` that map `countdownEnd` via `timeIntervalSince1970`. All other fields use `container.decodeIfPresent` so behavior is unchanged for them. 2. **`NotificationManagerLocalPushInterfaceDirect` assigns `LocalPushManager.delegate`.** The Extension path assigns the delegate at line 197; the Direct path (used on simulator and Mac Catalyst) never did. On those platforms that meant silent commands such as `clear_notification` (no alert title/body) were dropped: iOS doesn't fire `willPresent` for content-less notifications, and the delegate is the only fallback that routes into `commandManager`. One-line fix that brings the Direct factory into line with the Extension's behavior. Real-device verification (iPhone 13 Mini, iOS 26.5, paid Developer account): chronometer countdown rendered correctly 60→0 with the Codable fix in place. Without it the timer rendered as if `Date` were seconds-since-2001. ## Screenshots n/a — both fixes affect decode / message routing behavior, not UI rendering. ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant#1303 ## Any other notes Part of the Live Activities effort tracked in home-assistant/epics#61. Companion server PR: home-assistant/core#166072.
Summary
live_activity_token, matching Core's expected app data key.Root Cause
APNs could start the Live Activity, but the app was not observing
Activity<HALiveActivityAttributes>.activityUpdates. That meant the app did not attach its normal per-activity push-token and lifecycle observers to remotely-started activities, so Core could not receive the per-activity push token needed for subsequent updates.