Primeros pasos
Copia un prompt de configuración con los pasos de instalación y la guía completa en markdown para este plugin.
Set up this Capacitor plugin in the project.
Use the package manager already used by the project.
Install these package(s): `@capgo/capacitor-live-activities`
Run the required Capacitor sync/update step after installation.
Read this markdown guide for the full setup steps: https://raw.githubusercontent.com/Cap-go/website/refs/heads/main/apps/docs/src/content/docs/docs/plugins/live-activities/getting-started.mdx
Use that guide for platform-specific steps, native file edits, permissions, config changes, imports, and usage setup.
If that guide references other docs pages, read them too.
Instalar
Sección titulada “Instalación”Puedes usar nuestro setup asistido por IA para instalar el plugin. Añade las skills de Capgo a tu herramienta de IA con el siguiente comando:
bunx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-pluginsLuego usa el siguiente prompt:
Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-live-activities` plugin in my project.Si prefieres la configuración manual, instala el plugin ejecutando estos comandos y sigue las instrucciones de cada plataforma:
bun add @capgo/capacitor-live-activitiesbunx cap syncInstalar y sincronizar el plugin no crea la interfaz nativa de Live Activity. ActivityKit requiere un Widget Extension que registre una configuración de Live Activity antes de que startActivity pueda mostrar algo.
Requisitos
Sección titulada “Requisitos”- Usa iOS 16.1 o superior tanto para el target de la app como para el Widget Extension.
- Prueba en un dispositivo iOS o un simulador compatible. La Dynamic Island solo aparece en modelos compatibles; otros dispositivos usan la presentación en la Lock Screen.
- Mantén los datos combinados (estáticos y dinámicos) de ActivityKit por debajo del límite de 4 KB de Apple.
1. Crea una Widget Extension
Sección titulada “1. Crear una extensión de widget”Abre el proyecto nativo de iOS:
bunx cap open iosLuego:
- Selecciona Archivo > Nuevo > Target.
- Añade una extensión de widget.
- Activar Incluir Live Activity.
- Desactivar Incluir el Intent de configuración a menos que la app también necesite un widget configurable.
- Asegúrate de que la extensión generada esté integrada en el target principal de la app.
La Widget Extension debe contener un ActivityConfiguration y registrarlo en su WidgetBundle. Debe proporcionar cada presentación de Live Activity requerida:
- Pantalla bloqueada
- Dynamic Island expandida
- Dynamic Island compacta (leading y trailing)
- Dynamic Island mínima
Añadir solo el target no es suficiente. La app nativa o el plugin deben llamar a las APIs request, update y end de ActivityKit. La extensión debe contener code de SwiftUI que puedan decodificar y renderizar el mismo ActivityAttributes y el estado de contenido usados en esas llamadas. Incluye modelos de ActivityKit compartidos tanto en el target de la app principal como en el de la Widget Extension. La plantilla de Live Activity generada por Xcode no renderiza automáticamente los layouts JSON pasados a este plugin; la extensión también necesita un renderer de layout nativo compatible.
2. Habilitar Live Activities
Sección titulada “2. Habilitar Live Activities”Añade la siguiente clave al target principal de la app Info.plist:
<key>NSSupportsLiveActivities</key><true/>Si el proyecto genera su Info.plist, añade Compatible con Live Activities con un valor booleano de YES en las propiedades del target personalizado de iOS de la app principal.
3. Configurar el App Group para imágenes compartidas
Sección titulada “3. Configurar el App Group para imágenes compartidas”Solo necesitas un App Group cuando usas saveImage, removeImage, listImages, o cleanupImages. El plugin deriva el identificador del App Group del bundle identifier de la app principal usando este formato exacto:
group.<MAIN_APP_BUNDLE_ID>.liveactivitiesPor ejemplo, una app con bundle identifier com.example.delivery debe usar:
group.com.example.delivery.liveactivitiesEn Xcode, añade la capability de App Groups tanto al target de la app principal como al target de la Widget Extension; luego, habilita el mismo identificador en ambos targets.
Las extensiones de Live Activity no pueden acceder a la red. Descarga las imágenes remotas en la app principal y guárdalas en el App Group compartido antes de usarlas en una Live Activity. Para imágenes locales, habilita también la Widget Extension en la target membership de los assets.
4. Configura deep links
Sección titulada “4. Configure Deep Links”Al usar behavior.widgetUrl o una secuencia de temporizadores tapUrl, registra el URL scheme o Universal Link correspondiente en la app principal. Para un scheme personalizado como myapp://order/12345, añade el scheme en la sección Info > Tipos de URL de configuración.
5. Opcional: activa Server-Driven Updates
Sección titulada “5. Opcional: Habilitar actualizaciones desde el servidor”Las notificaciones push no son necesarias para las actualizaciones locales iniciadas por la app. Para iniciar, actualizar o finalizar Live Activities desde un servidor:
- Añade la Notificaciones push capability al target de la app principal.
- Obtén los tokens de push de ActivityKit y envíalos al servidor.
- Envía notificaciones de ActivityKit a través de APNs usando el
liveactivitytipo push. - Añadir
NSSupportsLiveActivitiesFrequentUpdatesa la app principalInfo.plistsolo cuando el caso de uso requiera actualizaciones push frecuentes.
Los tokens de push de ActivityKit son distintos a los tokens de dispositivo para notificaciones estándar. Activar solo la capacidad de Push Notifications no es suficiente; las actualizaciones gestionadas por el servidor requieren el manejo de tokens nativos y un backend de APNs.
Checklist de configuración nativa
Sección titulada “Native Setup Checklist”Antes de llamar a startActivity, verifica que:
NSSupportsLiveActivitiesesté habilitado en el target de la app principal.- La Widget Extension está integrada y registra un
ActivityConfiguration. - La implementación nativa de ActivityKit y la Widget Extension usan el mismo
ActivityAttributestipo. - Los deployment targets de la app y de la Widget Extension son iOS 16.1 o posterior.
- Las Live Activities están habilitadas para la app en los Ajustes de iOS.
- El App Group correspondiente está habilitado en ambos targets al usar imágenes compartidas.
- Cualquier custom URL scheme utilizado por
widgetUrlotapUrlestá registrado.
Importar
Sección titulada “Importar”import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';Inicio rápido
Sección titulada “Inicio rápido”import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { supported, reason } = await CapgoLiveActivities.areActivitiesSupported();if (supported) { console.log('Live Activities are supported!');} else { console.log('Not supported:', reason);}Ejemplo: startActivity
Sección titulada “Ejemplo: startActivity”import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { activityId } = await CapgoLiveActivities.startActivity({ layout: { type: 'container', direction: 'horizontal', children: [ { type: 'text', content: 'Order #{{orderNumber}}', fontSize: 16, fontWeight: 'bold' }, { type: 'text', content: '{{status}}', fontSize: 14, color: '#666666' } ] }, dynamicIslandLayout: { expanded: { leading: { type: 'image', source: 'sfSymbol', value: 'box.truck' }, trailing: { type: 'text', content: '{{eta}}' }, center: { type: 'text', content: '{{status}}' }, bottom: { type: 'progress', value: 'progress' } }, compactLeading: { type: 'image', source: 'sfSymbol', value: 'box.truck' }, compactTrailing: { type: 'text', content: '{{eta}}' }, minimal: { type: 'image', source: 'sfSymbol', value: 'box.truck' } }, data: { orderNumber: '12345', status: 'On the way', eta: '10 min', progress: 0.6 }});console.log('Started activity:', activityId);Ejemplo: updateActivity
Sección titulada “Ejemplo: updateActivity”import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.updateActivity({ activityId: 'abc123', data: { status: 'Arrived!', eta: 'Now', progress: 1.0 }, alertConfiguration: { title: 'Delivery Update', body: 'Your order has arrived!' }});Errores comunes
Sección titulada “Errores comunes”- Listeners: elimina los handles cuando se desmonten las pantallas.
- Sync nativo: ejecuta
bunx cap synctras actualizar los plugins. - Fuente de verdad: confianza
src/definitions.tsen el repo de GitHub.
Resumen de API
Sección titulada “Resumen de API”areActivitiesSupported
Sección titulada “areActivitiesSupported”Comprueba si este dispositivo es compatible con Live Activities. Requiere iOS 16.1+ y que el dispositivo sea compatible.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { supported, reason } = await CapgoLiveActivities.areActivitiesSupported();if (supported) { console.log('Live Activities are supported!');} else { console.log('Not supported:', reason);}startActivity
Sección titulada “startActivity”Inicia una nueva Live Activity con el layout y los datos especificados.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { activityId } = await CapgoLiveActivities.startActivity({ layout: { type: 'container', direction: 'horizontal', children: [ { type: 'text', content: 'Order #{{orderNumber}}', fontSize: 16, fontWeight: 'bold' }, { type: 'text', content: '{{status}}', fontSize: 14, color: '#666666' } ] }, dynamicIslandLayout: { expanded: { leading: { type: 'image', source: 'sfSymbol', value: 'box.truck' }, trailing: { type: 'text', content: '{{eta}}' }, center: { type: 'text', content: '{{status}}' }, bottom: { type: 'progress', value: 'progress' } }, compactLeading: { type: 'image', source: 'sfSymbol', value: 'box.truck' }, compactTrailing: { type: 'text', content: '{{eta}}' }, minimal: { type: 'image', source: 'sfSymbol', value: 'box.truck' } }, data: { orderNumber: '12345', status: 'On the way', eta: '10 min', progress: 0.6 }});console.log('Started activity:', activityId);updateActivity
Sección titulada “updateActivity”Actualiza una Live Activity existente con nuevos datos.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.updateActivity({ activityId: 'abc123', data: { status: 'Arrived!', eta: 'Now', progress: 1.0 }, alertConfiguration: { title: 'Delivery Update', body: 'Your order has arrived!' }});endActivity
Sección titulada “endActivity”Finaliza una Live Activity.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.endActivity({ activityId: 'abc123', data: { status: 'Delivered' }, dismissalPolicy: 'after', dismissAfter: Date.now() + 3600000 // 1 hour from now});getAllActivities
Sección titulada “getAllActivities”Obtén todas las Live Activities activas actualmente.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { activities } = await CapgoLiveActivities.getAllActivities();activities.forEach(activity => { console.log(`Activity ${activity.activityId}: ${activity.state}`);});saveImage
Sección titulada “saveImage”Guarda una imagen en el contenedor compartido del App Group para usarla en Live Activities. Las imágenes deben guardarse en el contenedor compartido para que la extensión del widget pueda acceder a ellas.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { success, imageName } = await CapgoLiveActivities.saveImage({ imageData: 'base64EncodedImageData...', name: 'product-image', compressionQuality: 0.8});// Use in layout with: { type: 'image', source: 'saved', value: imageName }removeImage
Sección titulada “removeImage”Elimina una imagen guardada del contenedor compartido.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { success } = await CapgoLiveActivities.removeImage({ name: 'product-image' });listImages
Sección titulada “listImages”Lista todas las imágenes guardadas en el contenedor compartido.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { images } = await CapgoLiveActivities.listImages();console.log('Saved images:', images);cleanupImages
Sección titulada “cleanupImages”Elimina todas las imágenes guardadas del contenedor compartido.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.cleanupImages();startTimerSequence
Sección titulada “startTimerSequence”Inicia una secuencia de temporizador para entrenamientos o deportes. En iOS: Se muestra en Live Activity y Dynamic Island En Android: Se muestra como una notificación en primer plano con el temporizador
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const { sequenceId } = await CapgoLiveActivities.startTimerSequence({ title: 'HIIT Workout', steps: [ { duration: 30, title: 'Jumping Jacks', subtitle: 'Warm up', color: '#FF6B00', icon: 'figure.jumprope' }, { duration: 10, title: 'Rest', color: '#00C853', icon: 'pause.circle' }, { duration: 45, title: 'Burpees', subtitle: 'High intensity', color: '#FF0000', icon: 'flame.fill' }, { duration: 15, title: 'Rest', color: '#00C853', icon: 'pause.circle' }, { duration: 45, title: 'Mountain Climbers', color: '#FF0000', icon: 'figure.run' }, { duration: 15, title: 'Rest', color: '#00C853', icon: 'pause.circle' }, ], loop: true, loopCount: 3, soundEnabled: true, vibrateEnabled: true, countdownBeeps: true, tapUrl: 'myapp://workout/hiit'});pauseTimerSequence
Sección titulada “pauseTimerSequence”Pausa la secuencia del temporizador.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.pauseTimerSequence({ sequenceId: 'abc123' });resumeTimerSequence
Sección titulada “resumeTimerSequence”Reanuda una secuencia de temporizador pausada.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.resumeTimerSequence({ sequenceId: 'abc123' });stopTimerSequence
Sección titulada “stopTimerSequence”Detiene y descarta la secuencia del temporizador.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.stopTimerSequence({ sequenceId: 'abc123' });skipTimerStep
Sección titulada “skipTimerStep”Salta al siguiente paso de la secuencia.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.skipTimerStep({ sequenceId: 'abc123' });previousTimerStep
Sección titulada “previousTimerStep”Vuelve al paso anterior de la secuencia.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
await CapgoLiveActivities.previousTimerStep({ sequenceId: 'abc123' });getTimerState
Sección titulada “getTimerState”Obtén el estado actual de una secuencia de temporizador.
import { CapgoLiveActivities } from '@capgo/capacitor-live-activities';
const state = await CapgoLiveActivities.getTimerState({ sequenceId: 'abc123' });console.log(`Step ${state.currentStepIndex + 1}/${state.totalSteps}: ${state.currentStep.title}`);console.log(`Time remaining: ${state.remainingSeconds}s`);Referencia de tipos
Sección titulada “Referencia de tipos”AreActivitiesSupportedResult
Sección titulada “AreActivitiesSupportedResult”Resultado de comprobar si se admiten las actividades.
export interface AreActivitiesSupportedResult { /** Whether Live Activities are supported on this device */ supported: boolean; /** Reason if not supported */ reason?: string;}StartActivityOptions
Sección titulada “StartActivityOptions”Opciones para iniciar una Live Activity.
export interface StartActivityOptions { /** Main activity layout (lock screen widget) */ layout: ActivityLayout; /** Dynamic Island layout configuration */ dynamicIslandLayout: DynamicIslandLayout; /** Activity behavior settings */ behavior?: LiveActivitiesBehavior; /** Dynamic data for the activity */ data: Record<string, unknown>; /** Stale date timestamp (activity becomes stale after this) */ staleDate?: number; /** Relevance score for activity ordering (0-100) */ relevanceScore?: number;}StartActivityResult
Sección titulada “StartActivityResult”Resultado de iniciar una actividad.
export interface StartActivityResult { /** Unique activity identifier */ activityId: string;}UpdateActivityOptions
Sección titulada “UpdateActivityOptions”Opciones para actualizar una Live Activity.
export interface UpdateActivityOptions { /** Activity ID to update */ activityId: string; /** Updated data */ data: Record<string, unknown>; /** Optional alert to show with update */ alertConfiguration?: ActivityAlertConfiguration; /** Updated stale date */ staleDate?: number; /** Updated relevance score */ relevanceScore?: number;}EndActivityOptions
Sección titulada “EndActivityOptions”Opciones para finalizar una Live Activity.
export interface EndActivityOptions { /** Activity ID to end */ activityId: string; /** Final data to display */ data?: Record<string, unknown>; /** Dismissal policy */ dismissalPolicy?: 'immediate' | 'default' | 'after'; /** Dismiss after timestamp (when dismissalPolicy is 'after') */ dismissAfter?: number;}GetAllActivitiesResult
Sección titulada “GetAllActivitiesResult”Resultado de getAllActivities.
export interface GetAllActivitiesResult { /** List of activities */ activities: ActivityInfo[];}SaveImageOptions
Sección titulada “SaveImageOptions”Opciones para guardar una imagen.
export interface SaveImageOptions { /** Base64 encoded image data */ imageData: string; /** Name to save the image as */ name: string; /** JPEG compression quality (0-1, default 0.8) */ compressionQuality?: number;}SaveImageResult
Sección titulada “SaveImageResult”Resultado de guardar una imagen.
export interface SaveImageResult { /** Whether the save was successful */ success: boolean; /** Saved image name */ imageName: string;}RemoveImageOptions
Sección titulada “RemoveImageOptions”Opciones para eliminar una imagen.
export interface RemoveImageOptions { /** Name of the image to remove */ name: string;}RemoveImageResult
Sección titulada “RemoveImageResult”Resultado de eliminar una imagen.
export interface RemoveImageResult { /** Whether the removal was successful */ success: boolean;}ListImagesResult
Sección titulada “ListImagesResult”Resultado de listar las imágenes.
export interface ListImagesResult { /** List of saved image names */ images: string[];}TimerSequenceOptions
Sección titulada “TimerSequenceOptions”Opciones para iniciar una secuencia de temporizador.
export interface TimerSequenceOptions { /** Array of steps in the sequence */ steps: TimerStep[]; /** Overall title for the sequence (e.g., "HIIT Workout", "Tabata") */ title?: string; /** Whether to loop the sequence when complete */ loop?: boolean; /** Number of times to loop (if loop is true, 0 means infinite) */ loopCount?: number; /** Play sound on step change (default: true) */ soundEnabled?: boolean; /** Vibrate on step change (default: true) */ vibrateEnabled?: boolean; /** Play countdown beeps in last 3 seconds (default: true) */ countdownBeeps?: boolean; /** Deep link URL when tapping the notification/activity */ tapUrl?: string; /** Keep screen on during timer (Android only, default: false) */ keepScreenOn?: boolean;}Fuente de verdad
Sección titulada “Fuente de verdad”Esta página se genera a partir del plugin src/definitions.ts. Vuelve a ejecutar el sync cuando el API público cambie en upstream.
Continúa desde Getting Started
Sección titulada “Continúa desde Primeros pasos”Si estás usando Primeros pasos para planificar las operaciones del dashboard y de API, conéctalo con Uso de @capgo/capacitor-live-activities para la capacidad nativa en Uso de @capgo/capacitor-live-activities, Resumen de API para los detalles de implementación en API Overview, Introducción para los detalles de implementación en la Introducción, Claves de API para los detalles de implementación en las claves de API, y Dispositivos para el detalle de implementación en Devices.