Skip to content

Cap-go/capacitor-live-activities

Repository files navigation

@capgo/capacitor-live-activities

Capgo - Instant updates for Capacitor

Manage iOS Live Activities from Capacitor with a powerful JSON-based layout system.

Why Capacitor Live Activities?

  • iOS 16.1+ Live Activities - Full integration with Apple's Live Activities framework
  • Dynamic Island Support - Seamless integration with iPhone 14 Pro+ Dynamic Island
  • JSON Layout System - Build complex layouts declaratively without Swift code
  • Real-time Updates - Update your activities dynamically from your app
  • Image Management - Save and use images in your Live Activities via App Groups
  • Cross-platform Safe - Graceful fallbacks on Android and web

Essential for delivery tracking apps, sports scores, ride-sharing, timers, and any app needing real-time lock screen updates.

Documentation

The most complete doc is available here: https://capgo.app/docs/plugins/live-activities/

Compatibility

Plugin version Capacitor compatibility Maintained
v8.*.* v8.*.*
v7.*.* v7.*.* On demand
v6.*.* v6.*.*
v5.*.* v5.*.*

Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.

Install

bun add @capgo/capacitor-live-activities
bunx cap sync

Requirements

  • iOS 16.1+ - Live Activities require iOS 16.1 or later
  • Widget Extension - You must create a Widget Extension target in Xcode
  • App Groups - Required for sharing data between app and widget

iOS Setup

1. Create Widget Extension

In Xcode:

  1. File → New → Target
  2. Select "Widget Extension"
  3. Name it exactly: LiveActivities
  4. Uncheck "Include Configuration Intent"

2. Configure App Groups

  1. Select your main app target → Signing & Capabilities
  2. Add "App Groups" capability
  3. Create group: group.YOUR_BUNDLE_ID.liveactivities
  4. Add the same App Group to your Widget Extension target

3. Enable Live Activities in Info.plist

Add to your app's Info.plist:

<key>NSSupportsLiveActivities</key>
<true/>

4. Create the Widget Bundle

In your Widget Extension, create LiveActivitiesBundle.swift:

import WidgetKit
import SwiftUI

@main
struct LiveActivitiesBundle: WidgetBundle {
    var body: some Widget {
        // Your Live Activity widget goes here
        LiveActivityWidget()
    }
}

Usage Examples

Check Support

import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';

const checkSupport = async () => {
  const { supported, reason } = await CapgoLiveActivities.areActivitiesSupported();
  if (supported) {
    console.log('Live Activities are supported!');
  } else {
    console.log('Not supported:', reason);
  }
};

Start a Delivery Tracking Activity

import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';

const startDeliveryActivity = async () => {
  const { activityId } = await CapgoLiveActivities.startActivity({
    layout: {
      type: 'container',
      direction: 'vertical',
      spacing: 8,
      children: [
        {
          type: 'container',
          direction: 'horizontal',
          children: [
            { type: 'image', source: 'sfSymbol', value: 'box.truck.fill', width: 24, height: 24, tintColor: '#007AFF' },
            { type: 'text', content: 'Order #{{orderNumber}}', fontSize: 16, fontWeight: 'bold' }
          ]
        },
        { type: 'text', content: '{{status}}', fontSize: 14, color: '#666666' },
        { type: 'progress', value: 'progress', tint: '#34C759' }
      ]
    },
    dynamicIslandLayout: {
      expanded: {
        leading: { type: 'image', source: 'sfSymbol', value: 'box.truck.fill', tintColor: '#007AFF' },
        trailing: { type: 'text', content: '{{eta}}', fontWeight: 'semibold' },
        center: { type: 'text', content: '{{status}}', fontSize: 14 },
        bottom: { type: 'progress', value: 'progress', tint: '#34C759' }
      },
      compactLeading: { type: 'image', source: 'sfSymbol', value: 'box.truck.fill' },
      compactTrailing: { type: 'text', content: '{{eta}}' },
      minimal: { type: 'image', source: 'sfSymbol', value: 'box.truck.fill' }
    },
    behavior: {
      widgetUrl: 'myapp://order/12345'
    },
    data: {
      orderNumber: '12345',
      status: 'On the way',
      eta: '10 min',
      progress: 0.6
    }
  });

  console.log('Started activity:', activityId);
  return activityId;
};

Update an Activity

const updateActivity = async (activityId: string) => {
  await CapgoLiveActivities.updateActivity({
    activityId,
    data: {
      status: 'Arriving soon!',
      eta: '2 min',
      progress: 0.9
    },
    alertConfiguration: {
      title: 'Delivery Update',
      body: 'Your order is almost there!'
    }
  });
};

End an Activity

const endActivity = async (activityId: string) => {
  await CapgoLiveActivities.endActivity({
    activityId,
    data: {
      status: 'Delivered!',
      progress: 1.0
    },
    dismissalPolicy: 'after',
    dismissAfter: Date.now() + 3600000 // Keep visible for 1 hour
  });
};

Timer Example (Countdown)

const startTimerActivity = async () => {
  const targetDate = Date.now() + 1800000; // 30 minutes from now

  const { activityId } = await CapgoLiveActivities.startActivity({
    layout: {
      type: 'container',
      direction: 'horizontal',
      spacing: 16,
      children: [
        { type: 'image', source: 'sfSymbol', value: 'timer', width: 32, height: 32 },
        {
          type: 'container',
          direction: 'vertical',
          children: [
            { type: 'text', content: '{{title}}', fontSize: 16, fontWeight: 'bold' },
            { type: 'timer', targetDate: 'endTime', style: 'timer', fontSize: 24, fontWeight: 'bold', color: '#FF3B30' }
          ]
        }
      ]
    },
    dynamicIslandLayout: {
      expanded: {
        center: { type: 'text', content: '{{title}}' },
        bottom: { type: 'timer', targetDate: 'endTime', style: 'timer', fontSize: 32 }
      },
      compactLeading: { type: 'image', source: 'sfSymbol', value: 'timer' },
      compactTrailing: { type: 'timer', targetDate: 'endTime', style: 'timer' },
      minimal: { type: 'timer', targetDate: 'endTime', style: 'timer' }
    },
    data: {
      title: 'Cooking Timer',
      endTime: targetDate
    }
  });

  return activityId;
};

Using Saved Images

// Save an image first
const { imageName } = await CapgoLiveActivities.saveImage({
  imageData: 'base64EncodedImageData...',
  name: 'product-thumbnail',
  compressionQuality: 0.8
});

// Use in activity layout
const { activityId } = await CapgoLiveActivities.startActivity({
  layout: {
    type: 'container',
    direction: 'horizontal',
    children: [
      { type: 'image', source: 'saved', value: imageName, width: 48, height: 48, properties: { cornerRadius: 8 } },
      { type: 'text', content: '{{productName}}', fontSize: 16 }
    ]
  },
  // ... rest of config
});

// Cleanup when done
await CapgoLiveActivities.cleanupImages();

Layout Elements

Container

Groups child elements horizontally, vertically, or stacked.

{
  type: 'container',
  direction: 'horizontal' | 'vertical' | 'zstack',
  alignment: 'leading' | 'center' | 'trailing' | 'top' | 'bottom',
  spacing: 8,
  children: [/* ... */],
  properties: { padding: 12, backgroundColor: '#F5F5F5', cornerRadius: 8 }
}

Text

Displays text with styling and variable interpolation.

{
  type: 'text',
  content: 'Hello {{name}}!',
  fontSize: 16,
  fontWeight: 'bold',
  color: '#000000',
  alignment: 'center',
  lineLimit: 2,
  fontDesign: 'rounded'
}

Image

Displays images from various sources.

// SF Symbol
{ type: 'image', source: 'sfSymbol', value: 'star.fill', tintColor: '#FFD700' }

// URL
{ type: 'image', source: 'url', value: 'https://example.com/image.png', width: 48, height: 48 }

// Saved image
{ type: 'image', source: 'saved', value: 'my-saved-image' }

// Asset from bundle
{ type: 'image', source: 'asset', value: 'logo' }

Progress

Shows a progress bar.

{
  type: 'progress',
  value: 'progressValue', // Key in data object (0-1)
  tint: '#34C759'
}

Timer

Displays a countdown or elapsed time.

{
  type: 'timer',
  targetDate: 'endTime', // Key in data object (timestamp)
  style: 'timer' | 'relative' | 'offset',
  fontSize: 24,
  color: '#FF3B30',
  pausesOnReach: true
}

Gauge

Circular progress indicator.

{
  type: 'gauge',
  value: 'level', // Key in data (0-1)
  style: 'accessoryCircular',
  label: 'Battery',
  tint: '#34C759'
}

Spacer

Flexible space between elements.

{ type: 'spacer', minLength: 8 }

API

Capacitor Live Activities Plugin interface for managing iOS Live Activities.

areActivitiesSupported()

areActivitiesSupported() => Promise<AreActivitiesSupportedResult>

Check if Live Activities are supported on this device. Requires iOS 16.1+ and device support.

Returns: Promise<AreActivitiesSupportedResult>

Since: 1.0.0


startActivity(...)

startActivity(options: StartActivityOptions) => Promise<StartActivityResult>

Start a new Live Activity with the specified layout and data.

Param Type Description
options StartActivityOptions - Options for starting the activity

Returns: Promise<StartActivityResult>

Since: 1.0.0


updateActivity(...)

updateActivity(options: UpdateActivityOptions) => Promise<void>

Update an existing Live Activity with new data.

Param Type Description
options UpdateActivityOptions - Options for updating the activity

Since: 1.0.0


endActivity(...)

endActivity(options: EndActivityOptions) => Promise<void>

End a Live Activity.

Param Type Description
options EndActivityOptions - Options for ending the activity

Since: 1.0.0


getAllActivities()

getAllActivities() => Promise<GetAllActivitiesResult>

Get all currently active Live Activities.

Returns: Promise<GetAllActivitiesResult>

Since: 1.0.0


saveImage(...)

saveImage(options: SaveImageOptions) => Promise<SaveImageResult>

Save an image to the shared App Group container for use in Live Activities. Images must be saved to the shared container to be accessible from the widget extension.

Param Type Description
options SaveImageOptions - Options for saving the image

Returns: Promise<SaveImageResult>

Since: 1.0.0


removeImage(...)

removeImage(options: RemoveImageOptions) => Promise<RemoveImageResult>

Remove a saved image from the shared container.

Param Type Description
options RemoveImageOptions - Options for removing the image

Returns: Promise<RemoveImageResult>

Since: 1.0.0


listImages()

listImages() => Promise<ListImagesResult>

List all saved images in the shared container.

Returns: Promise<ListImagesResult>

Since: 1.0.0


cleanupImages()

cleanupImages() => Promise<void>

Remove all saved images from the shared container.

Since: 1.0.0


getPluginVersion()

getPluginVersion() => Promise<{ version: string; }>

Get the native Capacitor plugin version.

Returns: Promise<{ version: string; }>

Since: 1.0.0


startTimerSequence(...)

startTimerSequence(options: TimerSequenceOptions) => Promise<TimerSequenceResult>

Start a timer sequence for workouts/sports. On iOS: Shows in Live Activity and Dynamic Island On Android: Shows as a foreground notification with timer

Param Type Description
options TimerSequenceOptions - Timer sequence configuration

Returns: Promise<TimerSequenceResult>

Since: 1.0.0


pauseTimerSequence(...)

pauseTimerSequence(options: { sequenceId: string; }) => Promise<void>

Pause the timer sequence.

Param Type Description
options { sequenceId: string; } - Options containing the sequence ID

Since: 1.0.0


resumeTimerSequence(...)

resumeTimerSequence(options: { sequenceId: string; }) => Promise<void>

Resume a paused timer sequence.

Param Type Description
options { sequenceId: string; } - Options containing the sequence ID

Since: 1.0.0


stopTimerSequence(...)

stopTimerSequence(options: { sequenceId: string; }) => Promise<void>

Stop and dismiss the timer sequence.

Param Type Description
options { sequenceId: string; } - Options containing the sequence ID

Since: 1.0.0


skipTimerStep(...)

skipTimerStep(options: { sequenceId: string; }) => Promise<void>

Skip to the next step in the sequence.

Param Type Description
options { sequenceId: string; } - Options containing the sequence ID

Since: 1.0.0


previousTimerStep(...)

previousTimerStep(options: { sequenceId: string; }) => Promise<void>

Go back to the previous step in the sequence.

Param Type Description
options { sequenceId: string; } - Options containing the sequence ID

Since: 1.0.0


getTimerState(...)

getTimerState(options: GetTimerStateOptions) => Promise<TimerSequenceState>

Get the current state of a timer sequence.

Param Type Description
options GetTimerStateOptions - Options containing the sequence ID

Returns: Promise<TimerSequenceState>

Since: 1.0.0


addListener('timerSequenceEvent', ...)

addListener(eventName: 'timerSequenceEvent', callback: TimerSequenceCallback) => Promise<{ remove: () => Promise<void>; }>

Add a listener for timer sequence events. Events include: stepChange, complete, tick, paused, resumed, stopped, loopComplete

Param Type Description
eventName 'timerSequenceEvent' - The event name to listen for
callback TimerSequenceCallback - Callback function that receives the event

Returns: Promise<{ remove: () => Promise<void>; }>

Since: 1.0.0


Interfaces

AreActivitiesSupportedResult

Result of checking if activities are supported

Prop Type Description
supported boolean Whether Live Activities are supported on this device
reason string Reason if not supported

StartActivityResult

Result of starting an activity

Prop Type Description
activityId string Unique activity identifier

StartActivityOptions

Options for starting a Live Activity

Prop Type Description
layout ActivityLayout Main activity layout (lock screen widget)
dynamicIslandLayout DynamicIslandLayout Dynamic Island layout configuration
behavior LiveActivitiesBehavior Activity behavior settings
data Record<string, unknown> Dynamic data for the activity
staleDate number Stale date timestamp (activity becomes stale after this)
relevanceScore number Relevance score for activity ordering (0-100)

LayoutElementContainer

Container layout element for grouping child elements

Prop Type Description
type 'container'
direction 'horizontal' | 'vertical' | 'zstack' Layout direction
children LayoutElement[] Child elements
alignment 'leading' | 'center' | 'trailing' | 'top' | 'bottom' Alignment within container
spacing number Spacing between children
properties BaseLayoutProperties Container properties

BaseLayoutProperties

Base layout element properties

Prop Type Description
padding number | { top?: number; bottom?: number; leading?: number; trailing?: number; } Padding around the element
backgroundColor ColorString Background color
cornerRadius number Corner radius
width number | 'infinity' Frame width
height number Frame height
opacity number Opacity (0-1)

LayoutElementText

Text layout element

Prop Type Description
type 'text'
content string Text content - supports {{variable}} interpolation
fontSize number Font size
fontWeight 'ultraLight' | 'thin' | 'light' | 'regular' | 'medium' | 'semibold' | 'bold' | 'heavy' | 'black' Font weight
color ColorString Text color
alignment 'leading' | 'center' | 'trailing' Text alignment
lineLimit number Line limit
fontDesign 'default' | 'monospaced' | 'rounded' | 'serif' Font design
properties BaseLayoutProperties Element properties

LayoutElementImage

Image layout element

Prop Type Description
type 'image'
source 'url' | 'sfSymbol' | 'asset' | 'base64' | 'saved' Image source type
value string Image value (URL, symbol name, asset name, base64 string, or saved image name)
width number Image width
height number Image height
contentMode 'fit' | 'fill' Content mode
tintColor ColorString Tint color for SF Symbols
properties BaseLayoutProperties Element properties

LayoutElementProgress

Progress bar layout element

Prop Type Description
type 'progress'
value string | number Progress value key in data (0-1) or direct value
total string | number Total value key in data or direct value
tint ColorString Progress bar color
properties BaseLayoutProperties Element properties

LayoutElementTimer

Timer layout element for countdowns

Prop Type Description
type 'timer'
targetDate string | number Target date key in data or timestamp
style 'timer' | 'relative' | 'offset' Timer style
pausesOnReach boolean Pause when target reached
fontSize number Font size
color ColorString Text color
fontWeight 'ultraLight' | 'thin' | 'light' | 'regular' | 'medium' | 'semibold' | 'bold' | 'heavy' | 'black' Font weight
properties BaseLayoutProperties Element properties

LayoutElementSpacer

Spacer layout element

Prop Type Description
type 'spacer'
minLength number Minimum length

LayoutElementGauge

Gauge layout element for circular progress

Prop Type Description
type 'gauge'
value string | number Current value key in data or direct value (0-1)
style 'automatic' | 'accessoryCircular' | 'accessoryCircularCapacity' | 'linearCapacity' Gauge style
label string Label text
currentValueLabel string Current value label
minimumValueLabel string Minimum value label
maximumValueLabel string Maximum value label
tint ColorString Tint color
properties BaseLayoutProperties Element properties

DynamicIslandLayout

Dynamic Island layout configuration

Prop Type Description
expanded DynamicIslandExpandedLayout Expanded state layout
compactLeading LayoutElement Compact leading content
compactTrailing LayoutElement Compact trailing content
minimal LayoutElement Minimal presentation content

DynamicIslandExpandedLayout

Dynamic Island expanded layout configuration

Prop Type Description
leading LayoutElement Leading region content
trailing LayoutElement Trailing region content
center LayoutElement Center region content
bottom LayoutElement Bottom region content

LiveActivitiesBehavior

Live Activity behavior configuration

Prop Type Description
widgetUrl string Widget URL for deep linking
backgroundTint ColorString Background tint color
systemActionForegroundColor ColorString System action foreground color
keyLineTint ColorString Key line tint color

UpdateActivityOptions

Options for updating a Live Activity

Prop Type Description
activityId string Activity ID to update
data Record<string, unknown> Updated data
alertConfiguration ActivityAlertConfiguration Optional alert to show with update
staleDate number Updated stale date
relevanceScore number Updated relevance score

ActivityAlertConfiguration

Alert configuration for activity updates

Prop Type Description
title string Alert title
body string Alert body
sound string Sound name (optional)

EndActivityOptions

Options for ending a Live Activity

Prop Type Description
activityId string Activity ID to end
data Record<string, unknown> Final data to display
dismissalPolicy 'default' | 'immediate' | 'after' Dismissal policy
dismissAfter number Dismiss after timestamp (when dismissalPolicy is 'after')

GetAllActivitiesResult

Result of getAllActivities

Prop Type Description
activities ActivityInfo[] List of activities

ActivityInfo

Activity info returned from getAllActivities

Prop Type Description
activityId string Activity ID
state 'active' | 'ended' | 'dismissed' | 'stale' Current activity state
startDate number Activity start date
data Record<string, unknown> Current data

SaveImageResult

Result of saving an image

Prop Type Description
success boolean Whether the save was successful
imageName string Saved image name

SaveImageOptions

Options for saving an image

Prop Type Description
imageData string Base64 encoded image data
name string Name to save the image as
compressionQuality number JPEG compression quality (0-1, default 0.8)

RemoveImageResult

Result of removing an image

Prop Type Description
success boolean Whether the removal was successful

RemoveImageOptions

Options for removing an image

Prop Type Description
name string Name of the image to remove

ListImagesResult

Result of listing images

Prop Type Description
images string[] List of saved image names

TimerSequenceResult

Result of starting a timer sequence

Prop Type Description
sequenceId string Unique sequence identifier

TimerSequenceOptions

Options for starting a timer sequence

Prop Type Description
steps TimerStep[] Array of steps in the sequence
title string Overall title for the sequence (e.g., "HIIT Workout", "Tabata")
loop boolean Whether to loop the sequence when complete
loopCount number Number of times to loop (if loop is true, 0 means infinite)
soundEnabled boolean Play sound on step change (default: true)
vibrateEnabled boolean Vibrate on step change (default: true)
countdownBeeps boolean Play countdown beeps in last 3 seconds (default: true)
tapUrl string Deep link URL when tapping the notification/activity
keepScreenOn boolean Keep screen on during timer (Android only, default: false)

TimerStep

A single step in a timer sequence (e.g., workout interval)

Prop Type Description
duration number Duration of this step in seconds
title string Title/instruction for this step (e.g., "Push-ups", "Rest")
subtitle string Optional subtitle (e.g., "20 reps", "High intensity")
color string Color for this step (hex color, e.g., "#FF0000" for work, "#00FF00" for rest)
icon string Optional icon (SF Symbol name on iOS, material icon name on Android)
sound 'beep' | 'bell' | 'whistle' | 'countdown' | 'none' Optional sound to play when step starts

TimerSequenceState

Current state of a timer sequence

Prop Type Description
sequenceId string Sequence ID
isRunning boolean Whether the sequence is running
isPaused boolean Whether the sequence is paused
isComplete boolean Whether the sequence is complete
currentStepIndex number Current step index (0-based)
totalSteps number Total number of steps
currentStep TimerStep Current step info
remainingSeconds number Remaining seconds in current step
totalRemainingSeconds number Total remaining seconds for entire sequence
elapsedSeconds number Total elapsed seconds
currentLoop number Current loop iteration (1-based, if looping)
totalLoops number Total loops (0 if infinite or not looping)

GetTimerStateOptions

Options for getting timer state

Prop Type Description
sequenceId string Sequence ID to get state for

TimerSequenceEvent

Event data for timer sequence events

Prop Type Description
type 'stepChange' | 'complete' | 'tick' | 'paused' | 'resumed' | 'stopped' | 'loopComplete' Event type
sequenceId string Sequence ID
state TimerSequenceState Current state when event occurred

Type Aliases

ActivityLayout

Layout for the main activity view (lock screen widget)

LayoutElement

LayoutElement

Union type for all layout elements

LayoutElementContainer | LayoutElementText | LayoutElementImage | LayoutElementProgress | LayoutElementTimer | LayoutElementSpacer | LayoutElementGauge

ColorString

Color string type - supports hex colors and system colors

string

Record

Construct a type with a set of properties K of type T

{ [P in K]: T; }

TimerSequenceCallback

Callback type for timer sequence events

(event: TimerSequenceEvent): void

Credits

Inspired by ludufre/capacitor-live-activities with a simplified API and Capgo integration.

About

Manage iOS Live Activities from Capacitor

Topics

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors