Skip to content

Adds iOS Live Activities support#4444

Draft
rwarner wants to merge 35 commits intohome-assistant:mainfrom
rwarner:feat/live-activities
Draft

Adds iOS Live Activities support#4444
rwarner wants to merge 35 commits intohome-assistant:mainfrom
rwarner:feat/live-activities

Conversation

@rwarner
Copy link
Copy Markdown

@rwarner rwarner commented Mar 19, 2026

Summary

For architecture decisions, data model details, iOS version strategy, push token flow, and rate limiting — see
technical-brief.pdf

Adds iOS Live Activities support, letting Home Assistant automations push real-time state to the Lock Screen — washing machine countdowns, EV charging progress, delivery tracking, alarm states, or anything time-sensitive that benefits from glanceable visibility without unlocking the phone.

When an automation sends a notification with live_update: true in the data payload, the companion app starts a Live Activity instead of (or in addition to) a standard notification banner. Subsequent pushes with the same tag update it in-place silently. clear_notification + tag ends it.

Field names (tag, title, message, progress, progress_max, chronometer, when, when_relative, notification_icon, notification_icon_color) are intentionally shared with Android's Live Notifications API. Both platforms use the same live_update: true trigger — a single YAML block targets iOS 17.2+ and Android 16+ with no platform-specific keys.

data:
  title: "Washing Machine"
  message: "Cycle in progress"
  data:
    tag: washer_cycle
    live_update: true           # Android 16+ and iOS 17.2+
    progress: 2700
    progress_max: 3600
    chronometer: true
    when: 2700
    when_relative: true
    notification_icon: mdi:washing-machine
    notification_icon_color: "#2196F3"

New files:

  • Sources/Shared/LiveActivity/HALiveActivityAttributes.swift — the ActivityAttributes type. Field names match the Android payload spec. Struct name and CodingKeys are wire-format frozen — APNs push-to-start payloads reference the Swift type name directly.
  • Sources/Shared/LiveActivity/LiveActivityRegistry.swift — Swift actor managing Activity<HALiveActivityAttributes> lifecycle. Uses a reservation pattern to prevent duplicate activities when two pushes with the same tag arrive simultaneously.
  • Sources/Shared/Notifications/NotificationCommands/HandlerLiveActivity.swift — start/update and end NotificationCommandHandler implementations, guarded against the PushProvider extension process where ActivityKit is unavailable.
  • Sources/Extensions/Widgets/LiveActivity/ActivityConfiguration wrapper, Lock Screen / StandBy view, and compact / minimal / expanded Dynamic Island views.
  • Sources/App/Settings/LiveActivity/LiveActivitySettingsView.swift — activity status, active list, privacy disclosure, and 11 debug scenarios for pre-server-side testing.

Modified files:

  • Widgets.swift — registers HALiveActivityConfiguration in all three WidgetBundle variants behind #available(iOSApplicationExtension 17.2, *)
  • NotificationsCommandManager.swift — registers new handlers; HandlerClearNotification now also ends a matching Live Activity when tag is present
  • HAAPI.swift — adds supports_live_activities, supports_live_activities_frequent_updates, live_activity_push_to_start_token, live_activity_push_to_start_apns_environment to registration payload under a single #available(iOS 17.2, *) check
  • AppDelegate.swift — reattaches surviving activities at launch and starts observing push-to-start tokens under a single #available(iOS 17.2, *) check
  • Info.plistNSSupportsLiveActivities + NSSupportsLiveActivitiesFrequentUpdates
  • SettingsItem.swift / SettingsView.swift — Live Activities settings row is gated behind Current.isTestFlight and shows a BetaLabel badge

Tests:

  • Unit Tests
    • 45 new tests (36 handler tests, 9 command manager routing tests). All 490 existing tests continue to pass.
  • Device Tests
    • I tried to test with my physical device, however I do not have a paid account. Turns out I could not deploy without disabling a lot of entitlements for compilation. Even so, once I did get it deployed and running Live Activities wouldn't show unless some of those settings that I disable were re-enable and leaving me in a particular spot.
    • I mainly tested with the simulator which is what is shown below

Screenshots

full-debug-scenarios

Link to pull request in Documentation repository

Documentation: home-assistant/companion.home-assistant#1303

Link to pull request in push relay repository

Relay server: home-assistant/mobile-apps-fcm-push#278

Link to pull request in HA core

Core: home-assistant/core#166072

Any other notes

iOS version gating at 17.2. The entire feature is gated at #available(iOS 17.2, *) — this is the minimum for push-to-start (the primary server-side start mechanism). A single availability check now covers all Live Activity APIs: supports_live_activities, frequentPushesEnabled, push-to-start token, and all ActivityKit usage. This eliminates the nested 16.2/17.2 check pattern.

Push-to-start (iOS 17.2+) is client-complete. The token is observed, stored in Keychain, and included in registration payloads. All companion server-side PRs are now open — relay server at home-assistant/mobile-apps-fcm-push#278 and HA core webhook handlers at home-assistant/core#166072. The relay server uses FCM's native apns.liveActivityToken support (Firebase Admin SDK v13.5.0+) — no custom APNs client or credentials needed.

Server-side work — all PRs now open:

Live Activities entry in Settings is gated behind TestFlight. The settings row only appears when Current.isTestFlight is true, preventing it from surfacing in a release build before the feature is fully tested. A BetaLabel badge is shown alongside the row title.

iPad: areActivitiesEnabled is always false on iPad — Apple system restriction. The Settings screen shows "Not available on iPad." The registry silently no-ops. HA receives supports_live_activities: false in the device registration for iPad.

HALiveActivityAttributes is frozen post-ship. The struct name appears as attributes-type in APNs push-to-start payloads. Renaming it silently breaks all remote starts. The ContentState CodingKeys are equally frozen — only additions are safe. Both have comments in the source calling this out.

The debug section in Settings is intentional. Gated behind #if DEBUG so it only appears in debug builds — it never ships to TestFlight or the App Store. It exercises the full ActivityKit lifecycle without requiring the server-side chain.

UNUserNotificationCenter in tests. The clear_notification + tag → Live Activity dismissal path is covered by code review rather than a unit test. HandlerClearNotification calls UNUserNotificationCenter.current().removeDeliveredNotifications synchronously, which requires a real app bundle and throws NSInternalInconsistencyException in the XCTest host. A comment in the test file explains this.

Rate limiting on iOS 18. Apple throttles Live Activity updates to ~15 seconds between renders. Automations should trigger on state change events, not polling timers.

Related:

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds ActivityKit-based Live Activities support to the Home Assistant iOS app, enabling notifications to start/update/end a Lock Screen/Dynamic Island Live Activity via homeassistant.command or homeassistant.live_activity payload fields, plus UI/settings and device registration support.

Changes:

  • Adds a Live Activity attributes model and an actor-based registry to manage activity lifecycle, push tokens, and dismissal reporting.
  • Extends notification command routing/handlers to start/update/end Live Activities (including clear_notification + tag dismissal).
  • Adds widget extension ActivityConfiguration UI, settings UI, localization strings, and new unit tests for routing/handlers.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
Tests/Shared/LiveActivity/NotificationsCommandManagerLiveActivityTests.swift Adds routing tests for live_activity, end_live_activity, and flag-based routing.
Tests/Shared/LiveActivity/MockLiveActivityRegistry.swift Provides a registry test double for handler/manager tests.
Tests/Shared/LiveActivity/HandlerLiveActivityTests.swift Adds validation/parsing/guard/dismissal-policy tests for the new handlers.
Sources/Shared/Settings/SettingsStore.swift Persists a “privacy disclosure seen” flag for Live Activities.
Sources/Shared/Resources/Swiftgen/Strings.swift Adds generated localization accessors for Live Activities settings strings.
Sources/Shared/Notifications/NotificationCommands/NotificationsCommandManager.swift Registers Live Activity commands and adds live_activity: true routing + clear_notification Live Activity end behavior.
Sources/Shared/Notifications/NotificationCommands/HandlerLiveActivity.swift Implements start/update and end handlers, including payload parsing and validation.
Sources/Shared/LiveActivity/LiveActivityRegistry.swift Adds an actor to manage activities, observe token/lifecycle streams, and report webhooks.
Sources/Shared/LiveActivity/HALiveActivityAttributes.swift Defines ActivityAttributes / ContentState wire model for Live Activities.
Sources/Shared/Environment/Environment.swift Adds apnsEnvironment helper and a lazily created liveActivityRegistry environment dependency.
Sources/Shared/API/HAAPI.swift Extends registration payload with Live Activities capability and token fields.
Sources/Extensions/Widgets/Widgets.swift Registers the Live Activity widget configuration in widget bundles with iOS 16.2 gating.
Sources/Extensions/Widgets/LiveActivity/HALockScreenView.swift Implements the Lock Screen/StandBy UI for the activity.
Sources/Extensions/Widgets/LiveActivity/HALiveActivityConfiguration.swift Adds ActivityConfiguration wrapper for the Live Activity widget.
Sources/Extensions/Widgets/LiveActivity/HADynamicIslandView.swift Implements Dynamic Island compact/minimal/expanded views.
Sources/App/Settings/Settings/SettingsItem.swift Adds Live Activities to Settings navigation and gates it behind iOS 16.2.
Sources/App/Settings/LiveActivity/LiveActivitySettingsView.swift Adds a settings screen for status, active activities list, privacy text, and debug scenarios.
Sources/App/Resources/en.lproj/Localizable.strings Adds English strings for Live Activities settings UI.
Sources/App/Resources/Info.plist Enables Live Activities + Frequent Updates support via Info.plist keys.
Sources/App/AppDelegate.swift Reattaches surviving activities at launch and starts observing push-to-start tokens (iOS 17.2+).
HomeAssistant.xcodeproj/project.pbxproj Adds new source files/groups and adjusts build settings (including a Widgets debug signing team).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

rwarner added a commit to rwarner/core that referenced this pull request Mar 20, 2026
Add support for iOS Live Activities in the mobile_app integration:

- Add `supports_live_activities`, `supports_live_activities_frequent_updates`,
  `live_activity_push_to_start_token`, and
  `live_activity_push_to_start_apns_environment` fields to SCHEMA_APP_DATA
  for explicit validation during device registration
- Add `update_live_activity_token` webhook handler: stores per-activity APNs
  push tokens reported by the iOS companion app when a Live Activity is
  created locally via ActivityKit
- Add `live_activity_dismissed` webhook handler: cleans up stored tokens when
  a Live Activity ends on the device
- Both handlers fire bus events so automations can react to activity lifecycle
- Add `supports_live_activities()` utility helper
- Add 4 tests covering token storage, default environment, dismissal cleanup,
  and nonexistent tag dismissal

for: home-assistant/mobile-apps-fcm-push#278
for: home-assistant/iOS#4444

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 23, 2026

tip for lint you can use bundle exec fastlane autocorrect

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 23, 2026

Can you make a screen recording showing the whole flow? Showing HA UI sending the push and iPhone handling it

@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 23, 2026

Can you make a screen recording showing the whole flow? Showing HA UI sending the push and iPhone handling it

So I don't have a paid Apple dev account so apparently the only way I could get it to compile to an actual device (to try to get push notifs) was to rip a bunch of entitlements out to compile for my physical device. For the emulator, I wasn't sure how to do a full-end-to-end test with the four repo changes altogether and run that locally. Theoretically it seemed like a possibility to do a local push to the emulated device but didn't get to that point.

Mainly why I created the debug options in the screenshot section showcasing all of the possibilities with the YAML at the moment. (This is in App Companion Settings -> Live Activity -> DEBUG options)

I don't mind putting some more stuff together, lemme know any specifics you would like to see and I can try. There's also more screenshots in the documentation repo here: home-assistant/companion.home-assistant#1303

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 23, 2026

Nowadays you can already test push notification on simulator as well from what I can remember, check this https://www.tiagohenriques.dev/blog/testing-push-notifications-ios-simulators

@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 23, 2026

Thanks, I'll look at this and see if I can produce some more examples for you / video on top of the previous gif

@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 23, 2026

Nowadays you can already test push notification on simulator as well from what I can remember, check this https://www.tiagohenriques.dev/blog/testing-push-notifications-ios-simulators

Thanks for the link! I looked into xcrun simctl push — from my testing, it delivers through UNUserNotificationCenter rather than ActivityKit's push token channel, so Live Activity payloads (event, content-state, etc.) arrive as regular notifications instead of updating the running activity. The simulator also returns nil for ActivityKit push tokens, so real APNs delivery to a Live Activity isn't possible either. Happy to be corrected if there's a way I'm missing!

For the local WebSocket path, the simulator is currently connecting through Nabu Casa (cloud relay), so notifications route through FCM rather than the local WebSocket channel. I'd need to be on the same local network as the HA instance for WebSocket-based delivery to work — I'll try to set that up.
Update: Would need a new Hass instance running my new core feature branch

In the meantime, I've added two screen recordings demonstrating start/update/end with various payload configurations on the simulator. The debug section in Settings also exercises all the UI states. As well as correcting the linting issues

Settings.Area.mp4
Debug.sample.mp4

@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 23, 2026

Progress with xcrun simctl actually, I was able to get a "push" to work using the following file and a small recent code change I just pushed

live_activity_test.apns

{
  "Simulator Target Bundle": "com.rwarner.ha.HomeAssistant.dev",
  "aps": {
    "alert": {
      "title": "Washing Machine",
      "body": "Cycle in progress"
    },
    "mutable-content": 1,
    "content-available": 1
  },
  "homeassistant": {
    "live_activity": true,
    "tag": "washer_cycle",
    "title": "Washing Machine",
    "message": "Cycle in progress",
    "progress": 2700,
    "progress_max": 3600,
    "chronometer": true,
    "when": 2700,
    "when_relative": true,
    "notification_icon": "mdi:washing-machine",
    "notification_icon_color": "#2196F3"
  }
}

xcrun simctl push booted com.rwarner.ha.HomeAssistant.dev /tmp/live_activity_test.apns

Which works while the application is in the foreground of the iPhone:

For some reason the dynamic island in the emulator is fussy but pops up very quickly
Screenshot 2026-03-23 at 3 38 23 PM

trimmed.mp4

Tests: push payload → NotificationCommandManager → HandlerStartOrUpdateLiveActivity → LiveActivityRegistry → ActivityKit → Lock Screen

However to test an actual background push Live Activity handler from what I can figure out I would need:

  • Local WebSocket — HA instance compiled with my core changes on same network
  • Real APNs — paid developer account
  • FCM — production Firebase project matching the bundle ID
  • ?Apple's Push Notification console in their paid dev area?

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 24, 2026

Local WebSocket — HA instance compiled with my core changes on same network

You have that already right? Because you opened a PR for core as well, so you can use that instance you used to test core to connect to the iOS App

@home-assistant home-assistant bot marked this pull request as draft March 24, 2026 10:15
@home-assistant
Copy link
Copy Markdown

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 37.56757% with 231 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@8a0f5b9). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...ces/Shared/LiveActivity/LiveActivityRegistry.swift 0.00% 198 Missing ⚠️
Sources/Shared/API/HAAPI.swift 28.57% 15 Missing ⚠️
Sources/Shared/Environment/Environment.swift 41.66% 7 Missing ⚠️
...Shared/LiveActivity/HALiveActivityAttributes.swift 60.00% 6 Missing ⚠️
...ficationCommands/NotificationsCommandManager.swift 76.19% 5 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4444   +/-   ##
=======================================
  Coverage        ?   42.49%           
=======================================
  Files           ?      270           
  Lines           ?    16012           
  Branches        ?        0           
=======================================
  Hits            ?     6804           
  Misses          ?     9208           
  Partials        ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 24, 2026

In your example we have 2 different tags, one for android and one for iOS:

    live_update: true           # Android 16+
    live_activity: true         # iOS 16.2+

Should we use the same as android has so the user does not need 2 different approaches based on platform? Are there more differences that we could merge into a single approach?

rwarner added a commit to rwarner/core that referenced this pull request Mar 24, 2026
Add support for iOS Live Activities in the mobile_app integration:

- Add `supports_live_activities`, `supports_live_activities_frequent_updates`,
  `live_activity_push_to_start_token`, and
  `live_activity_push_to_start_apns_environment` fields to SCHEMA_APP_DATA
  for explicit validation during device registration
- Add `update_live_activity_token` webhook handler: stores per-activity APNs
  push tokens reported by the iOS companion app when a Live Activity is
  created locally via ActivityKit
- Add `live_activity_dismissed` webhook handler: cleans up stored tokens when
  a Live Activity ends on the device
- Both handlers fire bus events so automations can react to activity lifecycle
- Add `supports_live_activities()` utility helper
- Add 4 tests covering token storage, default environment, dismissal cleanup,
  and nonexistent tag dismissal

for: home-assistant/mobile-apps-fcm-push#278
for: home-assistant/iOS#4444

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rwarner rwarner force-pushed the feat/live-activities branch from 8af7679 to c4ad13d Compare March 24, 2026 14:29
@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 24, 2026

Local WebSocket — HA instance compiled with my core changes on same network

You have that already right? Because you opened a PR for core as well, so you can use that instance you used to test core to connect to the iOS App

Correct yeah, I haven't stood up core before locally from the repo will take a stab and see if I can ping HASS Core directly from the localhost from the iPhone sim. Was just using my personal instance to try at first.


In your example we have 2 different tags, one for android and one for iOS:

    live_update: true           # Android 16+
    live_activity: true         # iOS 16.2+

Should we use the same as android has so the user does not need 2 different approaches based on platform? Are there more differences that we could merge into a single approach?

Great point actually. I can change this to just use the pre-existing live_update YAML that Android already uses and nobody has to make YAML additions / changes. (This would also require updating the other repos but honestly might be worth it)

Unless you think it would be handy to have the following example:

they might want a Live Activity on iOS but a regular sticky notification on Android (or vice versa).

But overall, the field names inside data (tag, progress, chronometer, etc.) are already unified across both platforms — it's only the opt-in trigger that's separate.


Responded to all comments and questions, updated suggested code changes and integrated requested tests.

rwarner and others added 3 commits March 25, 2026 09:53
Two bugs uncovered while testing Live Activities via local WebSocket push:

1. Use InterfaceDirect on Simulator — NEAppPushProvider (Network Extension)
   does not run in the Simulator, so the local push channel was never opened
   and notifications fell back to remote APNs/FCM which also fails on Simulator.

2. Promote live_activity fields into homeassistant payload in
   LegacyNotificationParserImpl — the WebSocket delivery path produces a flat
   payload where data.live_activity was never mapped into payload["homeassistant"].
   NotificationCommandManager checks payload["homeassistant"]["live_activity"],
   so Live Activity notifications arrived as regular banners instead of starting
   a Live Activity. This bug also affects real devices on a local/LAN connection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LiveActivityRegistry: silence AlertConfiguration sound on start (sound: nil)
  so the Dynamic Island bloom animation doesn't trigger an audible alert
- LiveActivityRegistry: track pending state for in-flight reservations so a
  second rapid push with the same tag applies its newer state on confirm
  instead of being silently dropped
- NotificationManager: willPresent now awaits handle() result before
  suppressing the banner; unknown commands fall back to normal presentation
  instead of being swallowed silently
- NotificationParserLegacy: only promote message to homeassistant dict when
  it is a String, preventing Optional("...") from leaking into the payload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… activities

- Use fixed frame(width: 44) for countdown timer in compact trailing slot
  instead of maxWidth: 50, preventing the Dynamic Island from squeezing
  the text narrower than M:SS requires
- Add contentTransition(.numericText(countsDown: true)) to all three timer
  Text views (compact trailing, expanded bottom, lock screen) for smooth
  digit animation
- Add computeStaleDate(for:) helper in LiveActivityRegistry: when chronometer
  is active, sets staleDate = countdownEnd + 2 s so the system marks the
  activity stale shortly after the timer ends rather than 30 min later;
  the +2 s offset also prevents the system spinner overlay that appears when
  staleDate == exactly countdownEnd
- Fix iOS 26 SDK breaking change: AlertConfiguration.sound is now non-optional,
  changed sound: nil to .default
- Handle new .pending ActivityState case added in iOS 26
- Fix NotificationCommandManager typo (was NotificationsCommandManager)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rwarner rwarner force-pushed the feat/live-activities branch from 4b3c244 to ed7e1f6 Compare March 25, 2026 13:53
@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 25, 2026

I had a feeling something was up with the dynamic island and the simulator. I went to work on another side project of mine and got it all working over there for the dynamic island and wanted to bring my findings over here. Now the dynamic island is working amazingly. I actually really like it. Just pushed up a rebase, some copilot fixes, and these dynamic island fixes. Here's some screenshots and a video of it in action (for each of the debug test buttons)

Untitled.mov

Irrigation
Screenshot 2026-03-25 at 9 23 40 AM
Screenshot 2026-03-25 at 9 23 54 AM


Alarm
Screenshot 2026-03-25 at 9 24 11 AM
Screenshot 2026-03-25 at 9 24 17 AM


All Fields
Screenshot 2026-03-25 at 9 24 36 AM
Screenshot 2026-03-25 at 9 24 47 AM


Laundry
Screenshot 2026-03-25 at 9 25 08 AM
Screenshot 2026-03-25 at 9 25 21 AM


EV Charging
Screenshot 2026-03-25 at 9 25 37 AM
Screenshot 2026-03-25 at 9 25 42 AM


Music
Screenshot 2026-03-25 at 9 26 11 AM
Screenshot 2026-03-25 at 9 26 16 AM


Shipments
Screenshot 2026-03-25 at 9 26 36 AM

Screenshot 2026-03-25 at 9 26 39 AM

Camera
Screenshot 2026-03-25 at 9 26 58 AM

rwarner and others added 2 commits March 25, 2026 13:38
@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 26, 2026

I'm manually testing the debug options you included and it looks great, I think we can improve the UI for the live activity itself in lock screen but this can be an iteration.

Can you add 2 things?
1 - Beta label to the live activities entry in settings (we have now a BetaLabel swiftUI view that you can reuse)
2 - Add a check Current.isTestFlight, to not let it slip into a release without we fully test it (after the PRs get merged)

Also have you checked how it behaves in macOS?

- Show BetaLabel next to Live Activities in settings (same as Kiosk)
- Gate Live Activities settings entry behind Current.isTestFlight to prevent it surfacing in a release build before fully tested

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 26, 2026

I'm manually testing the debug options you included and it looks great, I think we can improve the UI for the live activity itself in lock screen but this can be an iteration.

Awesome. Sounds good

Can you add 2 things? 1 - Beta label to the live activities entry in settings (we have now a BetaLabel swiftUI view that you can reuse) 2 - Add a check Current.isTestFlight, to not let it slip into a release without we fully test it (after the PRs get merged)

Added, let me know if this is right: ff65853

Also have you checked how it behaves in macOS?

I have not, not familiar with running this directly in macOS. Let me know what I should look at in regard to that.

Also, I know we still gotta decide about the differentiating flags between iOS/Android

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 26, 2026

I have not, not familiar with running this directly in macOS. Let me know what I should look at in regard to that.

Maybe I am confusing how mac live activities work, I think they only display the ones coming from your iPhone, anyway, your checks for "supports live activity" should be enough for now.

Also, I know we still gotta decide about the differentiating flags between iOS/Android

I missed where I commented about it but yes, I want android and iOS to have as minimum differences as possible, if one ignores tags that the other uses thats fine, but I dont want to duplicate tags that represent the same

…ivities

Unifies the iOS and Android notification data field: live_update: true now
triggers a Live Activity on iOS, matching the field Android already uses for
Live Updates. A single YAML automation now targets both platforms with no
platform-specific keys.

Internal command strings, webhook types, and keychain keys are unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 26, 2026

Maybe I am confusing how mac live activities work, I think they only display the ones coming from your iPhone, anyway, your checks for "supports live activity" should be enough for now.

No idea, not sure. Sounds good.

I missed where I commented about it but yes, I want android and iOS to have as minimum differences as possible, if one ignores tags that the other uses thats fine, but I dont want to duplicate tags that represent the same

No problem, has grown into a large PR here lol

  • Updated code for supporting live_update and removed live_activity for core, documentation, iOS
  • Updated related PR descriptions
  • Updated technical-brief.pdf

Let me know if we want to cutoff the feature for iOS 17+ rather than 16.2+ and I can do that too.

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 26, 2026

I see many checks for iOS 16.2 but since we can only start activities from server side (Home Assistant) on 17.2+, doesnt it make more sense to support starting on 17.2?

EDIT: I see my comment overlapped yours haha sorry, yes let's move for 17

Replaces all iOS 16.2 availability checks with iOS 17.2, flattens the
nested 16.2/17.2 blocks in AppDelegate and HAAPI into a single 17.2 check,
and removes now-redundant @available(iOS 17.2, *) method annotations from
the protocol and actor (the outer type annotation is sufficient).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Mar 26, 2026

Are you on discord? If so can you reach out to me, I want to have a quick chat about the full picture and If I understood your implementation correctly (bgoncal2)

@rwarner
Copy link
Copy Markdown
Author

rwarner commented Mar 26, 2026

  • Updated live activity minimum to 17.2
  • Updated the PRs descriptions for this new minimum
  • Regenerated technical-brief.pdf with this new minimum
  • Updated codebase for iOS and documentation for the new minimum

Yes I am, I'll reach out!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.

rwarner and others added 5 commits March 31, 2026 13:46
…ard, live_update test key

- isValidTag: replace CharacterSet.alphanumerics (Unicode-inclusive) with explicit
  ASCII character set to match the stated [a-zA-Z0-9_-] contract
- WidgetsBundle17: wrap HALiveActivityConfiguration() in #available(17.2) guard,
  matching WidgetsBundleLegacy — avoids availability error on iOS 17.0/17.1
- Tests: change live_activity flag to live_update to match production routing
  (NotificationsCommandManager routes on live_update, not live_activity)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cking

Per bgoncal review feedback: remove the Any? backing store workaround and
the @available annotation on the stored property. Move @available(iOS 17.2, *)
to individual protocol methods so LiveActivityRegistryProtocol can be referenced
without an availability guard, then store it as LiveActivityRegistryProtocol?
and return nil at runtime when on iOS < 17.2.

Update all call sites to optional-chain (?.); AppDelegate uses guard-let since
it already holds a non-nil reference after pre-warming inside #available(17.2).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restores the original single-line form to keep the diff focused on
Live Activities changes, per bgoncal review feedback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…me-assistant#4453)

This property was added in an earlier commit but main removed the TestFlight
gate for mTLS entirely (PR home-assistant#4453). Drop it to avoid a merge conflict and
align with the direction main took.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…iveActivities

BetaLabel was removed in main (home-assistant#4453). Resolve conflict by keeping LabsLabel()
for both .kiosk and .liveActivities entries in the settings list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment on lines +145 to +164
private var _liveActivityRegistryBacking: LiveActivityRegistryProtocol?

/// Call `_ = Current.liveActivityRegistry` on the main thread at launch (before any
/// background thread can access it) to avoid a lazy-init race between concurrent callers.
public var liveActivityRegistry: LiveActivityRegistryProtocol? {
get {
if let existing = _liveActivityRegistryBacking {
return existing
}
if #available(iOS 17.2, *) {
let registry = LiveActivityRegistry()
_liveActivityRegistryBacking = registry
return registry
}
return nil
}
set {
_liveActivityRegistryBacking = newValue
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need both? Based on your comment one lazy var would be enough right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants