LiveActivity
The LiveActivity API enables you to display real-time, dynamic information from your script on the Lock Screen and, where supported, in the Dynamic Island on iOS devices. It provides a structured interface to start, update, and end Live Activities, and observe their state throughout their lifecycle.
This document provides a complete guide to using the LiveActivity API in the Scripting app, including:
- Core concepts and lifecycle
- How to register a Live Activity UI
- How to start, update, and end Live Activities
- UI layout for Dynamic Island and Lock Screen
- Full TypeScript/TSX examples
- Detailed descriptions of every type and option
The API wraps Apple’s ActivityKit and brings it into the Scripting environment with a React-style UI building approach.
1. Understanding Live Activities
A Live Activity can appear in the following regions:
- Lock Screen
- Dynamic Island (iPhone 14 Pro and later)
- Banner-style presentation on devices without Dynamic Island
Live Activities are used for time-based and progress-based information, such as:
- Timers
- Fitness progress
- Delivery tracking
- Countdowns and reminders
- Real-time status updates
In Scripting, each Live Activity consists of:
- contentState (a JSON-serializable object that updates over time)
- UI Builder (a function that produces TSX UI for each state)
2. Live Activity State Types
3. LiveActivityDetail Type
Represents a summary of each active Live Activity.
4. Live Activity UI Types
4.1 LiveActivityUIProps
These regions correspond to ActivityKit’s UI areas:
4.2 Static Rendering and Component Limitations
A Live Activity builds the UI returned by its builder into a static snapshot. JavaScript does not keep running to regenerate views while the activity is displayed.
- Components such as
GeometryReader,ScrollViewReader,NamespaceReader, andEnvironmentValuesReaderare unsupported because they need to pass layout or environment information back to JavaScript during display to generate child views. Using these components may leave the corresponding content empty. - You can use components such as
HStack,VStack,Text, andImage, as well as custom function components and conditional rendering based oncontentState. Their content is determined when the snapshot is built. - Updating content through
activity.update(state)is still supported. The new state is passed to the registered builder to build a new UI snapshot; ActivityKit/WidgetKit controls when the display refreshes. Do not rely on timers, event callbacks, oruseStateinside the view to keep refreshing the UI.
5. Registering a Live Activity UI
Live Activities must be registered inside a standalone file such as live_activity.tsx.
6. Using a Live Activity in Your Script
BackgroundKeeper is global and needs no import. Import the UI components, hooks, types and Script from "scripting". Save this entry as index.tsx; the factory comes from live_activity.tsx above.
7. LiveActivity Class API Reference
7.1 start(contentState, options?)
Starts a Live Activity.
LiveActivityOptions
- staleDate: Timestamp(ms) or Date object at which the activity becomes stale
- relevanceScore: Determines which Live Activity is prioritized in the Dynamic Island
7.2 update(contentState, options?)
Pass a new JSON-serializable state to the builder to update the Live Activity's content. For example, await activity.update({ mins: 5 }) builds a UI snapshot using the new mins value. Static rendering does not disable this update capability; see section 4.2 for component limitations.
LiveActivityUpdateOptions
Alerts appear on Apple Watch when sending an update.
7.3 end(contentState, options?)
LiveActivityEndOptions
Rules for dismissal (seconds):
- Not provided: default system retention (up to 4 hours)
- <= 0: remove immediately
- > 0: remove after the specified interval
7.4 Reading Activity State
7.5 Listening for State Changes
Triggered when the Live Activity transitions between:
- active → stale
- active → ended
- ended → dismissed
7.6 Static Methods
8. UI Components for Expanded Layout
These components help structure the expanded Dynamic Island.
9. Best Practices
9.1 contentState must be JSON-serializable
The following are not allowed:
- Functions
- Date objects (must use timestamps)
- Class instances
- Non-serializable structures
9.2 Live Activity registration must be in a standalone file
This is required due to UI compilation and ActivityKit rules.
9.3 Live Activities survive script termination
If your script needs to keep running (e.g., timers), use:
10. Minimal Example
11. Notes
- Live Activity starts asynchronously. You need to wait for
startto returntruebefore callingupdateandend. - Live Activity cannot access documents and iCloud directories. If you want to access files or render images, you must save them to
FileManager.appGroupDocumentsDirectory. For example, to render an image, you save it toFileManager.appGroupDocumentsDirectory, then use<Image filePath={Path.join(FileManager.appGroupDocumentsDirectory, 'example.png')} />to render it. - Live Activity can access the Storage data shared with the app.
Empty Dynamic Island regions
Import EmptyView from scripting and supply <EmptyView /> for an intentionally empty slot. The current slots require view nodes; null and undefined are not supported replacements. This builder can be used with the LiveActivity creation example above.
Expanded region priority
All four LiveActivityUIExpanded components accept priority?: number. Higher priorities receive layout space first; default 0. Finite numbers, including zero and negative values, are accepted; invalid values fail the builder. This is a native region hint, independent of the general layoutPriority modifier. Custom AlarmLiveActivity uses the same components. Existing tint and margins remain unchanged.
Verify expanded layout, long/localized text, large Dynamic Type and VoiceOver on a Dynamic Island iPhone. iPad can verify builder data and supported lock-screen presentation, not expanded-island appearance.
